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 883 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
894 return false; | 894 return false; |
895 if (debug_big_endian != obj_file_is_big_endian) { | 895 if (debug_big_endian != obj_file_is_big_endian) { |
896 fprintf(stderr, "%s and %s does not match in endianness\n", | 896 fprintf(stderr, "%s and %s does not match in endianness\n", |
897 obj_filename.c_str(), debuglink_file.c_str()); | 897 obj_filename.c_str(), debuglink_file.c_str()); |
898 return false; | 898 return false; |
899 } | 899 } |
900 return true; | 900 return true; |
901 } | 901 } |
902 | 902 |
903 template<typename ElfClass> | 903 template<typename ElfClass> |
904 bool ReadSymbolDataElfClass(const typename ElfClass::Ehdr* elf_header, | 904 bool InitModuleForElfClass(const typename ElfClass::Ehdr* elf_header, |
905 const string& obj_filename, | 905 const string& obj_filename, |
906 const std::vector<string>& debug_dirs, | 906 scoped_ptr<Module>& module) { |
907 const DumpOptions& options, | |
908 Module** out_module) { | |
909 typedef typename ElfClass::Ehdr Ehdr; | |
910 | |
911 *out_module = NULL; | |
912 | |
913 PageAllocator allocator; | 907 PageAllocator allocator; |
914 wasteful_vector<uint8_t> identifier(&allocator, kDefaultBuildIdSize); | 908 wasteful_vector<uint8_t> identifier(&allocator, kDefaultBuildIdSize); |
915 if (!FileID::ElfFileIdentifierFromMappedFile(elf_header, | 909 if (!FileID::ElfFileIdentifierFromMappedFile(elf_header, identifier)) { |
916 identifier)) { | |
917 fprintf(stderr, "%s: unable to generate file identifier\n", | 910 fprintf(stderr, "%s: unable to generate file identifier\n", |
918 obj_filename.c_str()); | 911 obj_filename.c_str()); |
919 return false; | 912 return false; |
920 } | 913 } |
921 | 914 |
922 const char *architecture = ElfArchitecture<ElfClass>(elf_header); | 915 const char *architecture = ElfArchitecture<ElfClass>(elf_header); |
923 if (!architecture) { | 916 if (!architecture) { |
924 fprintf(stderr, "%s: unrecognized ELF machine architecture: %d\n", | 917 fprintf(stderr, "%s: unrecognized ELF machine architecture: %d\n", |
925 obj_filename.c_str(), elf_header->e_machine); | 918 obj_filename.c_str(), elf_header->e_machine); |
926 return false; | 919 return false; |
927 } | 920 } |
928 | 921 |
929 // Figure out what endianness this file is. | |
930 bool big_endian; | |
931 if (!ElfEndianness<ElfClass>(elf_header, &big_endian)) | |
932 return false; | |
933 | |
934 string name = BaseFileName(obj_filename); | 922 string name = BaseFileName(obj_filename); |
935 string os = "Linux"; | 923 string os = "Linux"; |
936 // Add an extra "0" at the end. PDB files on Windows have an 'age' | 924 // Add an extra "0" at the end. PDB files on Windows have an 'age' |
937 // number appended to the end of the file identifier; this isn't | 925 // number appended to the end of the file identifier; this isn't |
938 // really used or necessary on other platforms, but be consistent. | 926 // really used or necessary on other platforms, but be consistent. |
939 string id = FileID::ConvertIdentifierToUUIDString(identifier) + "0"; | 927 string id = FileID::ConvertIdentifierToUUIDString(identifier) + "0"; |
940 | 928 |
| 929 module.reset(new Module(name, os, architecture, id)); |
| 930 |
| 931 return true; |
| 932 } |
| 933 |
| 934 template<typename ElfClass> |
| 935 bool ReadSymbolDataElfClass(const typename ElfClass::Ehdr* elf_header, |
| 936 const string& obj_filename, |
| 937 const std::vector<string>& debug_dirs, |
| 938 const DumpOptions& options, |
| 939 Module** out_module) { |
| 940 typedef typename ElfClass::Ehdr Ehdr; |
| 941 |
| 942 *out_module = NULL; |
| 943 |
| 944 scoped_ptr<Module> module; |
| 945 if (!InitModuleForElfClass<ElfClass>(elf_header, obj_filename, module)) { |
| 946 return false; |
| 947 } |
| 948 |
| 949 // Figure out what endianness this file is. |
| 950 bool big_endian; |
| 951 if (!ElfEndianness<ElfClass>(elf_header, &big_endian)) |
| 952 return false; |
| 953 |
941 LoadSymbolsInfo<ElfClass> info(debug_dirs); | 954 LoadSymbolsInfo<ElfClass> info(debug_dirs); |
942 scoped_ptr<Module> module(new Module(name, os, architecture, id)); | |
943 if (!LoadSymbols<ElfClass>(obj_filename, big_endian, elf_header, | 955 if (!LoadSymbols<ElfClass>(obj_filename, big_endian, elf_header, |
944 !debug_dirs.empty(), &info, | 956 !debug_dirs.empty(), &info, |
945 options, module.get())) { | 957 options, module.get())) { |
946 const string debuglink_file = info.debuglink_file(); | 958 const string debuglink_file = info.debuglink_file(); |
947 if (debuglink_file.empty()) | 959 if (debuglink_file.empty()) |
948 return false; | 960 return false; |
949 | 961 |
950 // Load debuglink ELF file. | 962 // Load debuglink ELF file. |
951 fprintf(stderr, "Found debugging info in %s\n", debuglink_file.c_str()); | 963 fprintf(stderr, "Found debugging info in %s\n", debuglink_file.c_str()); |
952 MmapWrapper debug_map_wrapper; | 964 MmapWrapper debug_map_wrapper; |
953 Ehdr* debug_elf_header = NULL; | 965 Ehdr* debug_elf_header = NULL; |
954 if (!LoadELF(debuglink_file, &debug_map_wrapper, | 966 if (!LoadELF(debuglink_file, &debug_map_wrapper, |
955 reinterpret_cast<void**>(&debug_elf_header)) || | 967 reinterpret_cast<void**>(&debug_elf_header)) || |
956 !SanitizeDebugFile<ElfClass>(debug_elf_header, debuglink_file, | 968 !SanitizeDebugFile<ElfClass>(debug_elf_header, debuglink_file, |
957 obj_filename, architecture, big_endian)) { | 969 obj_filename, |
| 970 module->architecture().c_str(), |
| 971 big_endian)) { |
958 return false; | 972 return false; |
959 } | 973 } |
960 | 974 |
961 if (!LoadSymbols<ElfClass>(debuglink_file, big_endian, | 975 if (!LoadSymbols<ElfClass>(debuglink_file, big_endian, |
962 debug_elf_header, false, &info, | 976 debug_elf_header, false, &info, |
963 options, module.get())) { | 977 options, module.get())) { |
964 return false; | 978 return false; |
965 } | 979 } |
966 } | 980 } |
967 | 981 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1005 std::ostream &sym_stream) { | 1019 std::ostream &sym_stream) { |
1006 Module* module; | 1020 Module* module; |
1007 if (!ReadSymbolData(obj_file, debug_dirs, options, &module)) | 1021 if (!ReadSymbolData(obj_file, debug_dirs, options, &module)) |
1008 return false; | 1022 return false; |
1009 | 1023 |
1010 bool result = module->Write(sym_stream, options.symbol_data); | 1024 bool result = module->Write(sym_stream, options.symbol_data); |
1011 delete module; | 1025 delete module; |
1012 return result; | 1026 return result; |
1013 } | 1027 } |
1014 | 1028 |
| 1029 // Read the selected object file's debugging information, and write out the |
| 1030 // header only to |stream|. Return true on success; if an error occurs, report |
| 1031 // it and return false. |
| 1032 bool WriteSymbolFileHeader(const string& obj_file, |
| 1033 std::ostream &sym_stream) { |
| 1034 MmapWrapper map_wrapper; |
| 1035 void* elf_header = NULL; |
| 1036 if (!LoadELF(obj_file, &map_wrapper, &elf_header)) { |
| 1037 fprintf(stderr, "Could not load ELF file: %s\n", obj_file.c_str()); |
| 1038 return false; |
| 1039 } |
| 1040 |
| 1041 if (!IsValidElf(elf_header)) { |
| 1042 fprintf(stderr, "Not a valid ELF file: %s\n", obj_file.c_str()); |
| 1043 return false; |
| 1044 } |
| 1045 |
| 1046 int elfclass = ElfClass(elf_header); |
| 1047 scoped_ptr<Module> module; |
| 1048 if (elfclass == ELFCLASS32) { |
| 1049 if (!InitModuleForElfClass<ElfClass32>( |
| 1050 reinterpret_cast<const Elf32_Ehdr*>(elf_header), obj_file, module)) { |
| 1051 fprintf(stderr, "Failed to load ELF module: %s\n", obj_file.c_str()); |
| 1052 return false; |
| 1053 } |
| 1054 } else if (elfclass == ELFCLASS64) { |
| 1055 if (!InitModuleForElfClass<ElfClass64>( |
| 1056 reinterpret_cast<const Elf64_Ehdr*>(elf_header), obj_file, module)) { |
| 1057 fprintf(stderr, "Failed to load ELF module: %s\n", obj_file.c_str()); |
| 1058 return false; |
| 1059 } |
| 1060 } else { |
| 1061 fprintf(stderr, "Unsupported module file: %s\n", obj_file.c_str()); |
| 1062 return false; |
| 1063 } |
| 1064 |
| 1065 return module->Write(sym_stream, ALL_SYMBOL_DATA); |
| 1066 } |
| 1067 |
1015 bool ReadSymbolData(const string& obj_file, | 1068 bool ReadSymbolData(const string& obj_file, |
1016 const std::vector<string>& debug_dirs, | 1069 const std::vector<string>& debug_dirs, |
1017 const DumpOptions& options, | 1070 const DumpOptions& options, |
1018 Module** module) { | 1071 Module** module) { |
1019 MmapWrapper map_wrapper; | 1072 MmapWrapper map_wrapper; |
1020 void* elf_header = NULL; | 1073 void* elf_header = NULL; |
1021 if (!LoadELF(obj_file, &map_wrapper, &elf_header)) | 1074 if (!LoadELF(obj_file, &map_wrapper, &elf_header)) |
1022 return false; | 1075 return false; |
1023 | 1076 |
1024 return ReadSymbolDataInternal(reinterpret_cast<uint8_t*>(elf_header), | 1077 return ReadSymbolDataInternal(reinterpret_cast<uint8_t*>(elf_header), |
1025 obj_file, debug_dirs, options, module); | 1078 obj_file, debug_dirs, options, module); |
1026 } | 1079 } |
1027 | 1080 |
1028 } // namespace google_breakpad | 1081 } // namespace google_breakpad |
OLD | NEW |