OLD | NEW |
1 // Copyright (c) 2006, Google Inc. | 1 // Copyright (c) 2006, 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 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
320 } | 320 } |
321 return false; | 321 return false; |
322 } | 322 } |
323 | 323 |
324 // Get the symbol name of "pc" from the file pointed by "fd". Process | 324 // Get the symbol name of "pc" from the file pointed by "fd". Process |
325 // both regular and dynamic symbol tables if necessary. On success, | 325 // both regular and dynamic symbol tables if necessary. On success, |
326 // write the symbol name to "out" and return true. Otherwise, return | 326 // write the symbol name to "out" and return true. Otherwise, return |
327 // false. | 327 // false. |
328 static bool GetSymbolFromObjectFile(const int fd, uint64_t pc, | 328 static bool GetSymbolFromObjectFile(const int fd, uint64_t pc, |
329 char *out, int out_size, | 329 char *out, int out_size, |
330 uint64_t map_start_address) { | 330 uint64_t map_base_address) { |
331 // Read the ELF header. | 331 // Read the ELF header. |
332 ElfW(Ehdr) elf_header; | 332 ElfW(Ehdr) elf_header; |
333 if (!ReadFromOffsetExact(fd, &elf_header, sizeof(elf_header), 0)) { | 333 if (!ReadFromOffsetExact(fd, &elf_header, sizeof(elf_header), 0)) { |
334 return false; | 334 return false; |
335 } | 335 } |
336 | 336 |
337 uint64_t symbol_offset = 0; | 337 uint64_t symbol_offset = 0; |
338 if (elf_header.e_type == ET_DYN) { // DSO needs offset adjustment. | 338 if (elf_header.e_type == ET_DYN) { // DSO needs offset adjustment. |
339 symbol_offset = map_start_address; | 339 ElfW(Phdr) phdr; |
| 340 // We need to find the PT_LOAD segment corresponding to the read-execute |
| 341 // file mapping in order to correctly perform the offset adjustment. |
| 342 for (unsigned i = 0; i != elf_header.e_phnum; ++i) { |
| 343 if (!ReadFromOffsetExact(fd, &phdr, sizeof(phdr), |
| 344 elf_header.e_phoff + i * sizeof(phdr))) |
| 345 return false; |
| 346 if (phdr.p_type == PT_LOAD && |
| 347 (phdr.p_flags & (PF_R | PF_X)) == (PF_R | PF_X)) { |
| 348 // Find the mapped address corresponding to virtual address zero. We do |
| 349 // this by first adding p_offset. This gives us the mapped address of |
| 350 // the start of the segment, or in other words the mapped address |
| 351 // corresponding to the virtual address of the segment. (Note that this |
| 352 // is distinct from the start address, as p_offset is not guaranteed to |
| 353 // be page aligned.) We then subtract p_vaddr, which takes us to virtual |
| 354 // address zero. |
| 355 symbol_offset = map_base_address + phdr.p_offset - phdr.p_vaddr; |
| 356 break; |
| 357 } |
| 358 } |
| 359 if (symbol_offset == 0) |
| 360 return false; |
340 } | 361 } |
341 | 362 |
342 ElfW(Shdr) symtab, strtab; | 363 ElfW(Shdr) symtab, strtab; |
343 | 364 |
344 // Consult a regular symbol table first. | 365 // Consult a regular symbol table first. |
345 if (GetSectionHeaderByType(fd, elf_header.e_shnum, elf_header.e_shoff, | 366 if (GetSectionHeaderByType(fd, elf_header.e_shnum, elf_header.e_shoff, |
346 SHT_SYMTAB, &symtab)) { | 367 SHT_SYMTAB, &symtab)) { |
347 if (!ReadFromOffsetExact(fd, &strtab, sizeof(strtab), elf_header.e_shoff + | 368 if (!ReadFromOffsetExact(fd, &strtab, sizeof(strtab), elf_header.e_shoff + |
348 symtab.sh_link * sizeof(symtab))) { | 369 symtab.sh_link * sizeof(symtab))) { |
349 return false; | 370 return false; |
(...skipping 426 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
776 uint64_t relocation = (elf_type == ET_DYN) ? start_address : 0; | 797 uint64_t relocation = (elf_type == ET_DYN) ? start_address : 0; |
777 int num_bytes_written = g_symbolize_callback(wrapped_object_fd.get(), | 798 int num_bytes_written = g_symbolize_callback(wrapped_object_fd.get(), |
778 pc, out, out_size, | 799 pc, out, out_size, |
779 relocation); | 800 relocation); |
780 if (num_bytes_written > 0) { | 801 if (num_bytes_written > 0) { |
781 out += num_bytes_written; | 802 out += num_bytes_written; |
782 out_size -= num_bytes_written; | 803 out_size -= num_bytes_written; |
783 } | 804 } |
784 } | 805 } |
785 if (!GetSymbolFromObjectFile(wrapped_object_fd.get(), pc0, | 806 if (!GetSymbolFromObjectFile(wrapped_object_fd.get(), pc0, |
786 out, out_size, start_address)) { | 807 out, out_size, base_address)) { |
787 return false; | 808 return false; |
788 } | 809 } |
789 | 810 |
790 // Symbolization succeeded. Now we try to demangle the symbol. | 811 // Symbolization succeeded. Now we try to demangle the symbol. |
791 DemangleInplace(out, out_size); | 812 DemangleInplace(out, out_size); |
792 return true; | 813 return true; |
793 } | 814 } |
794 | 815 |
795 _END_GOOGLE_NAMESPACE_ | 816 _END_GOOGLE_NAMESPACE_ |
796 | 817 |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
840 | 861 |
841 // TODO: Support other environments. | 862 // TODO: Support other environments. |
842 bool Symbolize(void *pc, char *out, int out_size) { | 863 bool Symbolize(void *pc, char *out, int out_size) { |
843 assert(0); | 864 assert(0); |
844 return false; | 865 return false; |
845 } | 866 } |
846 | 867 |
847 _END_GOOGLE_NAMESPACE_ | 868 _END_GOOGLE_NAMESPACE_ |
848 | 869 |
849 #endif | 870 #endif |
OLD | NEW |