Index: source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h =================================================================== --- source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h +++ source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h @@ -50,6 +50,10 @@ const lldb_private::FileSpec *file, lldb::offset_t file_offset, lldb::offset_t length); + ObjectFilePECOFF(const lldb::ModuleSP &module_sp, + lldb::DataBufferSP &header_data_sp, + const lldb::ProcessSP &process_sp, lldb::addr_t header_addr); + ~ObjectFilePECOFF() override; //------------------------------------------------------------------ @@ -131,29 +135,31 @@ bool IsThumb(); -protected: - bool NeedsEndianSwap() const; - - typedef struct dos_header { // DOS .EXE header - uint16_t e_magic; // Magic number - uint16_t e_cblp; // Bytes on last page of file - uint16_t e_cp; // Pages in file - uint16_t e_crlc; // Relocations - uint16_t e_cparhdr; // Size of header in paragraphs - uint16_t e_minalloc; // Minimum extra paragraphs needed - uint16_t e_maxalloc; // Maximum extra paragraphs needed - uint16_t e_ss; // Initial (relative) SS value - uint16_t e_sp; // Initial SP value - uint16_t e_csum; // Checksum - uint16_t e_ip; // Initial IP value - uint16_t e_cs; // Initial (relative) CS value - uint16_t e_lfarlc; // File address of relocation table - uint16_t e_ovno; // Overlay number - uint16_t e_res[4]; // Reserved words - uint16_t e_oemid; // OEM identifier (for e_oeminfo) - uint16_t e_oeminfo; // OEM information; e_oemid specific - uint16_t e_res2[10]; // Reserved words - uint32_t e_lfanew; // File address of new exe header + lldb_private::DataExtractor ReadImageData(uint32_t offset, size_t size); + + protected: + bool NeedsEndianSwap() const; + + typedef struct dos_header { // DOS .EXE header + uint16_t e_magic; // Magic number + uint16_t e_cblp; // Bytes on last page of file + uint16_t e_cp; // Pages in file + uint16_t e_crlc; // Relocations + uint16_t e_cparhdr; // Size of header in paragraphs + uint16_t e_minalloc; // Minimum extra paragraphs needed + uint16_t e_maxalloc; // Maximum extra paragraphs needed + uint16_t e_ss; // Initial (relative) SS value + uint16_t e_sp; // Initial SP value + uint16_t e_csum; // Checksum + uint16_t e_ip; // Initial IP value + uint16_t e_cs; // Initial (relative) CS value + uint16_t e_lfarlc; // File address of relocation table + uint16_t e_ovno; // Overlay number + uint16_t e_res[4]; // Reserved words + uint16_t e_oemid; // OEM identifier (for e_oeminfo) + uint16_t e_oeminfo; // OEM information; e_oemid specific + uint16_t e_res2[10]; // Reserved words + uint32_t e_lfanew; // File address of new exe header } dos_header_t; typedef struct coff_header { Index: source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp =================================================================== --- source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp +++ source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp @@ -10,10 +10,12 @@ #include "ObjectFilePECOFF.h" #include "WindowsMiniDump.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/Support/COFF.h" #include "lldb/Core/ArchSpec.h" #include "lldb/Core/DataBuffer.h" +#include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/FileSpecList.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" @@ -83,7 +85,15 @@ ObjectFile *ObjectFilePECOFF::CreateMemoryInstance( const lldb::ModuleSP &module_sp, lldb::DataBufferSP &data_sp, const lldb::ProcessSP &process_sp, lldb::addr_t header_addr) { - return NULL; + if (!data_sp || !ObjectFilePECOFF::MagicBytesMatch(data_sp)) { + return nullptr; + } + auto objfile_ap = llvm::make_unique( + module_sp, data_sp, process_sp, header_addr); + if (objfile_ap.get() && objfile_ap->ParseHeader()) { + return objfile_ap.release(); + } + return nullptr; } size_t ObjectFilePECOFF::GetModuleSpecifications( @@ -164,6 +174,18 @@ ::memset(&m_coff_header_opt, 0, sizeof(m_coff_header_opt)); } +ObjectFilePECOFF::ObjectFilePECOFF(const lldb::ModuleSP &module_sp, + DataBufferSP &header_data_sp, + const lldb::ProcessSP &process_sp, + addr_t header_addr) + : ObjectFile(module_sp, process_sp, header_addr, header_data_sp), + m_dos_header(), m_coff_header(), m_coff_header_opt(), m_sect_headers(), + m_entry_point_address() { + ::memset(&m_dos_header, 0, sizeof(m_dos_header)); + ::memset(&m_coff_header, 0, sizeof(m_coff_header)); + ::memset(&m_coff_header_opt, 0, sizeof(m_coff_header_opt)); +} + ObjectFilePECOFF::~ObjectFilePECOFF() {} bool ObjectFilePECOFF::ParseHeader() { @@ -399,6 +421,28 @@ return success; } +DataExtractor ObjectFilePECOFF::ReadImageData(uint32_t offset, size_t size) { + if (m_file) { + DataBufferSP buffer_sp(m_file.ReadFileContents(offset, size)); + return DataExtractor(buffer_sp, GetByteOrder(), GetAddressByteSize()); + } + + DataExtractor data; + ProcessSP process_sp(m_process_wp.lock()); + if (process_sp) { + auto data_ap = llvm::make_unique(size, 0); + Error readmem_error; + size_t bytes_read = + process_sp->ReadMemory(m_image_base + offset, data_ap->GetBytes(), + data_ap->GetByteSize(), readmem_error); + if (bytes_read == size) { + DataBufferSP buffer_sp(data_ap.release()); + data.SetData(buffer_sp, 0, buffer_sp->GetByteSize()); + } + } + return data; +} + //---------------------------------------------------------------------- // ParseSectionHeaders //---------------------------------------------------------------------- @@ -408,12 +452,9 @@ m_sect_headers.clear(); if (nsects > 0) { - const uint32_t addr_byte_size = GetAddressByteSize(); const size_t section_header_byte_size = nsects * sizeof(section_header_t); - DataBufferSP section_header_data_sp(m_file.ReadFileContents( - section_header_data_offset, section_header_byte_size)); - DataExtractor section_header_data(section_header_data_sp, GetByteOrder(), - addr_byte_size); + DataExtractor section_header_data = + ReadImageData(section_header_data_offset, section_header_byte_size); lldb::offset_t offset = 0; if (section_header_data.ValidOffsetForDataOfSize( @@ -475,66 +516,67 @@ if (num_syms > 0 && m_coff_header.symoff > 0) { const uint32_t symbol_size = 18; - const uint32_t addr_byte_size = GetAddressByteSize(); const size_t symbol_data_size = num_syms * symbol_size; // Include the 4-byte string table size at the end of the symbols - DataBufferSP symtab_data_sp(m_file.ReadFileContents( - m_coff_header.symoff, symbol_data_size + 4)); - DataExtractor symtab_data(symtab_data_sp, GetByteOrder(), - addr_byte_size); - lldb::offset_t offset = symbol_data_size; - const uint32_t strtab_size = symtab_data.GetU32(&offset); - DataBufferSP strtab_data_sp(m_file.ReadFileContents( - m_coff_header.symoff + symbol_data_size, strtab_size)); - DataExtractor strtab_data(strtab_data_sp, GetByteOrder(), - addr_byte_size); - - // First 4 bytes should be zeroed after strtab_size has been read, - // because it is used as offset 0 to encode a NULL string. - uint32_t *strtab_data_start = (uint32_t *)strtab_data_sp->GetBytes(); - strtab_data_start[0] = 0; - - offset = 0; - std::string symbol_name; - Symbol *symbols = m_symtab_ap->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 = NULL; - // 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 == NULL) - 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->GetSectionAtIndex(symbol.sect - 1), - symbol.value); - symbols[i].GetAddressRef() = symbol_addr; - symbols[i].SetType(MapSymbolType(symbol.type)); - } - - if (symbol.naux > 0) { - i += symbol.naux; - offset += symbol_size; + DataExtractor symtab_data = + ReadImageData(m_coff_header.symoff, symbol_data_size + 4); + if (symtab_data.GetDataStart() != nullptr) { + lldb::offset_t offset = symbol_data_size; + const uint32_t strtab_size = symtab_data.GetU32(&offset); + DataExtractor strtab_data = ReadImageData( + m_coff_header.symoff + symbol_data_size, strtab_size); + if (strtab_data.GetDataStart() != nullptr) { + // First 4 bytes should be zeroed after strtab_size has been read, + // because it is used as offset 0 to encode a NULL string. + uint32_t *strtab_data_start = + (uint32_t *)strtab_data.GetDataStart(); + strtab_data_start[0] = 0; + + offset = 0; + std::string symbol_name; + Symbol *symbols = m_symtab_ap->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 = NULL; + // 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 == NULL) + 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->GetSectionAtIndex(symbol.sect - 1), + symbol.value); + symbols[i].GetAddressRef() = symbol_addr; + symbols[i].SetType(MapSymbolType(symbol.type)); + } + + if (symbol.naux > 0) { + i += symbol.naux; + offset += symbol_size; + } + } } } } @@ -547,11 +589,10 @@ uint32_t data_start = m_coff_header_opt.data_dirs[coff_data_dir_export_table].vmaddr; Address address(m_coff_header_opt.image_base + data_start, sect_list); - DataBufferSP symtab_data_sp(m_file.ReadFileContents( - address.GetSection()->GetFileOffset() + address.GetOffset(), - m_coff_header_opt.data_dirs[0].vmsize)); - DataExtractor symtab_data(symtab_data_sp, GetByteOrder(), - GetAddressByteSize()); + DataExtractor symtab_data = ReadImageData( + address.GetSection()->GetFileOffset() + address.GetOffset() - + m_coff_header_opt.image_base, + m_coff_header_opt.data_dirs[0].vmsize); lldb::offset_t offset = 0; // Read export_table header