aboutsummaryrefslogtreecommitdiff
path: root/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp')
-rw-r--r--lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp189
1 files changed, 76 insertions, 113 deletions
diff --git a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
index 5e7a921..3890e8b 100644
--- a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
+++ b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
@@ -30,11 +30,12 @@
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/Timer.h"
#include "lldb/Utility/UUID.h"
-#include "llvm/BinaryFormat/COFF.h"
+#include "llvm/BinaryFormat/COFF.h"
#include "llvm/Object/COFFImportFile.h"
#include "llvm/Support/CRC.h"
#include "llvm/Support/Error.h"
+#include "llvm/Support/FormatAdapters.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -760,131 +761,93 @@ llvm::StringRef ObjectFilePECOFF::GetSectionName(const section_header_t &sect) {
void ObjectFilePECOFF::ParseSymtab(Symtab &symtab) {
SectionList *sect_list = GetSectionList();
- const uint32_t num_syms = m_coff_header.nsyms;
- if (m_file && num_syms > 0 && m_coff_header.symoff > 0) {
- const uint32_t symbol_size = 18;
- const size_t symbol_data_size = num_syms * symbol_size;
- // Include the 4-byte string table size at the end of the symbols
- DataExtractor symtab_data =
- ReadImageData(m_coff_header.symoff, symbol_data_size + 4);
- lldb::offset_t offset = symbol_data_size;
- const uint32_t strtab_size = symtab_data.GetU32(&offset);
- if (strtab_size > 0) {
- DataExtractor strtab_data = ReadImageData(
- m_coff_header.symoff + symbol_data_size, strtab_size);
-
- offset = 0;
- std::string symbol_name;
- Symbol *symbols = symtab.Resize(num_syms);
- for (uint32_t i = 0; i < num_syms; ++i) {
- coff_symbol_t symbol;
- const uint32_t symbol_offset = offset;
- const char *symbol_name_cstr = nullptr;
- // If the first 4 bytes of the symbol string are zero, then they
- // are followed by a 4-byte string table offset. Else these
- // 8 bytes contain the symbol name
- if (symtab_data.GetU32(&offset) == 0) {
- // Long string that doesn't fit into the symbol table name, so
- // now we must read the 4 byte string table offset
- uint32_t strtab_offset = symtab_data.GetU32(&offset);
- symbol_name_cstr = strtab_data.PeekCStr(strtab_offset);
- symbol_name.assign(symbol_name_cstr);
- } else {
- // Short string that fits into the symbol table name which is 8
- // bytes
- offset += sizeof(symbol.name) - 4; // Skip remaining
- symbol_name_cstr = symtab_data.PeekCStr(symbol_offset);
- if (symbol_name_cstr == nullptr)
- break;
- symbol_name.assign(symbol_name_cstr, sizeof(symbol.name));
- }
- symbol.value = symtab_data.GetU32(&offset);
- symbol.sect = symtab_data.GetU16(&offset);
- symbol.type = symtab_data.GetU16(&offset);
- symbol.storage = symtab_data.GetU8(&offset);
- symbol.naux = symtab_data.GetU8(&offset);
- symbols[i].GetMangled().SetValue(ConstString(symbol_name.c_str()));
- if ((int16_t)symbol.sect >= 1) {
- Address symbol_addr(sect_list->FindSectionByID(symbol.sect),
- symbol.value);
- symbols[i].GetAddressRef() = symbol_addr;
- symbols[i].SetType(MapSymbolType(symbol.type));
- }
+ AppendFromExportTable(sect_list, symtab);
+ AppendFromCOFFSymbolTable(sect_list, symtab);
+}
- if (symbol.naux > 0) {
- i += symbol.naux;
- offset += symbol.naux * symbol_size;
- }
- }
+void ObjectFilePECOFF::AppendFromCOFFSymbolTable(SectionList *sect_list,
+ Symtab &symtab) {
+ const uint32_t num_syms = m_binary->getNumberOfSymbols();
+ if (num_syms == 0)
+ return;
+ // Check that this is not a bigobj; we do not support bigobj.
+ if (m_binary->getSymbolTableEntrySize() !=
+ sizeof(llvm::object::coff_symbol16))
+ return;
+
+ Log *log = GetLog(LLDBLog::Object);
+ symtab.Reserve(symtab.GetNumSymbols() + num_syms);
+ for (const auto &sym_ref : m_binary->symbols()) {
+ const auto coff_sym_ref = m_binary->getCOFFSymbol(sym_ref);
+ auto name_or_error = sym_ref.getName();
+ if (auto err = name_or_error.takeError()) {
+ LLDB_LOG(log,
+ "ObjectFilePECOFF::AppendFromCOFFSymbolTable - failed to get "
+ "symbol table entry name: {0}",
+ llvm::fmt_consume(std::move(err)));
+ continue;
+ }
+ const llvm::StringRef sym_name = *name_or_error;
+ Symbol symbol;
+ symbol.GetMangled().SetValue(ConstString(sym_name));
+ int16_t section_number =
+ static_cast<int16_t>(coff_sym_ref.getSectionNumber());
+ if (section_number >= 1) {
+ symbol.GetAddressRef() = Address(
+ sect_list->FindSectionByID(section_number), coff_sym_ref.getValue());
+ symbol.SetType(MapSymbolType(coff_sym_ref.getType()));
}
+ symtab.AddSymbol(symbol);
}
+}
- // Read export header
- if (coff_data_dir_export_table < m_coff_header_opt.data_dirs.size() &&
- m_coff_header_opt.data_dirs[coff_data_dir_export_table].vmsize > 0 &&
- m_coff_header_opt.data_dirs[coff_data_dir_export_table].vmaddr > 0) {
- export_directory_entry export_table;
- uint32_t data_start =
- m_coff_header_opt.data_dirs[coff_data_dir_export_table].vmaddr;
-
- DataExtractor symtab_data = ReadImageDataByRVA(
- data_start, m_coff_header_opt.data_dirs[0].vmsize);
- lldb::offset_t offset = 0;
+void ObjectFilePECOFF::AppendFromExportTable(SectionList *sect_list,
+ Symtab &symtab) {
+ const auto *export_table = m_binary->getExportTable();
+ if (!export_table)
+ return;
+ const uint32_t num_syms = export_table->AddressTableEntries;
+ if (num_syms == 0)
+ return;
- // Read export_table header
- export_table.characteristics = symtab_data.GetU32(&offset);
- export_table.time_date_stamp = symtab_data.GetU32(&offset);
- export_table.major_version = symtab_data.GetU16(&offset);
- export_table.minor_version = symtab_data.GetU16(&offset);
- export_table.name = symtab_data.GetU32(&offset);
- export_table.base = symtab_data.GetU32(&offset);
- export_table.number_of_functions = symtab_data.GetU32(&offset);
- export_table.number_of_names = symtab_data.GetU32(&offset);
- export_table.address_of_functions = symtab_data.GetU32(&offset);
- export_table.address_of_names = symtab_data.GetU32(&offset);
- export_table.address_of_name_ordinals = symtab_data.GetU32(&offset);
-
- bool has_ordinal = export_table.address_of_name_ordinals != 0;
-
- lldb::offset_t name_offset = export_table.address_of_names - data_start;
- lldb::offset_t name_ordinal_offset =
- export_table.address_of_name_ordinals - data_start;
-
- Symbol *symbols = symtab.Resize(export_table.number_of_names);
-
- std::string symbol_name;
-
- // Read each export table entry
- for (size_t i = 0; i < export_table.number_of_names; ++i) {
- uint32_t name_ordinal =
- has_ordinal ? symtab_data.GetU16(&name_ordinal_offset) : i;
- uint32_t name_address = symtab_data.GetU32(&name_offset);
-
- const char *symbol_name_cstr =
- symtab_data.PeekCStr(name_address - data_start);
- symbol_name.assign(symbol_name_cstr);
-
- lldb::offset_t function_offset = export_table.address_of_functions -
- data_start +
- sizeof(uint32_t) * name_ordinal;
- uint32_t function_rva = symtab_data.GetU32(&function_offset);
-
- Address symbol_addr(m_coff_header_opt.image_base + function_rva,
- sect_list);
- symbols[i].GetMangled().SetValue(ConstString(symbol_name.c_str()));
- symbols[i].GetAddressRef() = symbol_addr;
- symbols[i].SetType(lldb::eSymbolTypeCode);
- symbols[i].SetDebug(true);
+ Log *log = GetLog(LLDBLog::Object);
+ symtab.Reserve(symtab.GetNumSymbols() + num_syms);
+ // Read each export table entry, ordered by ordinal instead of by name.
+ for (const auto &entry : m_binary->export_directories()) {
+ llvm::StringRef sym_name;
+ if (auto err = entry.getSymbolName(sym_name)) {
+ LLDB_LOG(log,
+ "ObjectFilePECOFF::AppendFromExportTable - failed to get export "
+ "table entry name: {0}",
+ llvm::fmt_consume(std::move(err)));
+ continue;
+ }
+ Symbol symbol;
+ // Note: symbol name may be empty if it is only exported by ordinal.
+ symbol.GetMangled().SetValue(ConstString(sym_name));
+
+ uint32_t function_rva;
+ if (auto err = entry.getExportRVA(function_rva)) {
+ LLDB_LOG(log,
+ "ObjectFilePECOFF::AppendFromExportTable - failed to get "
+ "address of export entry '{0}': {1}",
+ sym_name, llvm::fmt_consume(std::move(err)));
+ continue;
}
+ symbol.GetAddressRef() =
+ Address(m_coff_header_opt.image_base + function_rva, sect_list);
+ symbol.SetType(lldb::eSymbolTypeCode);
+ symbol.SetDebug(true);
+ symtab.AddSymbol(symbol);
}
}
std::unique_ptr<CallFrameInfo> ObjectFilePECOFF::CreateCallFrameInfo() {
- if (coff_data_dir_exception_table >= m_coff_header_opt.data_dirs.size())
+ if (llvm::COFF::EXCEPTION_TABLE >= m_coff_header_opt.data_dirs.size())
return {};
data_directory data_dir_exception =
- m_coff_header_opt.data_dirs[coff_data_dir_exception_table];
+ m_coff_header_opt.data_dirs[llvm::COFF::EXCEPTION_TABLE];
if (!data_dir_exception.vmaddr)
return {};