OLD | NEW |
1 // Copyright (c) 2011 Google Inc. | 1 // Copyright (c) 2011 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 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
55 #include "common/dwarf/bytereader-inl.h" | 55 #include "common/dwarf/bytereader-inl.h" |
56 #include "common/dwarf/dwarf2diehandler.h" | 56 #include "common/dwarf/dwarf2diehandler.h" |
57 #include "common/dwarf_cfi_to_module.h" | 57 #include "common/dwarf_cfi_to_module.h" |
58 #include "common/dwarf_cu_to_module.h" | 58 #include "common/dwarf_cu_to_module.h" |
59 #include "common/dwarf_line_to_module.h" | 59 #include "common/dwarf_line_to_module.h" |
60 #include "common/linux/elfutils.h" | 60 #include "common/linux/elfutils.h" |
61 #include "common/linux/elfutils-inl.h" | 61 #include "common/linux/elfutils-inl.h" |
62 #include "common/linux/elf_symbols_to_module.h" | 62 #include "common/linux/elf_symbols_to_module.h" |
63 #include "common/linux/file_id.h" | 63 #include "common/linux/file_id.h" |
64 #include "common/module.h" | 64 #include "common/module.h" |
| 65 #include "common/scoped_ptr.h" |
65 #include "common/stabs_reader.h" | 66 #include "common/stabs_reader.h" |
66 #include "common/stabs_to_module.h" | 67 #include "common/stabs_to_module.h" |
67 #include "common/using_std_string.h" | 68 #include "common/using_std_string.h" |
68 | 69 |
69 // This namespace contains helper functions. | 70 // This namespace contains helper functions. |
70 namespace { | 71 namespace { |
71 | 72 |
72 using google_breakpad::DwarfCFIToModule; | 73 using google_breakpad::DwarfCFIToModule; |
73 using google_breakpad::DwarfCUToModule; | 74 using google_breakpad::DwarfCUToModule; |
74 using google_breakpad::DwarfLineToModule; | 75 using google_breakpad::DwarfLineToModule; |
75 using google_breakpad::ElfClass; | 76 using google_breakpad::ElfClass; |
76 using google_breakpad::ElfClass32; | 77 using google_breakpad::ElfClass32; |
77 using google_breakpad::ElfClass64; | 78 using google_breakpad::ElfClass64; |
78 using google_breakpad::FindElfSectionByName; | 79 using google_breakpad::FindElfSectionByName; |
79 using google_breakpad::GetOffset; | 80 using google_breakpad::GetOffset; |
80 using google_breakpad::IsValidElf; | 81 using google_breakpad::IsValidElf; |
81 using google_breakpad::Module; | 82 using google_breakpad::Module; |
82 using google_breakpad::StabsToModule; | 83 using google_breakpad::StabsToModule; |
| 84 using google_breakpad::scoped_ptr; |
83 | 85 |
84 // | 86 // |
85 // FDWrapper | 87 // FDWrapper |
86 // | 88 // |
87 // Wrapper class to make sure opened file is closed. | 89 // Wrapper class to make sure opened file is closed. |
88 // | 90 // |
89 class FDWrapper { | 91 class FDWrapper { |
90 public: | 92 public: |
91 explicit FDWrapper(int fd) : | 93 explicit FDWrapper(int fd) : |
92 fd_(fd) {} | 94 fd_(fd) {} |
(...skipping 609 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
702 // last slash, or the whole filename if there are no slashes. | 704 // last slash, or the whole filename if there are no slashes. |
703 string BaseFileName(const string &filename) { | 705 string BaseFileName(const string &filename) { |
704 // Lots of copies! basename's behavior is less than ideal. | 706 // Lots of copies! basename's behavior is less than ideal. |
705 char *c_filename = strdup(filename.c_str()); | 707 char *c_filename = strdup(filename.c_str()); |
706 string base = basename(c_filename); | 708 string base = basename(c_filename); |
707 free(c_filename); | 709 free(c_filename); |
708 return base; | 710 return base; |
709 } | 711 } |
710 | 712 |
711 template<typename ElfClass> | 713 template<typename ElfClass> |
712 bool WriteSymbolFileElfClass(const typename ElfClass::Ehdr* elf_header, | 714 bool ReadSymbolDataElfClass(const typename ElfClass::Ehdr* elf_header, |
713 const string& obj_filename, | 715 const string& obj_filename, |
714 const string& debug_dir, | 716 const string& debug_dir, |
715 bool cfi, | 717 bool cfi, |
716 std::ostream& sym_stream) { | 718 Module** out_module) { |
717 typedef typename ElfClass::Ehdr Ehdr; | 719 typedef typename ElfClass::Ehdr Ehdr; |
718 typedef typename ElfClass::Shdr Shdr; | 720 typedef typename ElfClass::Shdr Shdr; |
719 | 721 |
| 722 *out_module = NULL; |
| 723 |
720 unsigned char identifier[16]; | 724 unsigned char identifier[16]; |
721 if (!google_breakpad::FileID::ElfFileIdentifierFromMappedFile(elf_header, | 725 if (!google_breakpad::FileID::ElfFileIdentifierFromMappedFile(elf_header, |
722 identifier)) { | 726 identifier)) { |
723 fprintf(stderr, "%s: unable to generate file identifier\n", | 727 fprintf(stderr, "%s: unable to generate file identifier\n", |
724 obj_filename.c_str()); | 728 obj_filename.c_str()); |
725 return false; | 729 return false; |
726 } | 730 } |
727 | 731 |
728 const char *architecture = ElfArchitecture<ElfClass>(elf_header); | 732 const char *architecture = ElfArchitecture<ElfClass>(elf_header); |
729 if (!architecture) { | 733 if (!architecture) { |
730 fprintf(stderr, "%s: unrecognized ELF machine architecture: %d\n", | 734 fprintf(stderr, "%s: unrecognized ELF machine architecture: %d\n", |
731 obj_filename.c_str(), elf_header->e_machine); | 735 obj_filename.c_str(), elf_header->e_machine); |
732 return false; | 736 return false; |
733 } | 737 } |
734 | 738 |
735 // Figure out what endianness this file is. | 739 // Figure out what endianness this file is. |
736 bool big_endian; | 740 bool big_endian; |
737 if (!ElfEndianness<ElfClass>(elf_header, &big_endian)) | 741 if (!ElfEndianness<ElfClass>(elf_header, &big_endian)) |
738 return false; | 742 return false; |
739 | 743 |
740 string name = BaseFileName(obj_filename); | 744 string name = BaseFileName(obj_filename); |
741 string os = "Linux"; | 745 string os = "Linux"; |
742 string id = FormatIdentifier(identifier); | 746 string id = FormatIdentifier(identifier); |
743 | 747 |
744 LoadSymbolsInfo<ElfClass> info(debug_dir); | 748 LoadSymbolsInfo<ElfClass> info(debug_dir); |
745 Module module(name, os, architecture, id); | 749 scoped_ptr<Module> module(new Module(name, os, architecture, id)); |
746 if (!LoadSymbols<ElfClass>(obj_filename, big_endian, elf_header, | 750 if (!LoadSymbols<ElfClass>(obj_filename, big_endian, elf_header, |
747 !debug_dir.empty(), &info, &module)) { | 751 !debug_dir.empty(), &info, module.get())) { |
748 const string debuglink_file = info.debuglink_file(); | 752 const string debuglink_file = info.debuglink_file(); |
749 if (debuglink_file.empty()) | 753 if (debuglink_file.empty()) |
750 return false; | 754 return false; |
751 | 755 |
752 // Load debuglink ELF file. | 756 // Load debuglink ELF file. |
753 fprintf(stderr, "Found debugging info in %s\n", debuglink_file.c_str()); | 757 fprintf(stderr, "Found debugging info in %s\n", debuglink_file.c_str()); |
754 MmapWrapper debug_map_wrapper; | 758 MmapWrapper debug_map_wrapper; |
755 Ehdr* debug_elf_header = NULL; | 759 Ehdr* debug_elf_header = NULL; |
756 if (!LoadELF(debuglink_file, &debug_map_wrapper, | 760 if (!LoadELF(debuglink_file, &debug_map_wrapper, |
757 reinterpret_cast<void**>(&debug_elf_header))) | 761 reinterpret_cast<void**>(&debug_elf_header))) |
(...skipping 17 matching lines...) Expand all Loading... |
775 bool debug_big_endian; | 779 bool debug_big_endian; |
776 if (!ElfEndianness<ElfClass>(debug_elf_header, &debug_big_endian)) | 780 if (!ElfEndianness<ElfClass>(debug_elf_header, &debug_big_endian)) |
777 return false; | 781 return false; |
778 if (debug_big_endian != big_endian) { | 782 if (debug_big_endian != big_endian) { |
779 fprintf(stderr, "%s and %s does not match in endianness\n", | 783 fprintf(stderr, "%s and %s does not match in endianness\n", |
780 obj_filename.c_str(), debuglink_file.c_str()); | 784 obj_filename.c_str(), debuglink_file.c_str()); |
781 return false; | 785 return false; |
782 } | 786 } |
783 | 787 |
784 if (!LoadSymbols<ElfClass>(debuglink_file, debug_big_endian, | 788 if (!LoadSymbols<ElfClass>(debuglink_file, debug_big_endian, |
785 debug_elf_header, false, &info, &module)) { | 789 debug_elf_header, false, &info, module.get())) { |
786 return false; | 790 return false; |
787 } | 791 } |
788 } | 792 } |
789 if (!module.Write(sym_stream, cfi)) | |
790 return false; | |
791 | 793 |
| 794 *out_module = module.release(); |
792 return true; | 795 return true; |
793 } | 796 } |
794 | 797 |
795 } // namespace | 798 } // namespace |
796 | 799 |
797 namespace google_breakpad { | 800 namespace google_breakpad { |
798 | 801 |
799 // Not explicitly exported, but not static so it can be used in unit tests. | 802 // Not explicitly exported, but not static so it can be used in unit tests. |
800 bool WriteSymbolFileInternal(const uint8_t* obj_file, | 803 bool ReadSymbolDataInternal(const uint8_t* obj_file, |
801 const string& obj_filename, | 804 const string& obj_filename, |
802 const string& debug_dir, | 805 const string& debug_dir, |
803 bool cfi, | 806 bool cfi, |
804 std::ostream& sym_stream) { | 807 Module** module) { |
805 | 808 |
806 if (!IsValidElf(obj_file)) { | 809 if (!IsValidElf(obj_file)) { |
807 fprintf(stderr, "Not a valid ELF file: %s\n", obj_filename.c_str()); | 810 fprintf(stderr, "Not a valid ELF file: %s\n", obj_filename.c_str()); |
808 return false; | 811 return false; |
809 } | 812 } |
810 | 813 |
811 int elfclass = ElfClass(obj_file); | 814 int elfclass = ElfClass(obj_file); |
812 if (elfclass == ELFCLASS32) { | 815 if (elfclass == ELFCLASS32) { |
813 return WriteSymbolFileElfClass<ElfClass32>( | 816 return ReadSymbolDataElfClass<ElfClass32>( |
814 reinterpret_cast<const Elf32_Ehdr*>(obj_file), obj_filename, debug_dir, | 817 reinterpret_cast<const Elf32_Ehdr*>(obj_file), obj_filename, debug_dir, |
815 cfi, sym_stream); | 818 cfi, module); |
816 } | 819 } |
817 if (elfclass == ELFCLASS64) { | 820 if (elfclass == ELFCLASS64) { |
818 return WriteSymbolFileElfClass<ElfClass64>( | 821 return ReadSymbolDataElfClass<ElfClass64>( |
819 reinterpret_cast<const Elf64_Ehdr*>(obj_file), obj_filename, debug_dir, | 822 reinterpret_cast<const Elf64_Ehdr*>(obj_file), obj_filename, debug_dir, |
820 cfi, sym_stream); | 823 cfi, module); |
821 } | 824 } |
822 | 825 |
823 return false; | 826 return false; |
824 } | 827 } |
825 | 828 |
826 bool WriteSymbolFile(const string &obj_file, | 829 bool WriteSymbolFile(const string &obj_file, |
827 const string &debug_dir, | 830 const string &debug_dir, |
828 bool cfi, | 831 bool cfi, |
829 std::ostream &sym_stream) { | 832 std::ostream &sym_stream) { |
| 833 Module* module; |
| 834 if (!ReadSymbolData(obj_file, debug_dir, cfi, &module)) |
| 835 return false; |
| 836 |
| 837 bool result = module->Write(sym_stream, cfi); |
| 838 delete module; |
| 839 return result; |
| 840 } |
| 841 |
| 842 bool ReadSymbolData(const string& obj_file, |
| 843 const string& debug_dir, |
| 844 bool cfi, |
| 845 Module** module) { |
830 MmapWrapper map_wrapper; | 846 MmapWrapper map_wrapper; |
831 void* elf_header = NULL; | 847 void* elf_header = NULL; |
832 if (!LoadELF(obj_file, &map_wrapper, &elf_header)) | 848 if (!LoadELF(obj_file, &map_wrapper, &elf_header)) |
833 return false; | 849 return false; |
834 | 850 |
835 return WriteSymbolFileInternal(reinterpret_cast<uint8_t*>(elf_header), | 851 return ReadSymbolDataInternal(reinterpret_cast<uint8_t*>(elf_header), |
836 obj_file, debug_dir, cfi, sym_stream); | 852 obj_file, debug_dir, cfi, module); |
837 } | 853 } |
838 | 854 |
839 } // namespace google_breakpad | 855 } // namespace google_breakpad |
OLD | NEW |