Quick fixes to the PE COFF file loader.

llvm-svn: 139448
This commit is contained in:
Greg Clayton 2011-09-10 01:04:42 +00:00
parent 28dda8eebc
commit 28469ca3a5
2 changed files with 160 additions and 44 deletions

View File

@ -72,6 +72,46 @@ static uint32_t COFFMachineToMachCPU(uint16_t machine);
#define IMAGE_FILE_UP_SYSTEM_ONLY 0x4000
#define IMAGE_FILE_BYTES_REVERSED_HI 0x8000
// Section Flags
// The section flags in the Characteristics field of the section header indicate
// characteristics of the section.
#define IMAGE_SCN_TYPE_NO_PAD 0x00000008 // The section should not be padded to the next boundary. This flag is obsolete and is replaced by IMAGE_SCN_ALIGN_1BYTES. This is valid only for object files.
#define IMAGE_SCN_CNT_CODE 0x00000020 // The section contains executable code.
#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 // The section contains initialized data.
#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 // The section contains uninitialized data.
#define IMAGE_SCN_LNK_OTHER 0x00000100 // Reserved for future use.
#define IMAGE_SCN_LNK_INFO 0x00000200 // The section contains comments or other information. The .drectve section has this type. This is valid for object files only.
#define IMAGE_SCN_LNK_REMOVE 0x00000800 // The section will not become part of the image. This is valid only for object files.
#define IMAGE_SCN_LNK_COMDAT 0x00001000 // The section contains COMDAT data. For more information, see section 5.5.6, “COMDAT Sections (Object Only).” This is valid only for object files.
#define IMAGE_SCN_GPREL 0x00008000 // The section contains data referenced through the global pointer (GP).
#define IMAGE_SCN_MEM_PURGEABLE 0x00020000
#define IMAGE_SCN_MEM_16BIT 0x00020000 // For ARM machine types, the section contains Thumb code. Reserved for future use with other machine types.
#define IMAGE_SCN_MEM_LOCKED 0x00040000
#define IMAGE_SCN_MEM_PRELOAD 0x00080000
#define IMAGE_SCN_ALIGN_1BYTES 0x00100000 // Align data on a 1-byte boundary. Valid only for object files.
#define IMAGE_SCN_ALIGN_2BYTES 0x00200000 // Align data on a 2-byte boundary. Valid only for object files.
#define IMAGE_SCN_ALIGN_4BYTES 0x00300000 // Align data on a 4-byte boundary. Valid only for object files.
#define IMAGE_SCN_ALIGN_8BYTES 0x00400000 // Align data on an 8-byte boundary. Valid only for object files.
#define IMAGE_SCN_ALIGN_16BYTES 0x00500000 // Align data on a 16-byte boundary. Valid only for object files.
#define IMAGE_SCN_ALIGN_32BYTES 0x00600000 // Align data on a 32-byte boundary. Valid only for object files.
#define IMAGE_SCN_ALIGN_64BYTES 0x00700000 // Align data on a 64-byte boundary. Valid only for object files.
#define IMAGE_SCN_ALIGN_128BYTES 0x00800000 // Align data on a 128-byte boundary. Valid only for object files.
#define IMAGE_SCN_ALIGN_256BYTES 0x00900000 // Align data on a 256-byte boundary. Valid only for object files.
#define IMAGE_SCN_ALIGN_512BYTES 0x00A00000 // Align data on a 512-byte boundary. Valid only for object files.
#define IMAGE_SCN_ALIGN_1024BYTES 0x00B00000 // Align data on a 1024-byte boundary. Valid only for object files.
#define IMAGE_SCN_ALIGN_2048BYTES 0x00C00000 // Align data on a 2048-byte boundary. Valid only for object files.
#define IMAGE_SCN_ALIGN_4096BYTES 0x00D00000 // Align data on a 4096-byte boundary. Valid only for object files.
#define IMAGE_SCN_ALIGN_8192BYTES 0x00E00000 // Align data on an 8192-byte boundary. Valid only for object files.
#define IMAGE_SCN_LNK_NRELOC_OVFL 0x01000000 // The section contains extended relocations.
#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000 // The section can be discarded as needed.
#define IMAGE_SCN_MEM_NOT_CACHED 0x04000000 // The section cannot be cached.
#define IMAGE_SCN_MEM_NOT_PAGED 0x08000000 // The section is not pageable.
#define IMAGE_SCN_MEM_SHARED 0x10000000 // The section can be shared in memory.
#define IMAGE_SCN_MEM_EXECUTE 0x20000000 // The section can be executed as code.
#define IMAGE_SCN_MEM_READ 0x40000000 // The section can be read.
#define IMAGE_SCN_MEM_WRITE 0x80000000 // The section can be written to.
using namespace lldb;
using namespace lldb_private;
@ -162,12 +202,14 @@ ObjectFilePECOFF::ParseHeader ()
uint32_t pe_signature = m_data.GetU32 (&offset);
if (pe_signature != IMAGE_NT_SIGNATURE)
return false;
}
if (ParseCOFFHeader(&offset))
{
if (m_coff_header.hdrsize > 0)
ParseCOFFOptionalHeader(&offset);
ParseSectionHeaders (offset);
if (ParseCOFFHeader(&offset))
{
if (m_coff_header.hdrsize > 0)
ParseCOFFOptionalHeader(&offset);
ParseSectionHeaders (offset);
}
StreamFile s(stdout, false);// REMOVE THIS LINE!!!
Dump(&s);// REMOVE THIS LINE!!!
return true;
}
return false;
@ -334,7 +376,7 @@ ObjectFilePECOFF::ParseCOFFOptionalHeader(uint32_t* offset_ptr)
m_coff_header_opt.reserved1 = m_data.GetU32(offset_ptr);
m_coff_header_opt.image_size = m_data.GetU32(offset_ptr);
m_coff_header_opt.header_size = m_data.GetU32(offset_ptr);
m_coff_header_opt.checksym = m_data.GetU32(offset_ptr);
m_coff_header_opt.checksum = m_data.GetU32(offset_ptr);
m_coff_header_opt.subsystem = m_data.GetU16(offset_ptr);
m_coff_header_opt.dll_flags = m_data.GetU16(offset_ptr);
m_coff_header_opt.stack_reserve_size = m_data.GetMaxU64 (offset_ptr, addr_byte_size);
@ -436,39 +478,57 @@ ObjectFilePECOFF::GetSymtab()
SectionList *sect_list = GetSectionList();
m_symtab_ap.reset(new Symtab(this));
Mutex::Locker symtab_locker (m_symtab_ap->GetMutex());
DataExtractor stab_data;
DataExtractor stabstr_data;
static ConstString g_stab_sect_name(".stab");
static ConstString g_stabstr_sect_name(".stabstr");
const Section *stab_section = sect_list->FindSectionByName (g_stab_sect_name).get();
if (stab_section == NULL)
return m_symtab_ap.get();
const Section *stabstr_section = sect_list->FindSectionByName (g_stabstr_sect_name).get();
if (stabstr_section == NULL)
return m_symtab_ap.get();
uint32_t offset = 0;
if (stab_section->ReadSectionDataFromObjectFile (this, stab_data) &&
stabstr_section->ReadSectionDataFromObjectFile (this, stabstr_data))
const uint32_t num_syms = m_coff_header.nsyms;
if (num_syms > 0 && m_coff_header.symoff > 0)
{
const uint32_t num_syms = stab_data.GetByteSize() / sizeof (coff_symbol_t);
const uint32_t symbol_size = sizeof(section_header_t);
const uint32_t addr_byte_size = GetAddressByteSize ();
const size_t symbol_data_size = num_syms * symbol_size;
// Include the 4 bytes 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);
uint32_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 + 4, strtab_size));
DataExtractor strtab_data (strtab_data_sp, GetByteOrder(), addr_byte_size);
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 void *name_data = stab_data.GetData(&offset, sizeof(symbol.name));
if (name_data == NULL)
break;
memcpy (symbol.name, name_data, sizeof(symbol.name));
symbol.value = stab_data.GetU32 (&offset);
symbol.sect = stab_data.GetU16 (&offset);
symbol.type = stab_data.GetU16 (&offset);
symbol.storage = stab_data.GetU8 (&offset);
symbol.naux = stab_data.GetU8 (&offset);
symbol.name[sizeof(symbol.name)-1] = '\0';
const uint32_t symbol_offset = offset;
const char *symbol_name_cstr = NULL;
// If the first 4 bytes of the symbol string are zero, then we
// it is 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);
Address symbol_addr(sect_list->GetSectionAtIndex(symbol.sect-1).get(), symbol.value);
symbols[i].GetMangled ().SetValue(symbol.name, symbol.name[0]=='_' && symbol.name[1] == 'Z');
symbols[i].GetMangled ().SetValue (symbol_name.c_str(), symbol_name[0]=='_' && symbol_name[1] == 'Z');
symbols[i].SetValue(symbol_addr);
if (symbol.naux > 0)
@ -495,14 +555,70 @@ ObjectFilePECOFF::GetSectionList()
std::string sect_name;
GetSectionName (sect_name, m_sect_headers[idx]);
ConstString const_sect_name (sect_name.c_str());
static ConstString g_code_sect_name (".code");
static ConstString g_CODE_sect_name ("CODE");
static ConstString g_data_sect_name (".data");
static ConstString g_DATA_sect_name ("DATA");
static ConstString g_bss_sect_name (".bss");
static ConstString g_BSS_sect_name ("BSS");
static ConstString g_debug_sect_name (".debug");
static ConstString g_reloc_sect_name (".reloc");
static ConstString g_stab_sect_name (".stab");
static ConstString g_stabstr_sect_name (".stabstr");
SectionType section_type = eSectionTypeOther;
if (m_sect_headers[idx].flags & IMAGE_SCN_CNT_CODE &&
((const_sect_name == g_code_sect_name) || (const_sect_name == g_CODE_sect_name)))
{
section_type = eSectionTypeCode;
}
else if (m_sect_headers[idx].flags & IMAGE_SCN_CNT_INITIALIZED_DATA &&
((const_sect_name == g_data_sect_name) || (const_sect_name == g_DATA_sect_name)))
{
section_type = eSectionTypeData;
}
else if (m_sect_headers[idx].flags & IMAGE_SCN_CNT_UNINITIALIZED_DATA &&
((const_sect_name == g_bss_sect_name) || (const_sect_name == g_BSS_sect_name)))
{
if (m_sect_headers[idx].size == 0)
section_type = eSectionTypeZeroFill;
else
section_type = eSectionTypeData;
}
else if (const_sect_name == g_debug_sect_name)
{
section_type = eSectionTypeDebug;
}
else if (const_sect_name == g_stabstr_sect_name)
{
section_type = eSectionTypeDataCString;
}
else if (const_sect_name == g_reloc_sect_name)
{
section_type = eSectionTypeOther;
}
else if (m_sect_headers[idx].flags & IMAGE_SCN_CNT_CODE)
{
section_type = eSectionTypeCode;
}
else if (m_sect_headers[idx].flags & IMAGE_SCN_CNT_INITIALIZED_DATA)
{
section_type = eSectionTypeData;
}
else if (m_sect_headers[idx].flags & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
{
if (m_sect_headers[idx].size == 0)
section_type = eSectionTypeZeroFill;
else
section_type = eSectionTypeData;
}
// Use a segment ID of the segment index shifted left by 8 so they
// never conflict with any of the sections.
SectionSP section_sp (new Section (NULL,
module, // Module to which this section belongs
idx + 1, // Section ID is the 1 based segment index shifted right by 8 bits as not to collide with any of the 256 section IDs that are possible
const_sect_name, // Name of this section
eSectionTypeCode, // This section is a container of other sections.
section_type, // This section is a container of other sections.
m_sect_headers[idx].vmaddr, // File VM address == addresses as they are found in the object file
m_sect_headers[idx].vmsize, // VM size in bytes of this section
m_sect_headers[idx].offset, // Offset to the data for this section in the file
@ -659,7 +775,7 @@ ObjectFilePECOFF::DumpOptCOFFHeader(Stream *s, const coff_opt_header_t& header)
s->Printf (" reserved1 = 0x%8.8x\n", header.reserved1);
s->Printf (" image_size = 0x%8.8x\n", header.image_size);
s->Printf (" header_size = 0x%8.8x\n", header.header_size);
s->Printf (" checksym = 0x%8.8x\n", header.checksym);
s->Printf (" checksum = 0x%8.8x\n", header.checksum);
s->Printf (" subsystem = 0x%4.4x\n", header.subsystem);
s->Printf (" dll_flags = 0x%4.4x\n", header.dll_flags);
s->Printf (" stack_reserve_size = 0x%16.16llx\n", header.stack_reserve_size);
@ -671,7 +787,7 @@ ObjectFilePECOFF::DumpOptCOFFHeader(Stream *s, const coff_opt_header_t& header)
uint32_t i;
for (i=0; i<header.data_dirs.size(); i++)
{
s->Printf (" data_dirs[%u] vmaddr = 0x%8.8x, vmsize = 0x%8.8x\n",
s->Printf (" data_dirs[%2u] vmaddr = 0x%8.8x, vmsize = 0x%8.8x\n",
i,
header.data_dirs[i].vmaddr,
header.data_dirs[i].vmsize);
@ -689,10 +805,10 @@ ObjectFilePECOFF::DumpSectionHeader(Stream *s, const section_header_t& sh)
GetSectionName(name, sh);
s->Printf ("%-16s 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x 0x%4.4x 0x%4.4x 0x%8.8x\n",
name.c_str(),
sh.vmsize,
sh.vmaddr,
sh.size,
sh.vmsize,
sh.offset,
sh.size,
sh.reloff,
sh.lineoff,
sh.nreloc,
@ -711,15 +827,15 @@ ObjectFilePECOFF::DumpSectionHeaders(Stream *s)
{
s->PutCString ("Section Headers\n");
s->PutCString ("IDX name vm size vm addr size offset reloff lineoff nrel nlin flags\n");
s->PutCString ("==== ---------------- -------- -------- -------- -------- -------- -------- ---- ---- --------\n");
s->PutCString ("IDX name vm addr vm size file off file size reloc off line off nreloc nline flags\n");
s->PutCString ("==== ---------------- ---------- ---------- ---------- ---------- ---------- ---------- ------ ------ ----------\n");
uint32_t idx = 0;
SectionHeaderCollIter pos, end = m_sect_headers.end();
for (pos = m_sect_headers.begin(); pos != end; ++pos, ++idx)
{
s->Printf ("[%2u]", idx);
s->Printf ("[%2u] ", idx);
ObjectFilePECOFF::DumpSectionHeader(s, *pos);
}
}

View File

@ -173,7 +173,7 @@ protected:
uint32_t reserved1;
uint32_t image_size;
uint32_t header_size;
uint32_t checksym;
uint32_t checksum;
uint16_t subsystem;
uint16_t dll_flags;
uint64_t stack_reserve_size;