|
30 | 30 | #include "lldb/Utility/StreamString.h"
|
31 | 31 | #include "lldb/Utility/Timer.h"
|
32 | 32 | #include "lldb/Utility/UUID.h"
|
33 |
| -#include "llvm/BinaryFormat/COFF.h" |
34 | 33 |
|
| 34 | +#include "llvm/BinaryFormat/COFF.h" |
35 | 35 | #include "llvm/Object/COFFImportFile.h"
|
36 | 36 | #include "llvm/Support/CRC.h"
|
37 | 37 | #include "llvm/Support/Error.h"
|
| 38 | +#include "llvm/Support/FormatAdapters.h" |
38 | 39 | #include "llvm/Support/Host.h"
|
39 | 40 | #include "llvm/Support/MemoryBuffer.h"
|
40 | 41 |
|
@@ -760,131 +761,93 @@ llvm::StringRef ObjectFilePECOFF::GetSectionName(const section_header_t §) {
|
760 | 761 |
|
761 | 762 | void ObjectFilePECOFF::ParseSymtab(Symtab &symtab) {
|
762 | 763 | SectionList *sect_list = GetSectionList();
|
763 |
| - const uint32_t num_syms = m_coff_header.nsyms; |
764 |
| - if (m_file && num_syms > 0 && m_coff_header.symoff > 0) { |
765 |
| - const uint32_t symbol_size = 18; |
766 |
| - const size_t symbol_data_size = num_syms * symbol_size; |
767 |
| - // Include the 4-byte string table size at the end of the symbols |
768 |
| - DataExtractor symtab_data = |
769 |
| - ReadImageData(m_coff_header.symoff, symbol_data_size + 4); |
770 |
| - lldb::offset_t offset = symbol_data_size; |
771 |
| - const uint32_t strtab_size = symtab_data.GetU32(&offset); |
772 |
| - if (strtab_size > 0) { |
773 |
| - DataExtractor strtab_data = ReadImageData( |
774 |
| - m_coff_header.symoff + symbol_data_size, strtab_size); |
775 |
| - |
776 |
| - offset = 0; |
777 |
| - std::string symbol_name; |
778 |
| - Symbol *symbols = symtab.Resize(num_syms); |
779 |
| - for (uint32_t i = 0; i < num_syms; ++i) { |
780 |
| - coff_symbol_t symbol; |
781 |
| - const uint32_t symbol_offset = offset; |
782 |
| - const char *symbol_name_cstr = nullptr; |
783 |
| - // If the first 4 bytes of the symbol string are zero, then they |
784 |
| - // are followed by a 4-byte string table offset. Else these |
785 |
| - // 8 bytes contain the symbol name |
786 |
| - if (symtab_data.GetU32(&offset) == 0) { |
787 |
| - // Long string that doesn't fit into the symbol table name, so |
788 |
| - // now we must read the 4 byte string table offset |
789 |
| - uint32_t strtab_offset = symtab_data.GetU32(&offset); |
790 |
| - symbol_name_cstr = strtab_data.PeekCStr(strtab_offset); |
791 |
| - symbol_name.assign(symbol_name_cstr); |
792 |
| - } else { |
793 |
| - // Short string that fits into the symbol table name which is 8 |
794 |
| - // bytes |
795 |
| - offset += sizeof(symbol.name) - 4; // Skip remaining |
796 |
| - symbol_name_cstr = symtab_data.PeekCStr(symbol_offset); |
797 |
| - if (symbol_name_cstr == nullptr) |
798 |
| - break; |
799 |
| - symbol_name.assign(symbol_name_cstr, sizeof(symbol.name)); |
800 |
| - } |
801 |
| - symbol.value = symtab_data.GetU32(&offset); |
802 |
| - symbol.sect = symtab_data.GetU16(&offset); |
803 |
| - symbol.type = symtab_data.GetU16(&offset); |
804 |
| - symbol.storage = symtab_data.GetU8(&offset); |
805 |
| - symbol.naux = symtab_data.GetU8(&offset); |
806 |
| - symbols[i].GetMangled().SetValue(ConstString(symbol_name.c_str())); |
807 |
| - if ((int16_t)symbol.sect >= 1) { |
808 |
| - Address symbol_addr(sect_list->FindSectionByID(symbol.sect), |
809 |
| - symbol.value); |
810 |
| - symbols[i].GetAddressRef() = symbol_addr; |
811 |
| - symbols[i].SetType(MapSymbolType(symbol.type)); |
812 |
| - } |
| 764 | + AppendFromExportTable(sect_list, symtab); |
| 765 | + AppendFromCOFFSymbolTable(sect_list, symtab); |
| 766 | +} |
813 | 767 |
|
814 |
| - if (symbol.naux > 0) { |
815 |
| - i += symbol.naux; |
816 |
| - offset += symbol.naux * symbol_size; |
817 |
| - } |
818 |
| - } |
| 768 | +void ObjectFilePECOFF::AppendFromCOFFSymbolTable(SectionList *sect_list, |
| 769 | + Symtab &symtab) { |
| 770 | + const uint32_t num_syms = m_binary->getNumberOfSymbols(); |
| 771 | + if (num_syms == 0) |
| 772 | + return; |
| 773 | + // Check that this is not a bigobj; we do not support bigobj. |
| 774 | + if (m_binary->getSymbolTableEntrySize() != |
| 775 | + sizeof(llvm::object::coff_symbol16)) |
| 776 | + return; |
| 777 | + |
| 778 | + Log *log = GetLog(LLDBLog::Object); |
| 779 | + symtab.Reserve(symtab.GetNumSymbols() + num_syms); |
| 780 | + for (const auto &sym_ref : m_binary->symbols()) { |
| 781 | + const auto coff_sym_ref = m_binary->getCOFFSymbol(sym_ref); |
| 782 | + auto name_or_error = sym_ref.getName(); |
| 783 | + if (auto err = name_or_error.takeError()) { |
| 784 | + LLDB_LOG(log, |
| 785 | + "ObjectFilePECOFF::AppendFromCOFFSymbolTable - failed to get " |
| 786 | + "symbol table entry name: {0}", |
| 787 | + llvm::fmt_consume(std::move(err))); |
| 788 | + continue; |
| 789 | + } |
| 790 | + const llvm::StringRef sym_name = *name_or_error; |
| 791 | + Symbol symbol; |
| 792 | + symbol.GetMangled().SetValue(ConstString(sym_name)); |
| 793 | + int16_t section_number = |
| 794 | + static_cast<int16_t>(coff_sym_ref.getSectionNumber()); |
| 795 | + if (section_number >= 1) { |
| 796 | + symbol.GetAddressRef() = Address( |
| 797 | + sect_list->FindSectionByID(section_number), coff_sym_ref.getValue()); |
| 798 | + symbol.SetType(MapSymbolType(coff_sym_ref.getType())); |
819 | 799 | }
|
| 800 | + symtab.AddSymbol(symbol); |
820 | 801 | }
|
| 802 | +} |
821 | 803 |
|
822 |
| - // Read export header |
823 |
| - if (coff_data_dir_export_table < m_coff_header_opt.data_dirs.size() && |
824 |
| - m_coff_header_opt.data_dirs[coff_data_dir_export_table].vmsize > 0 && |
825 |
| - m_coff_header_opt.data_dirs[coff_data_dir_export_table].vmaddr > 0) { |
826 |
| - export_directory_entry export_table; |
827 |
| - uint32_t data_start = |
828 |
| - m_coff_header_opt.data_dirs[coff_data_dir_export_table].vmaddr; |
829 |
| - |
830 |
| - DataExtractor symtab_data = ReadImageDataByRVA( |
831 |
| - data_start, m_coff_header_opt.data_dirs[0].vmsize); |
832 |
| - lldb::offset_t offset = 0; |
| 804 | +void ObjectFilePECOFF::AppendFromExportTable(SectionList *sect_list, |
| 805 | + Symtab &symtab) { |
| 806 | + const auto *export_table = m_binary->getExportTable(); |
| 807 | + if (!export_table) |
| 808 | + return; |
| 809 | + const uint32_t num_syms = export_table->AddressTableEntries; |
| 810 | + if (num_syms == 0) |
| 811 | + return; |
833 | 812 |
|
834 |
| - // Read export_table header |
835 |
| - export_table.characteristics = symtab_data.GetU32(&offset); |
836 |
| - export_table.time_date_stamp = symtab_data.GetU32(&offset); |
837 |
| - export_table.major_version = symtab_data.GetU16(&offset); |
838 |
| - export_table.minor_version = symtab_data.GetU16(&offset); |
839 |
| - export_table.name = symtab_data.GetU32(&offset); |
840 |
| - export_table.base = symtab_data.GetU32(&offset); |
841 |
| - export_table.number_of_functions = symtab_data.GetU32(&offset); |
842 |
| - export_table.number_of_names = symtab_data.GetU32(&offset); |
843 |
| - export_table.address_of_functions = symtab_data.GetU32(&offset); |
844 |
| - export_table.address_of_names = symtab_data.GetU32(&offset); |
845 |
| - export_table.address_of_name_ordinals = symtab_data.GetU32(&offset); |
846 |
| - |
847 |
| - bool has_ordinal = export_table.address_of_name_ordinals != 0; |
848 |
| - |
849 |
| - lldb::offset_t name_offset = export_table.address_of_names - data_start; |
850 |
| - lldb::offset_t name_ordinal_offset = |
851 |
| - export_table.address_of_name_ordinals - data_start; |
852 |
| - |
853 |
| - Symbol *symbols = symtab.Resize(export_table.number_of_names); |
854 |
| - |
855 |
| - std::string symbol_name; |
856 |
| - |
857 |
| - // Read each export table entry |
858 |
| - for (size_t i = 0; i < export_table.number_of_names; ++i) { |
859 |
| - uint32_t name_ordinal = |
860 |
| - has_ordinal ? symtab_data.GetU16(&name_ordinal_offset) : i; |
861 |
| - uint32_t name_address = symtab_data.GetU32(&name_offset); |
862 |
| - |
863 |
| - const char *symbol_name_cstr = |
864 |
| - symtab_data.PeekCStr(name_address - data_start); |
865 |
| - symbol_name.assign(symbol_name_cstr); |
866 |
| - |
867 |
| - lldb::offset_t function_offset = export_table.address_of_functions - |
868 |
| - data_start + |
869 |
| - sizeof(uint32_t) * name_ordinal; |
870 |
| - uint32_t function_rva = symtab_data.GetU32(&function_offset); |
871 |
| - |
872 |
| - Address symbol_addr(m_coff_header_opt.image_base + function_rva, |
873 |
| - sect_list); |
874 |
| - symbols[i].GetMangled().SetValue(ConstString(symbol_name.c_str())); |
875 |
| - symbols[i].GetAddressRef() = symbol_addr; |
876 |
| - symbols[i].SetType(lldb::eSymbolTypeCode); |
877 |
| - symbols[i].SetDebug(true); |
| 813 | + Log *log = GetLog(LLDBLog::Object); |
| 814 | + symtab.Reserve(symtab.GetNumSymbols() + num_syms); |
| 815 | + // Read each export table entry, ordered by ordinal instead of by name. |
| 816 | + for (const auto &entry : m_binary->export_directories()) { |
| 817 | + llvm::StringRef sym_name; |
| 818 | + if (auto err = entry.getSymbolName(sym_name)) { |
| 819 | + LLDB_LOG(log, |
| 820 | + "ObjectFilePECOFF::AppendFromExportTable - failed to get export " |
| 821 | + "table entry name: {0}", |
| 822 | + llvm::fmt_consume(std::move(err))); |
| 823 | + continue; |
| 824 | + } |
| 825 | + Symbol symbol; |
| 826 | + // Note: symbol name may be empty if it is only exported by ordinal. |
| 827 | + symbol.GetMangled().SetValue(ConstString(sym_name)); |
| 828 | + |
| 829 | + uint32_t function_rva; |
| 830 | + if (auto err = entry.getExportRVA(function_rva)) { |
| 831 | + LLDB_LOG(log, |
| 832 | + "ObjectFilePECOFF::AppendFromExportTable - failed to get " |
| 833 | + "address of export entry '{0}': {1}", |
| 834 | + sym_name, llvm::fmt_consume(std::move(err))); |
| 835 | + continue; |
878 | 836 | }
|
| 837 | + symbol.GetAddressRef() = |
| 838 | + Address(m_coff_header_opt.image_base + function_rva, sect_list); |
| 839 | + symbol.SetType(lldb::eSymbolTypeCode); |
| 840 | + symbol.SetDebug(true); |
| 841 | + symtab.AddSymbol(symbol); |
879 | 842 | }
|
880 | 843 | }
|
881 | 844 |
|
882 | 845 | std::unique_ptr<CallFrameInfo> ObjectFilePECOFF::CreateCallFrameInfo() {
|
883 |
| - if (coff_data_dir_exception_table >= m_coff_header_opt.data_dirs.size()) |
| 846 | + if (llvm::COFF::EXCEPTION_TABLE >= m_coff_header_opt.data_dirs.size()) |
884 | 847 | return {};
|
885 | 848 |
|
886 | 849 | data_directory data_dir_exception =
|
887 |
| - m_coff_header_opt.data_dirs[coff_data_dir_exception_table]; |
| 850 | + m_coff_header_opt.data_dirs[llvm::COFF::EXCEPTION_TABLE]; |
888 | 851 | if (!data_dir_exception.vmaddr)
|
889 | 852 | return {};
|
890 | 853 |
|
|
0 commit comments