Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(65)

Side by Side Diff: src/client/linux/minidump_writer/linux_dumper.cc

Issue 543125: Port linux_syscall_support and linux_dumper to support Linux ARM. Unit tests... (Closed) Base URL: http://google-breakpad.googlecode.com/svn/trunk/
Patch Set: '' Created 10 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2009, Google Inc. 1 // Copyright (c) 2009, Google Inc.
2 // All rights reserved. 2 // All rights reserved.
3 // 3 //
4 // Redistribution and use in source and binary forms, with or without 4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are 5 // modification, are permitted provided that the following conditions are
6 // met: 6 // met:
7 // 7 //
8 // * Redistributions of source code must retain the above copyright 8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer. 9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above 10 // * Redistributions in binary form must reproduce the above
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
73 73
74 // Resume a thread by detaching from it. 74 // Resume a thread by detaching from it.
75 static bool ResumeThread(pid_t pid) { 75 static bool ResumeThread(pid_t pid) {
76 return sys_ptrace(PTRACE_DETACH, pid, NULL, NULL) >= 0; 76 return sys_ptrace(PTRACE_DETACH, pid, NULL, NULL) >= 0;
77 } 77 }
78 78
79 namespace google_breakpad { 79 namespace google_breakpad {
80 80
81 LinuxDumper::LinuxDumper(int pid) 81 LinuxDumper::LinuxDumper(int pid)
82 : pid_(pid), 82 : pid_(pid),
83 threads_suspened_(false), 83 threads_suspended_(false),
84 threads_(&allocator_, 8), 84 threads_(&allocator_, 8),
85 mappings_(&allocator_) { 85 mappings_(&allocator_) {
86 } 86 }
87 87
88 bool LinuxDumper::Init() { 88 bool LinuxDumper::Init() {
89 return EnumerateThreads(&threads_) && 89 return EnumerateThreads(&threads_) &&
90 EnumerateMappings(&mappings_); 90 EnumerateMappings(&mappings_);
91 } 91 }
92 92
93 bool LinuxDumper::ThreadsSuspend() { 93 bool LinuxDumper::ThreadsSuspend() {
94 if (threads_suspened_) 94 if (threads_suspended_)
95 return true; 95 return true;
96 bool good = true; 96 bool good = true;
97 for (size_t i = 0; i < threads_.size(); ++i) 97 for (size_t i = 0; i < threads_.size(); ++i)
98 good &= SuspendThread(threads_[i]); 98 good &= SuspendThread(threads_[i]);
99 threads_suspened_ = true; 99 threads_suspended_ = true;
100 return good; 100 return good;
101 } 101 }
102 102
103 bool LinuxDumper::ThreadsResume() { 103 bool LinuxDumper::ThreadsResume() {
104 if (!threads_suspened_) 104 if (!threads_suspended_)
105 return false; 105 return false;
106 bool good = true; 106 bool good = true;
107 for (size_t i = 0; i < threads_.size(); ++i) 107 for (size_t i = 0; i < threads_.size(); ++i)
108 good &= ResumeThread(threads_[i]); 108 good &= ResumeThread(threads_[i]);
109 threads_suspened_ = false; 109 threads_suspended_ = false;
110 return good; 110 return good;
111 } 111 }
112 112
113 void 113 void
114 LinuxDumper::BuildProcPath(char* path, pid_t pid, const char* node) const { 114 LinuxDumper::BuildProcPath(char* path, pid_t pid, const char* node) const {
115 assert(path); 115 assert(path);
116 if (!path) { 116 if (!path) {
117 return; 117 return;
118 } 118 }
119 119
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
273 } 273 }
274 } 274 }
275 dir_reader->PopEntry(); 275 dir_reader->PopEntry();
276 } 276 }
277 277
278 sys_close(fd); 278 sys_close(fd);
279 return true; 279 return true;
280 } 280 }
281 281
282 // Read thread info from /proc/$pid/status. 282 // Read thread info from /proc/$pid/status.
283 // Fill out the |tgid|, |ppid| and |pid| members of |info|. If unavailible, 283 // Fill out the |tgid|, |ppid| and |pid| members of |info|. If unavailable,
284 // these members are set to -1. Returns true iff all three members are 284 // these members are set to -1. Returns true iff all three members are
285 // availible. 285 // available.
286 bool LinuxDumper::ThreadInfoGet(pid_t tid, ThreadInfo* info) { 286 bool LinuxDumper::ThreadInfoGet(pid_t tid, ThreadInfo* info) {
287 assert(info != NULL); 287 assert(info != NULL);
288 char status_path[80]; 288 char status_path[80];
289 BuildProcPath(status_path, tid, "status"); 289 BuildProcPath(status_path, tid, "status");
290 290
291 const int fd = open(status_path, O_RDONLY); 291 const int fd = open(status_path, O_RDONLY);
292 if (fd < 0) 292 if (fd < 0)
293 return false; 293 return false;
294 294
295 LineReader* const line_reader = new(allocator_) LineReader(fd); 295 LineReader* const line_reader = new(allocator_) LineReader(fd);
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
330 return false; 330 return false;
331 } 331 }
332 } 332 }
333 #endif 333 #endif
334 334
335 const uint8_t* stack_pointer; 335 const uint8_t* stack_pointer;
336 #if defined(__i386) 336 #if defined(__i386)
337 memcpy(&stack_pointer, &info->regs.esp, sizeof(info->regs.esp)); 337 memcpy(&stack_pointer, &info->regs.esp, sizeof(info->regs.esp));
338 #elif defined(__x86_64) 338 #elif defined(__x86_64)
339 memcpy(&stack_pointer, &info->regs.rsp, sizeof(info->regs.rsp)); 339 memcpy(&stack_pointer, &info->regs.rsp, sizeof(info->regs.rsp));
340 #elif defined(__ARM_EABI__)
341 memcpy(&stack_pointer, &info->regs.uregs[R13], sizeof(info->regs.uregs[R13]));
340 #else 342 #else
341 #error "This code hasn't been ported to your platform yet." 343 #error "This code hasn't been ported to your platform yet."
342 #endif 344 #endif
343 345
344 if (!GetStackInfo(&info->stack, &info->stack_len, 346 if (!GetStackInfo(&info->stack, &info->stack_len,
345 (uintptr_t) stack_pointer)) 347 (uintptr_t) stack_pointer))
346 return false; 348 return false;
347 349
348 return true; 350 return true;
349 } 351 }
350 352
351 // Get information about the stack, given the stack pointer. We don't try to 353 // Get information about the stack, given the stack pointer. We don't try to
352 // walk the stack since we might not have all the information needed to do 354 // walk the stack since we might not have all the information needed to do
353 // unwind. So we just grab, up to, 32k of stack. 355 // unwind. So we just grab, up to, 32k of stack.
354 bool LinuxDumper::GetStackInfo(const void** stack, size_t* stack_len, 356 bool LinuxDumper::GetStackInfo(const void** stack, size_t* stack_len,
355 uintptr_t int_stack_pointer) { 357 uintptr_t int_stack_pointer) {
356 #if defined(__i386) || defined(__x86_64)
357 static const bool stack_grows_down = true;
358 static const uintptr_t page_size = 4096;
359 #else
360 #error "This code has not been ported to your platform yet."
361 #endif
362 // Move the stack pointer to the bottom of the page that it's in. 358 // Move the stack pointer to the bottom of the page that it's in.
359 const uintptr_t page_size = getpagesize();
360
363 uint8_t* const stack_pointer = 361 uint8_t* const stack_pointer =
364 reinterpret_cast<uint8_t*>(int_stack_pointer & ~(page_size - 1)); 362 reinterpret_cast<uint8_t*>(int_stack_pointer & ~(page_size - 1));
365 363
366 // The number of bytes of stack which we try to capture. 364 // The number of bytes of stack which we try to capture.
367 static unsigned kStackToCapture = 32 * 1024; 365 static int kStackToCapture = 32 * 1024;
368 366
369 const MappingInfo* mapping = FindMapping(stack_pointer); 367 const MappingInfo* mapping = FindMapping(stack_pointer);
370 if (!mapping) 368 if (!mapping)
371 return false; 369 return false;
372 if (stack_grows_down) { 370 const ptrdiff_t offset = stack_pointer - (uint8_t*) mapping->start_addr;
awong 2010/02/08 20:52:55 so...we're assuming a single stack direction now?
373 const ptrdiff_t offset = stack_pointer - (uint8_t*) mapping->start_addr; 371 const ptrdiff_t distance_to_end =
374 const ptrdiff_t distance_to_end = 372 static_cast<ptrdiff_t>(mapping->size) - offset;
375 static_cast<ptrdiff_t>(mapping->size) - offset; 373 *stack_len = distance_to_end > kStackToCapture ?
376 *stack_len = distance_to_end > kStackToCapture ? 374 kStackToCapture : distance_to_end;
377 kStackToCapture : distance_to_end; 375 *stack = stack_pointer;
378 *stack = stack_pointer;
379 } else {
380 const ptrdiff_t offset = stack_pointer - (uint8_t*) mapping->start_addr;
381 *stack_len = offset > kStackToCapture ? kStackToCapture : offset;
382 *stack = stack_pointer - *stack_len;
383 }
384
385 return true; 376 return true;
386 } 377 }
387 378
388 // static 379 // static
389 void LinuxDumper::CopyFromProcess(void* dest, pid_t child, const void* src, 380 void LinuxDumper::CopyFromProcess(void* dest, pid_t child, const void* src,
390 size_t length) { 381 size_t length) {
391 unsigned long tmp; 382 unsigned long tmp = 55;
awong 2010/02/08 20:52:55 Magic number alert! What's this number for?
392 size_t done = 0; 383 size_t done = 0;
393 static const size_t word_size = sizeof(tmp); 384 static const size_t word_size = sizeof(tmp);
394 uint8_t* const local = (uint8_t*) dest; 385 uint8_t* const local = (uint8_t*) dest;
395 uint8_t* const remote = (uint8_t*) src; 386 uint8_t* const remote = (uint8_t*) src;
396 387
397 while (done < length) { 388 while (done < length) {
398 const size_t l = length - done > word_size ? word_size : length - done; 389 const size_t l = length - done > word_size ? word_size : length - done;
399 if (sys_ptrace(PTRACE_PEEKDATA, child, remote + done, &tmp) == -1) 390 if (sys_ptrace(PTRACE_PEEKDATA, child, remote + done, &tmp) == -1) {
400 tmp = 0; 391 tmp = 0;
392 }
401 memcpy(local + done, &tmp, l); 393 memcpy(local + done, &tmp, l);
402 done += l; 394 done += l;
403 } 395 }
404 } 396 }
405 397
406 // Find the mapping which the given memory address falls in. 398 // Find the mapping which the given memory address falls in.
407 const MappingInfo* LinuxDumper::FindMapping(const void* address) const { 399 const MappingInfo* LinuxDumper::FindMapping(const void* address) const {
408 const uintptr_t addr = (uintptr_t) address; 400 const uintptr_t addr = (uintptr_t) address;
409 401
410 for (size_t i = 0; i < mappings_.size(); ++i) { 402 for (size_t i = 0; i < mappings_.size(); ++i) {
411 const uintptr_t start = static_cast<uintptr_t>(mappings_[i]->start_addr); 403 const uintptr_t start = static_cast<uintptr_t>(mappings_[i]->start_addr);
412 if (addr >= start && addr - start < mappings_[i]->size) 404 if (addr >= start && addr - start < mappings_[i]->size)
413 return mappings_[i]; 405 return mappings_[i];
414 } 406 }
415 407
416 return NULL; 408 return NULL;
417 } 409 }
418 410
419 } // namespace google_breakpad 411 } // namespace google_breakpad
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698