LEFT | RIGHT |
1 // Copyright (c) 2010, Google Inc. | 1 // Copyright (c) 2010, 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 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
67 | 67 |
68 namespace google_breakpad { | 68 namespace google_breakpad { |
69 | 69 |
70 // All interesting auvx entry types are below AT_SYSINFO_EHDR | 70 // All interesting auvx entry types are below AT_SYSINFO_EHDR |
71 #define AT_MAX AT_SYSINFO_EHDR | 71 #define AT_MAX AT_SYSINFO_EHDR |
72 | 72 |
73 LinuxDumper::LinuxDumper(pid_t pid) | 73 LinuxDumper::LinuxDumper(pid_t pid) |
74 : pid_(pid), | 74 : pid_(pid), |
75 crash_address_(0), | 75 crash_address_(0), |
76 crash_signal_(0), | 76 crash_signal_(0), |
77 crash_thread_(0), | 77 crash_thread_(pid), |
78 threads_(&allocator_, 8), | 78 threads_(&allocator_, 8), |
79 mappings_(&allocator_), | 79 mappings_(&allocator_), |
80 auxv_(&allocator_, AT_MAX + 1), | 80 auxv_(&allocator_, AT_MAX + 1), |
81 executable_device_(0), | 81 executable_device_(0), |
82 executable_inode_(0) { | 82 executable_inode_(0) { |
| 83 // The passed-in size to the constructor (above) is only a hint. |
| 84 // Must call .resize() to do actual initialization of the elements. |
| 85 auxv_.resize(AT_MAX + 1); |
83 } | 86 } |
84 | 87 |
85 LinuxDumper::~LinuxDumper() { | 88 LinuxDumper::~LinuxDumper() { |
86 } | 89 } |
87 | 90 |
88 bool LinuxDumper::Init() { | 91 bool LinuxDumper::Init() { |
89 return ReadAuxv() && EnumerateThreads() && EnumerateMappings(); | 92 return ReadAuxv() && EnumerateThreads() && EnumerateMappings(); |
90 } | 93 } |
91 | 94 |
92 bool | 95 bool |
93 LinuxDumper::ElfFileIdentifierForMapping(const MappingInfo& mapping, | 96 LinuxDumper::ElfFileIdentifierForMapping(const MappingInfo& mapping, |
94 uint8_t identifier[sizeof(MDGUID)]) | 97 uint8_t identifier[sizeof(MDGUID)]) { |
95 { | |
96 my_memset(identifier, 0, sizeof(MDGUID)); | 98 my_memset(identifier, 0, sizeof(MDGUID)); |
97 if (IsMappedFileOpenUnsafe(mapping)) | 99 if (IsMappedFileOpenUnsafe(mapping)) |
98 return false; | 100 return false; |
99 | 101 |
100 // Special-case linux-gate because it's not a real file. | 102 // Special-case linux-gate because it's not a real file. |
101 if (mapping.start_addr == auxv_[AT_SYSINFO_EHDR]) { | 103 if (mapping.start_addr == auxv_[AT_SYSINFO_EHDR]) { |
102 MemoryRange linux_gate; | 104 MemoryRange linux_gate; |
103 if (pid_ == sys_getpid()) { | 105 if (pid_ == sys_getpid()) { |
104 linux_gate.Set(reinterpret_cast<void*>(mapping.start_addr), mapping.size); | 106 linux_gate.Set(reinterpret_cast<void*>(mapping.start_addr), mapping.size); |
105 } else { | 107 } else { |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
202 i = my_read_hex_ptr(&dev_minor, i + 1); | 204 i = my_read_hex_ptr(&dev_minor, i + 1); |
203 if (*i != ' ') | 205 if (*i != ' ') |
204 goto popline; | 206 goto popline; |
205 i = my_read_decimal_ptr(&inode, i + 1); | 207 i = my_read_decimal_ptr(&inode, i + 1); |
206 if (*i != ' ') | 208 if (*i != ' ') |
207 goto popline; | 209 goto popline; |
208 | 210 |
209 dev_t device; | 211 dev_t device; |
210 device = makedev(dev_major, dev_minor); | 212 device = makedev(dev_major, dev_minor); |
211 const char* name; | 213 const char* name; |
212 // Skip whitespaces. | 214 // Skip whitespace. |
213 for (name = i; *name == ' '; name++); | 215 for (name = i; *name == ' '; name++); |
214 if (!*name) | 216 if (!*name) |
215 name = NULL; | 217 name = NULL; |
216 // Merge adjacent mappings with the same device/inode pair into one module, | 218 // Merge adjacent mappings with the same device/inode pair into one module, |
217 // assuming they're a single library mapped by the dynamic linker | 219 // assuming they're a single library mapped by the dynamic linker |
218 if (name && !mappings_.empty()) { | 220 if (name && !mappings_.empty()) { |
219 MappingInfo* module = mappings_.back(); | 221 MappingInfo* module = mappings_.back(); |
220 if ((start_addr == module->start_addr + module->size) && | 222 if ((start_addr == module->start_addr + module->size) && |
221 (device == module->device) && (inode == module->inode)) { | 223 (device == module->device) && (inode == module->inode)) { |
222 module->size = end_addr - module->start_addr; | 224 module->size = end_addr - module->start_addr; |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
289 | 291 |
290 uint8_t* const stack_pointer = | 292 uint8_t* const stack_pointer = |
291 reinterpret_cast<uint8_t*>(int_stack_pointer & ~(page_size - 1)); | 293 reinterpret_cast<uint8_t*>(int_stack_pointer & ~(page_size - 1)); |
292 | 294 |
293 // The number of bytes of stack which we try to capture. | 295 // The number of bytes of stack which we try to capture. |
294 static const ptrdiff_t kStackToCapture = 32 * 1024; | 296 static const ptrdiff_t kStackToCapture = 32 * 1024; |
295 | 297 |
296 const MappingInfo* mapping = FindMapping(stack_pointer); | 298 const MappingInfo* mapping = FindMapping(stack_pointer); |
297 if (!mapping) | 299 if (!mapping) |
298 return false; | 300 return false; |
299 const ptrdiff_t offset = stack_pointer - (uint8_t*) mapping->start_addr; | 301 const ptrdiff_t offset = stack_pointer - |
| 302 reinterpret_cast<uint8_t*>(mapping->start_addr); |
300 const ptrdiff_t distance_to_end = | 303 const ptrdiff_t distance_to_end = |
301 static_cast<ptrdiff_t>(mapping->size) - offset; | 304 static_cast<ptrdiff_t>(mapping->size) - offset; |
302 *stack_len = distance_to_end > kStackToCapture ? | 305 *stack_len = distance_to_end > kStackToCapture ? |
303 kStackToCapture : distance_to_end; | 306 kStackToCapture : distance_to_end; |
304 *stack = stack_pointer; | 307 *stack = stack_pointer; |
305 return true; | 308 return true; |
306 } | 309 } |
307 | 310 |
308 // Find the mapping which the given memory address falls in. | 311 // Find the mapping which the given memory address falls in. |
309 const MappingInfo* LinuxDumper::FindMapping(const void* address) const { | 312 const MappingInfo* LinuxDumper::FindMapping(const void* address) const { |
310 const uintptr_t addr = (uintptr_t) address; | 313 const uintptr_t addr = (uintptr_t) address; |
311 | 314 |
312 for (size_t i = 0; i < mappings_.size(); ++i) { | 315 for (size_t i = 0; i < mappings_.size(); ++i) { |
313 const uintptr_t start = static_cast<uintptr_t>(mappings_[i]->start_addr); | 316 const uintptr_t start = static_cast<uintptr_t>(mappings_[i]->start_addr); |
314 if (addr >= start && addr - start < mappings_[i]->size) | 317 if (addr >= start && addr - start < mappings_[i]->size) |
315 return mappings_[i]; | 318 return mappings_[i]; |
316 } | 319 } |
317 | 320 |
318 return NULL; | 321 return NULL; |
319 } | 322 } |
320 | 323 |
321 } // namespace google_breakpad | 324 } // namespace google_breakpad |
LEFT | RIGHT |