OLD | NEW |
---|---|
1 // Copyright (c) 2011 Google Inc. | 1 // Copyright (c) 2011 Google Inc. |
Mark Mentovai
2016/01/25 21:50:39
And I guess these tool .cc files too.
| |
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 |
11 // copyright notice, this list of conditions and the following disclaimer | 11 // copyright notice, this list of conditions and the following disclaimer |
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
213 // dwarf2reader::LineInfo and populates a Module and a line vector | 213 // dwarf2reader::LineInfo and populates a Module and a line vector |
214 // with the results. | 214 // with the results. |
215 class DumperLineToModule: public DwarfCUToModule::LineToModuleHandler { | 215 class DumperLineToModule: public DwarfCUToModule::LineToModuleHandler { |
216 public: | 216 public: |
217 // Create a line-to-module converter using BYTE_READER. | 217 // Create a line-to-module converter using BYTE_READER. |
218 explicit DumperLineToModule(dwarf2reader::ByteReader *byte_reader) | 218 explicit DumperLineToModule(dwarf2reader::ByteReader *byte_reader) |
219 : byte_reader_(byte_reader) { } | 219 : byte_reader_(byte_reader) { } |
220 void StartCompilationUnit(const string& compilation_dir) { | 220 void StartCompilationUnit(const string& compilation_dir) { |
221 compilation_dir_ = compilation_dir; | 221 compilation_dir_ = compilation_dir; |
222 } | 222 } |
223 void ReadProgram(const char* program, uint64 length, | 223 void ReadProgram(const uint8_t *program, uint64 length, |
224 Module* module, std::vector<Module::Line>* lines) { | 224 Module* module, std::vector<Module::Line>* lines) { |
225 DwarfLineToModule handler(module, compilation_dir_, lines); | 225 DwarfLineToModule handler(module, compilation_dir_, lines); |
226 dwarf2reader::LineInfo parser(program, length, byte_reader_, &handler); | 226 dwarf2reader::LineInfo parser(program, length, byte_reader_, &handler); |
227 parser.Start(); | 227 parser.Start(); |
228 } | 228 } |
229 private: | 229 private: |
230 string compilation_dir_; | 230 string compilation_dir_; |
231 dwarf2reader::ByteReader *byte_reader_; | 231 dwarf2reader::ByteReader *byte_reader_; |
232 }; | 232 }; |
233 | 233 |
(...skipping 17 matching lines...) Expand all Loading... | |
251 // Build a map of the ELF file's sections. | 251 // Build a map of the ELF file's sections. |
252 const Shdr* sections = | 252 const Shdr* sections = |
253 GetOffset<ElfClass, Shdr>(elf_header, elf_header->e_shoff); | 253 GetOffset<ElfClass, Shdr>(elf_header, elf_header->e_shoff); |
254 int num_sections = elf_header->e_shnum; | 254 int num_sections = elf_header->e_shnum; |
255 const Shdr* section_names = sections + elf_header->e_shstrndx; | 255 const Shdr* section_names = sections + elf_header->e_shstrndx; |
256 for (int i = 0; i < num_sections; i++) { | 256 for (int i = 0; i < num_sections; i++) { |
257 const Shdr* section = §ions[i]; | 257 const Shdr* section = §ions[i]; |
258 string name = GetOffset<ElfClass, char>(elf_header, | 258 string name = GetOffset<ElfClass, char>(elf_header, |
259 section_names->sh_offset) + | 259 section_names->sh_offset) + |
260 section->sh_name; | 260 section->sh_name; |
261 const char* contents = GetOffset<ElfClass, char>(elf_header, | 261 const uint8_t *contents = GetOffset<ElfClass, uint8_t>(elf_header, |
262 section->sh_offset); | 262 section->sh_offset); |
263 file_context.AddSectionToSectionMap(name, contents, section->sh_size); | 263 file_context.AddSectionToSectionMap(name, contents, section->sh_size); |
264 } | 264 } |
265 | 265 |
266 // Parse all the compilation units in the .debug_info section. | 266 // Parse all the compilation units in the .debug_info section. |
267 DumperLineToModule line_to_module(&byte_reader); | 267 DumperLineToModule line_to_module(&byte_reader); |
268 dwarf2reader::SectionMap::const_iterator debug_info_entry = | 268 dwarf2reader::SectionMap::const_iterator debug_info_entry = |
269 file_context.section_map().find(".debug_info"); | 269 file_context.section_map().find(".debug_info"); |
270 assert(debug_info_entry != file_context.section_map().end()); | 270 assert(debug_info_entry != file_context.section_map().end()); |
271 const std::pair<const char*, uint64>& debug_info_section = | 271 const std::pair<const uint8_t *, uint64>& debug_info_section = |
272 debug_info_entry->second; | 272 debug_info_entry->second; |
273 // This should never have been called if the file doesn't have a | 273 // This should never have been called if the file doesn't have a |
274 // .debug_info section. | 274 // .debug_info section. |
275 assert(debug_info_section.first); | 275 assert(debug_info_section.first); |
276 uint64 debug_info_length = debug_info_section.second; | 276 uint64 debug_info_length = debug_info_section.second; |
277 for (uint64 offset = 0; offset < debug_info_length;) { | 277 for (uint64 offset = 0; offset < debug_info_length;) { |
278 // Make a handler for the root DIE that populates MODULE with the | 278 // Make a handler for the root DIE that populates MODULE with the |
279 // data that was found. | 279 // data that was found. |
280 DwarfCUToModule::WarningReporter reporter(dwarf_filename, offset); | 280 DwarfCUToModule::WarningReporter reporter(dwarf_filename, offset); |
281 DwarfCUToModule root_handler(&file_context, &line_to_module, &reporter); | 281 DwarfCUToModule root_handler(&file_context, &line_to_module, &reporter); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
338 fprintf(stderr, "%s: unrecognized ELF machine architecture '%d';" | 338 fprintf(stderr, "%s: unrecognized ELF machine architecture '%d';" |
339 " cannot convert DWARF call frame information\n", | 339 " cannot convert DWARF call frame information\n", |
340 dwarf_filename.c_str(), elf_header->e_machine); | 340 dwarf_filename.c_str(), elf_header->e_machine); |
341 return false; | 341 return false; |
342 } | 342 } |
343 | 343 |
344 const dwarf2reader::Endianness endianness = big_endian ? | 344 const dwarf2reader::Endianness endianness = big_endian ? |
345 dwarf2reader::ENDIANNESS_BIG : dwarf2reader::ENDIANNESS_LITTLE; | 345 dwarf2reader::ENDIANNESS_BIG : dwarf2reader::ENDIANNESS_LITTLE; |
346 | 346 |
347 // Find the call frame information and its size. | 347 // Find the call frame information and its size. |
348 const char* cfi = | 348 const uint8_t *cfi = |
349 GetOffset<ElfClass, char>(elf_header, section->sh_offset); | 349 GetOffset<ElfClass, uint8_t>(elf_header, section->sh_offset); |
350 size_t cfi_size = section->sh_size; | 350 size_t cfi_size = section->sh_size; |
351 | 351 |
352 // Plug together the parser, handler, and their entourages. | 352 // Plug together the parser, handler, and their entourages. |
353 DwarfCFIToModule::Reporter module_reporter(dwarf_filename, section_name); | 353 DwarfCFIToModule::Reporter module_reporter(dwarf_filename, section_name); |
354 DwarfCFIToModule handler(module, register_names, &module_reporter); | 354 DwarfCFIToModule handler(module, register_names, &module_reporter); |
355 dwarf2reader::ByteReader byte_reader(endianness); | 355 dwarf2reader::ByteReader byte_reader(endianness); |
356 | 356 |
357 byte_reader.SetAddressSize(ElfClass::kAddrSize); | 357 byte_reader.SetAddressSize(ElfClass::kAddrSize); |
358 | 358 |
359 // Provide the base addresses for .eh_frame encoded pointers, if | 359 // Provide the base addresses for .eh_frame encoded pointers, if |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
426 // two absolute paths are the same. | 426 // two absolute paths are the same. |
427 bool IsSameFile(const char* left_abspath, const string& right_path) { | 427 bool IsSameFile(const char* left_abspath, const string& right_path) { |
428 char right_abspath[PATH_MAX]; | 428 char right_abspath[PATH_MAX]; |
429 if (!realpath(right_path.c_str(), right_abspath)) | 429 if (!realpath(right_path.c_str(), right_abspath)) |
430 return false; | 430 return false; |
431 return strcmp(left_abspath, right_abspath) == 0; | 431 return strcmp(left_abspath, right_abspath) == 0; |
432 } | 432 } |
433 | 433 |
434 // Read the .gnu_debuglink and get the debug file name. If anything goes | 434 // Read the .gnu_debuglink and get the debug file name. If anything goes |
435 // wrong, return an empty string. | 435 // wrong, return an empty string. |
436 string ReadDebugLink(const char* debuglink, | 436 string ReadDebugLink(const uint8_t *debuglink, |
437 const size_t debuglink_size, | 437 const size_t debuglink_size, |
438 const bool big_endian, | 438 const bool big_endian, |
439 const string& obj_file, | 439 const string& obj_file, |
440 const std::vector<string>& debug_dirs) { | 440 const std::vector<string>& debug_dirs) { |
441 size_t debuglink_len = strlen(debuglink) + 5; // Include '\0' + CRC32. | 441 // Include '\0' + CRC32 (4 bytes). |
442 size_t debuglink_len = strlen(reinterpret_cast<const char *>(debuglink)) + 5; | |
442 debuglink_len = 4 * ((debuglink_len + 3) / 4); // Round up to 4 bytes. | 443 debuglink_len = 4 * ((debuglink_len + 3) / 4); // Round up to 4 bytes. |
443 | 444 |
444 // Sanity check. | 445 // Sanity check. |
445 if (debuglink_len != debuglink_size) { | 446 if (debuglink_len != debuglink_size) { |
446 fprintf(stderr, "Mismatched .gnu_debuglink string / section size: " | 447 fprintf(stderr, "Mismatched .gnu_debuglink string / section size: " |
447 "%zx %zx\n", debuglink_len, debuglink_size); | 448 "%zx %zx\n", debuglink_len, debuglink_size); |
448 return string(); | 449 return string(); |
449 } | 450 } |
450 | 451 |
451 char obj_file_abspath[PATH_MAX]; | 452 char obj_file_abspath[PATH_MAX]; |
452 if (!realpath(obj_file.c_str(), obj_file_abspath)) { | 453 if (!realpath(obj_file.c_str(), obj_file_abspath)) { |
453 fprintf(stderr, "Cannot resolve absolute path for %s\n", obj_file.c_str()); | 454 fprintf(stderr, "Cannot resolve absolute path for %s\n", obj_file.c_str()); |
454 return string(); | 455 return string(); |
455 } | 456 } |
456 | 457 |
457 std::vector<string> searched_paths; | 458 std::vector<string> searched_paths; |
458 string debuglink_path; | 459 string debuglink_path; |
459 std::vector<string>::const_iterator it; | 460 std::vector<string>::const_iterator it; |
460 for (it = debug_dirs.begin(); it < debug_dirs.end(); ++it) { | 461 for (it = debug_dirs.begin(); it < debug_dirs.end(); ++it) { |
461 const string& debug_dir = *it; | 462 const string& debug_dir = *it; |
462 debuglink_path = debug_dir + "/" + debuglink; | 463 debuglink_path = debug_dir + "/" + |
464 reinterpret_cast<const char *>(debuglink); | |
463 | 465 |
464 // There is the annoying case of /path/to/foo.so having foo.so as the | 466 // There is the annoying case of /path/to/foo.so having foo.so as the |
465 // debug link file name. Thus this may end up opening /path/to/foo.so again, | 467 // debug link file name. Thus this may end up opening /path/to/foo.so again, |
466 // and there is a small chance of the two files having the same CRC. | 468 // and there is a small chance of the two files having the same CRC. |
467 if (IsSameFile(obj_file_abspath, debuglink_path)) | 469 if (IsSameFile(obj_file_abspath, debuglink_path)) |
468 continue; | 470 continue; |
469 | 471 |
470 searched_paths.push_back(debug_dir); | 472 searched_paths.push_back(debug_dir); |
471 int debuglink_fd = open(debuglink_path.c_str(), O_RDONLY); | 473 int debuglink_fd = open(debuglink_path.c_str(), O_RDONLY); |
472 if (debuglink_fd < 0) | 474 if (debuglink_fd < 0) |
(...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
762 obj_file.c_str()); | 764 obj_file.c_str()); |
763 | 765 |
764 // Failed, but maybe there's a .gnu_debuglink section? | 766 // Failed, but maybe there's a .gnu_debuglink section? |
765 if (read_gnu_debug_link) { | 767 if (read_gnu_debug_link) { |
766 const Shdr* gnu_debuglink_section | 768 const Shdr* gnu_debuglink_section |
767 = FindElfSectionByName<ElfClass>(".gnu_debuglink", SHT_PROGBITS, | 769 = FindElfSectionByName<ElfClass>(".gnu_debuglink", SHT_PROGBITS, |
768 sections, names, | 770 sections, names, |
769 names_end, elf_header->e_shnum); | 771 names_end, elf_header->e_shnum); |
770 if (gnu_debuglink_section) { | 772 if (gnu_debuglink_section) { |
771 if (!info->debug_dirs().empty()) { | 773 if (!info->debug_dirs().empty()) { |
772 const char* debuglink_contents = | 774 const uint8_t *debuglink_contents = |
773 GetOffset<ElfClass, char>(elf_header, | 775 GetOffset<ElfClass, uint8_t>(elf_header, |
774 gnu_debuglink_section->sh_offset); | 776 gnu_debuglink_section->sh_offset); |
775 string debuglink_file = | 777 string debuglink_file = |
776 ReadDebugLink(debuglink_contents, | 778 ReadDebugLink(debuglink_contents, |
777 gnu_debuglink_section->sh_size, | 779 gnu_debuglink_section->sh_size, |
778 big_endian, | 780 big_endian, |
779 obj_file, | 781 obj_file, |
780 info->debug_dirs()); | 782 info->debug_dirs()); |
781 info->set_debuglink_file(debuglink_file); | 783 info->set_debuglink_file(debuglink_file); |
782 } else { | 784 } else { |
783 fprintf(stderr, ".gnu_debuglink section found in '%s', " | 785 fprintf(stderr, ".gnu_debuglink section found in '%s', " |
784 "but no debug path specified.\n", obj_file.c_str()); | 786 "but no debug path specified.\n", obj_file.c_str()); |
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
997 MmapWrapper map_wrapper; | 999 MmapWrapper map_wrapper; |
998 void* elf_header = NULL; | 1000 void* elf_header = NULL; |
999 if (!LoadELF(obj_file, &map_wrapper, &elf_header)) | 1001 if (!LoadELF(obj_file, &map_wrapper, &elf_header)) |
1000 return false; | 1002 return false; |
1001 | 1003 |
1002 return ReadSymbolDataInternal(reinterpret_cast<uint8_t*>(elf_header), | 1004 return ReadSymbolDataInternal(reinterpret_cast<uint8_t*>(elf_header), |
1003 obj_file, debug_dirs, options, module); | 1005 obj_file, debug_dirs, options, module); |
1004 } | 1006 } |
1005 | 1007 |
1006 } // namespace google_breakpad | 1008 } // namespace google_breakpad |
OLD | NEW |