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

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

Issue 1189823002: Update breakpad for Android packed relocations. (Closed) Base URL: https://chromium.googlesource.com/external/google-breakpad/src.git@master
Patch Set: Update for more review comments. Created 5 years, 6 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
OLDNEW
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 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
45 #include <string.h> 45 #include <string.h>
46 46
47 #include "client/linux/minidump_writer/line_reader.h" 47 #include "client/linux/minidump_writer/line_reader.h"
48 #include "common/linux/elfutils.h" 48 #include "common/linux/elfutils.h"
49 #include "common/linux/file_id.h" 49 #include "common/linux/file_id.h"
50 #include "common/linux/linux_libc_support.h" 50 #include "common/linux/linux_libc_support.h"
51 #include "common/linux/memory_mapped_file.h" 51 #include "common/linux/memory_mapped_file.h"
52 #include "common/linux/safe_readlink.h" 52 #include "common/linux/safe_readlink.h"
53 #include "third_party/lss/linux_syscall_support.h" 53 #include "third_party/lss/linux_syscall_support.h"
54 54
55 #if defined(__ANDROID__)
56
57 // Android packed relocations definitions are not yet available from the
58 // NDK header files, so we have to provide them manually here.
59 #ifndef DT_LOOS
60 #define DT_LOOS 0x6000000d
61 #endif
62 #ifndef DT_ANDROID_REL
63 static const int DT_ANDROID_REL = DT_LOOS + 2;
64 #endif
65 #ifndef DT_ANDROID_RELA
66 static const int DT_ANDROID_RELA = DT_LOOS + 4;
67 #endif
68
69 #endif // __ANDROID __
70
55 static const char kMappedFileUnsafePrefix[] = "/dev/"; 71 static const char kMappedFileUnsafePrefix[] = "/dev/";
56 static const char kDeletedSuffix[] = " (deleted)"; 72 static const char kDeletedSuffix[] = " (deleted)";
57 static const char kReservedFlags[] = " ---p"; 73 static const char kReservedFlags[] = " ---p";
58 74
59 inline static bool IsMappedFileOpenUnsafe( 75 inline static bool IsMappedFileOpenUnsafe(
60 const google_breakpad::MappingInfo& mapping) { 76 const google_breakpad::MappingInfo& mapping) {
61 // It is unsafe to attempt to open a mapped file that lives under /dev, 77 // It is unsafe to attempt to open a mapped file that lives under /dev,
62 // because the semantics of the open may be driver-specific so we'd risk 78 // because the semantics of the open may be driver-specific so we'd risk
63 // hanging the crash dumper. And a file in /dev/ almost certainly has no 79 // hanging the crash dumper. And a file in /dev/ almost certainly has no
64 // ELF file identifier anyways. 80 // ELF file identifier anyways.
(...skipping 20 matching lines...) Expand all
85 auxv_.resize(AT_MAX + 1); 101 auxv_.resize(AT_MAX + 1);
86 } 102 }
87 103
88 LinuxDumper::~LinuxDumper() { 104 LinuxDumper::~LinuxDumper() {
89 } 105 }
90 106
91 bool LinuxDumper::Init() { 107 bool LinuxDumper::Init() {
92 return ReadAuxv() && EnumerateThreads() && EnumerateMappings(); 108 return ReadAuxv() && EnumerateThreads() && EnumerateMappings();
93 } 109 }
94 110
111 bool LinuxDumper::LateInit() {
112 #if defined(__ANDROID__)
113 LatePostprocessMappings();
114 #endif
115 return true;
116 }
117
95 bool 118 bool
96 LinuxDumper::ElfFileIdentifierForMapping(const MappingInfo& mapping, 119 LinuxDumper::ElfFileIdentifierForMapping(const MappingInfo& mapping,
97 bool member, 120 bool member,
98 unsigned int mapping_id, 121 unsigned int mapping_id,
99 uint8_t identifier[sizeof(MDGUID)]) { 122 uint8_t identifier[sizeof(MDGUID)]) {
100 assert(!member || mapping_id < mappings_.size()); 123 assert(!member || mapping_id < mappings_.size());
101 my_memset(identifier, 0, sizeof(MDGUID)); 124 my_memset(identifier, 0, sizeof(MDGUID));
102 if (IsMappedFileOpenUnsafe(mapping)) 125 if (IsMappedFileOpenUnsafe(mapping))
103 return false; 126 return false;
104 127
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after
388 } 411 }
389 } 412 }
390 line_reader->PopLine(line_len); 413 line_reader->PopLine(line_len);
391 } 414 }
392 415
393 sys_close(fd); 416 sys_close(fd);
394 417
395 return !mappings_.empty(); 418 return !mappings_.empty();
396 } 419 }
397 420
421 #if defined(__ANDROID__)
422
423 bool LinuxDumper::GetLoadedElfHeader(uintptr_t start_addr, ElfW(Ehdr)* ehdr) {
424 CopyFromProcess(ehdr, pid_,
425 reinterpret_cast<const void*>(start_addr),
426 sizeof(*ehdr));
427 return my_memcmp(&ehdr->e_ident, ELFMAG, SELFMAG) == 0;
428 }
429
430 void LinuxDumper::ParseLoadedElfProgramHeaders(ElfW(Ehdr)* ehdr,
431 uintptr_t start_addr,
432 uintptr_t* min_vaddr_ptr,
433 uintptr_t* dyn_vaddr_ptr,
434 size_t* dyn_count_ptr) {
435 uintptr_t phdr_addr = start_addr + ehdr->e_phoff;
436
437 const uintptr_t max_addr = UINTPTR_MAX;
438 uintptr_t min_vaddr = max_addr;
439 uintptr_t dyn_vaddr = 0;
440 size_t dyn_count = 0;
441
442 for (size_t i = 0; i < ehdr->e_phnum; ++i) {
443 ElfW(Phdr) phdr;
444 CopyFromProcess(&phdr, pid_,
445 reinterpret_cast<const void*>(phdr_addr),
446 sizeof(phdr));
447 if (phdr.p_type == PT_LOAD && phdr.p_vaddr < min_vaddr) {
448 min_vaddr = phdr.p_vaddr;
449 }
450 if (phdr.p_type == PT_DYNAMIC) {
451 dyn_vaddr = phdr.p_vaddr;
452 dyn_count = phdr.p_memsz / sizeof(ElfW(Dyn));
453 }
454 phdr_addr += sizeof(phdr);
455 }
456
457 *min_vaddr_ptr = min_vaddr;
458 *dyn_vaddr_ptr = dyn_vaddr;
459 *dyn_count_ptr = dyn_count;
460 }
461
462 bool LinuxDumper::HasAndroidPackedRelocations(uintptr_t load_bias,
463 uintptr_t dyn_vaddr,
464 size_t dyn_count) {
465 uintptr_t dyn_addr = load_bias + dyn_vaddr;
466 for (size_t i = 0; i < dyn_count; ++i) {
467 ElfW(Dyn) dyn;
468 CopyFromProcess(&dyn, pid_,
469 reinterpret_cast<const void*>(dyn_addr),
470 sizeof(dyn));
471 if (dyn.d_tag == DT_ANDROID_REL || dyn.d_tag == DT_ANDROID_RELA) {
472 return true;
473 }
474 dyn_addr += sizeof(dyn);
475 }
476 return false;
477 }
478
479 uintptr_t LinuxDumper::GetEffectiveLoadBias(ElfW(Ehdr)* ehdr,
480 uintptr_t start_addr) {
481 uintptr_t min_vaddr = 0;
482 uintptr_t dyn_vaddr = 0;
483 size_t dyn_count = 0;
484 ParseLoadedElfProgramHeaders(ehdr, start_addr,
485 &min_vaddr, &dyn_vaddr, &dyn_count);
486 // If |min_vaddr| is non-zero and we find Android packed relocation tags,
487 // return the effective load bias.
488 if (min_vaddr != 0) {
489 const uintptr_t load_bias = start_addr - min_vaddr;
490 if (HasAndroidPackedRelocations(load_bias, dyn_vaddr, dyn_count)) {
491 return load_bias;
492 }
493 }
494 // Either |min_vaddr| is zero, or it is non-zero but we did not find the
495 // expected Android packed relocations tags.
496 return start_addr;
497 }
498
499 void LinuxDumper::LatePostprocessMappings() {
500 for (size_t i = 0; i < mappings_.size(); ++i) {
501 // Only consider exec mappings that indicate a file path was mapped, and
502 // where the ELF header indicates a mapped shared library.
503 MappingInfo* mapping = mappings_[i];
504 if (!(mapping->exec && mapping->name[0] == '/')) {
505 continue;
506 }
507 ElfW(Ehdr) ehdr;
508 if (!GetLoadedElfHeader(mapping->start_addr, &ehdr)) {
509 continue;
510 }
511 if (ehdr.e_type == ET_DYN) {
512 // Compute the effective load bias for this mapped library, and update
513 // the mapping to hold that rather than |start_addr|. Where the library
514 // does not contain Android packed relocations, GetEffectiveLoadBias()
515 // returns |start_addr| and the mapping entry is not changed.
516 mapping->start_addr = GetEffectiveLoadBias(&ehdr, mapping->start_addr);
517 }
518 }
519 }
520
521 #endif // __ANDROID__
522
398 // Get information about the stack, given the stack pointer. We don't try to 523 // Get information about the stack, given the stack pointer. We don't try to
399 // walk the stack since we might not have all the information needed to do 524 // walk the stack since we might not have all the information needed to do
400 // unwind. So we just grab, up to, 32k of stack. 525 // unwind. So we just grab, up to, 32k of stack.
401 bool LinuxDumper::GetStackInfo(const void** stack, size_t* stack_len, 526 bool LinuxDumper::GetStackInfo(const void** stack, size_t* stack_len,
402 uintptr_t int_stack_pointer) { 527 uintptr_t int_stack_pointer) {
403 // Move the stack pointer to the bottom of the page that it's in. 528 // Move the stack pointer to the bottom of the page that it's in.
404 const uintptr_t page_size = getpagesize(); 529 const uintptr_t page_size = getpagesize();
405 530
406 uint8_t* const stack_pointer = 531 uint8_t* const stack_pointer =
407 reinterpret_cast<uint8_t*>(int_stack_pointer & ~(page_size - 1)); 532 reinterpret_cast<uint8_t*>(int_stack_pointer & ~(page_size - 1));
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
466 exe_stat.st_dev == new_path_stat.st_dev && 591 exe_stat.st_dev == new_path_stat.st_dev &&
467 exe_stat.st_ino == new_path_stat.st_ino) { 592 exe_stat.st_ino == new_path_stat.st_ino) {
468 return false; 593 return false;
469 } 594 }
470 595
471 my_memcpy(path, exe_link, NAME_MAX); 596 my_memcpy(path, exe_link, NAME_MAX);
472 return true; 597 return true;
473 } 598 }
474 599
475 } // namespace google_breakpad 600 } // namespace google_breakpad
OLDNEW
« no previous file with comments | « client/linux/minidump_writer/linux_dumper.h ('k') | client/linux/minidump_writer/minidump_writer.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698