Chromium Code Reviews| 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 |