kolibrios/programs/develop/objconv/elf2cof.cpp

703 lines
31 KiB
C++

/**************************** elf2cof.cpp *********************************
* Author: Agner Fog
* Date created: 2006-08-19
* Last modified: 2013-11-27
* Project: objconv
* Module: elf2cof.cpp
* Description:
* Module for converting ELF file to PE/COFF file
*
* Copyright 2006-2013 GNU General Public License http://www.gnu.org/licenses
*****************************************************************************/
#include "stdafx.h"
// All functions in this module are templated to make two versions: 32 and 64 bits.
// See instantiations at the end of this file.
// Constructor
template <class TELF_Header, class TELF_SectionHeader, class TELF_Symbol, class TELF_Relocation>
CELF2COF<ELFSTRUCTURES>::CELF2COF() {
// Reset all
memset(this, 0, sizeof(*this));
}
// Convert(): Do the conversion
template <class TELF_Header, class TELF_SectionHeader, class TELF_Symbol, class TELF_Relocation>
void CELF2COF<ELFSTRUCTURES>::Convert() {
// Some compilers require this-> for accessing members of template base class,
// according to the so-called two-phase lookup rule.
// Allocate variable size buffers
NewSectIndex.SetNum(this->NSections);// Allocate section translation table
NewSectIndex.SetZero(); // Initialize
// Call the subfunctions
ToFile.SetFileType(FILETYPE_COFF); // Set type of to file
MakeFileHeader(); // Make file header
MakeSectionsIndex(); // Make sections index translation table
MakeSymbolTable(); // Make symbol table and string tables
MakeSections(); // Make sections and relocation tables
HideUnusedSymbols(); // Hide unused symbols
MakeBinaryFile(); // Put sections together
*this << ToFile; // Take over new file buffer
}
// MakeFileHeader(): Convert subfunction to make file header
template <class TELF_Header, class TELF_SectionHeader, class TELF_Symbol, class TELF_Relocation>
void CELF2COF<ELFSTRUCTURES>::MakeFileHeader() {
// Make PE file header
NewFileHeader.Machine = (this->WordSize == 32) ? PE_MACHINE_I386 : PE_MACHINE_X8664;
NewFileHeader.TimeDateStamp = (uint32)time(0);
NewFileHeader.SizeOfOptionalHeader = 0;
NewFileHeader.Flags = 0;
// Values inserted later:
NewFileHeader.NumberOfSections = 0;
NewFileHeader.PSymbolTable = 0;
NewFileHeader.NumberOfSymbols = 0;
// Put file header into file
ToFile.Push(&NewFileHeader, sizeof(NewFileHeader));
}
// MakeSectionsIndex(): Make sections index translation table
template <class TELF_Header, class TELF_SectionHeader, class TELF_Symbol, class TELF_Relocation>
void CELF2COF<ELFSTRUCTURES>::MakeSectionsIndex() {
// We must make this table before the segments, because it is needed for the
// symbol table, and we must make the symbol table before the relocation table,
// and we must make the relocation table together with the sections.
uint32 oldsec; // Section number in old file
uint32 newsec = 0; // Section number in new file
// Loop through old sections
for (oldsec = 0; oldsec < this->NSections; oldsec++) {
// Get section name
const char * sname = "";
uint32 namei = this->SectionHeaders[oldsec].sh_name;
if (namei >= this->SecStringTableLen) err.submit(2112);
else sname = this->SecStringTable + namei;
if (cmd.DebugInfo == CMDL_DEBUG_STRIP) {
// Check for debug section names
if (strncmp(sname, ".note", 5) == 0
|| strncmp(sname, ".comment", 8) == 0
|| strncmp(sname, ".stab", 5) == 0
|| strncmp(sname, ".debug", 6) == 0) {
// Remove this section
this->SectionHeaders[oldsec].sh_type = SHT_REMOVE_ME;
cmd.CountDebugRemoved();
}
}
if (cmd.ExeptionInfo == CMDL_EXCEPTION_STRIP) {
// Check for exception section name
if (strncmp(sname, ".eh_frame", 9) == 0) {
// Remove this section
this->SectionHeaders[oldsec].sh_type = SHT_REMOVE_ME;
cmd.CountExceptionRemoved();
}
}
// Search for program data sections only
if (this->SectionHeaders[oldsec].sh_type == SHT_PROGBITS
|| this->SectionHeaders[oldsec].sh_type == SHT_NOBITS) {
// Section index translation table
NewSectIndex[oldsec] = newsec++;
}
else {
NewSectIndex[oldsec] = 0;
}
}
// Store number of sections in new file
NumSectionsNew = newsec;
// Calculate file offset of raw data
RawDataOffset = sizeof(SCOFF_FileHeader) + NumSectionsNew * sizeof(SCOFF_SectionHeader);
}
// MakeSections(): Convert subfunction to make sections and relocation tables
template <class TELF_Header, class TELF_SectionHeader, class TELF_Symbol, class TELF_Relocation>
void CELF2COF<ELFSTRUCTURES>::MakeSections() {
uint32 oldsec; // Section number in old file
uint32 relsec; // Relocation section in old file
SCOFF_SectionHeader NewHeader; // New section header
TELF_SectionHeader OldHeader; // Old section header
TELF_SectionHeader OldRelHeader; // Old relocation section header
TELF_Relocation OldRelocation; // Old relocation table entry
SCOFF_Relocation NewRelocation; // New relocation table entry
// Loop through old sections
for (oldsec = 0; oldsec < this->NSections; oldsec++) {
// Copy old header for convenience
OldHeader = this->SectionHeaders[oldsec];
// Search for program data sections only
if (OldHeader.sh_type == SHT_PROGBITS || OldHeader.sh_type == SHT_NOBITS) {
// Reset new section header
memset(&NewHeader, 0, sizeof(NewHeader));
// Section name
const char * sname = "";
uint32 namei = OldHeader.sh_name;
if (namei >= this->SecStringTableLen) err.submit(2112);
else sname = this->SecStringTable + namei;
// Check for special names
if (strcmp(sname, ELF_CONSTRUCTOR_NAME)==0) {
// This is the constructors segment
sname = COFF_CONSTRUCTOR_NAME;
OldHeader.sh_flags &= ~ SHF_WRITE;
}
// Store name in section header
COFF_PutNameInSectionHeader(NewHeader, sname, NewStringTable);
// Raw data
NewHeader.SizeOfRawData = uint32(OldHeader.sh_size); // section size in file
if (OldHeader.sh_size && OldHeader.sh_type != SHT_NOBITS) {
// File to raw data for section
NewHeader.PRawData = NewRawData.GetDataSize() + RawDataOffset;
// Copy raw data
NewRawData.Push(this->Buf()+(uint32)(OldHeader.sh_offset), (uint32)(OldHeader.sh_size));
NewRawData.Align(4);
}
// Section flags
NewHeader.Flags = PE_SCN_MEM_READ;
if (OldHeader.sh_flags & SHF_WRITE) NewHeader.Flags |= PE_SCN_MEM_WRITE;
if (OldHeader.sh_flags & SHF_EXECINSTR) {
NewHeader.Flags |= PE_SCN_MEM_EXECUTE | PE_SCN_CNT_CODE;
}
else {
NewHeader.Flags |= (OldHeader.sh_type == SHT_PROGBITS) ?
PE_SCN_CNT_INIT_DATA : PE_SCN_CNT_UNINIT_DATA;
}
// Alignment
int NewAlign = FloorLog2(uint32(OldHeader.sh_addralign)) + 1;
if (NewAlign > 14) NewAlign = 14; // limit for highest alignment
NewHeader.Flags |= PE_SCN_ALIGN_1 * NewAlign;
// Find relocation table for this section by searching through all sections
for (relsec = 1; relsec < this->NSections; relsec++) {
// Get section header
OldRelHeader = this->SectionHeaders[relsec];
// Check if this is a relocations section referring to oldsec
if ((OldRelHeader.sh_type == SHT_REL || OldRelHeader.sh_type == SHT_RELA) // if section is relocation
&& OldRelHeader.sh_info == oldsec) { // and if section refers to current section
// Found the right relocation table. Get pointer
int8 * reltab = this->Buf() + uint32(OldRelHeader.sh_offset);
int8 * reltabend = reltab + uint32(OldRelHeader.sh_size);
// Get entry size
int entrysize = uint32(OldRelHeader.sh_entsize);
int expectedentrysize = (OldRelHeader.sh_type == SHT_RELA) ?
sizeof(TELF_Relocation) : // Elf32_Rela, Elf64_Rela
sizeof(TELF_Relocation) - this->WordSize/8; // Elf32_Rel, Elf64_Rel
if (entrysize < expectedentrysize) {err.submit(2033); entrysize = expectedentrysize;}
// File pointer for new relocations
NewHeader.PRelocations = NewRawData.GetDataSize() + RawDataOffset; // file to relocation entries
// Loop through relocation table entries
for (; reltab < reltabend; reltab += entrysize) {
// Copy relocation table entry with or without addend
OldRelocation.r_addend = 0;
memcpy(&OldRelocation, reltab, entrysize);
// Find inline addend
uint32 InlinePosition = (uint32)(NewHeader.PRawData - RawDataOffset + OldRelocation.r_offset);
// Check that address is valid
if (InlinePosition >= this->GetDataSize()) {
// Address is invalid
err.submit(2032);
break;
}
// Pointer to inline addend
int32 * piaddend = (int32*)(NewRawData.Buf() + InlinePosition);
// Symbol offset
NewRelocation.VirtualAddress = uint32(OldRelocation.r_offset);
// Symbol table index
if (OldRelocation.r_sym < NewSymbolIndex.GetNumEntries()) {
NewRelocation.SymbolTableIndex = NewSymbolIndex[OldRelocation.r_sym];
}
else {
NewRelocation.SymbolTableIndex = 0; // Symbol table index out of range
}
// Get relocation type and fix addend
if (this->WordSize == 32) {
switch(OldRelocation.r_type) {
case R_386_NONE: // Ignored
NewRelocation.Type = COFF32_RELOC_ABS; break;
case R_386_IRELATIVE:
err.submit(1063); // Warning: Gnu indirect function cannot be converted
// continue in next case?:
case R_386_32: // 32-bit absolute virtual address
NewRelocation.Type = COFF32_RELOC_DIR32;
*piaddend += uint32(OldRelocation.r_addend);
break;
case R_386_PC32: // 32-bit self-relative
NewRelocation.Type = COFF32_RELOC_REL32;
// Difference between EIP-relative and self-relative relocation = size of address field
// Adjust inline addend for different relocation method:
*piaddend += 4 + uint32(OldRelocation.r_addend);
break;
case R_386_GOT32: case R_386_GLOB_DAT: case R_386_GOTOFF: case R_386_GOTPC:
// Global offset table
err.submit(2042); // cannot convert position-independent code
err.ClearError(2042); // report this error only once
NewRelocation.Type = 0;
break;
case R_386_PLT32: case R_386_JMP_SLOT:
// procedure linkage table
err.submit(2043); // cannot convert import table
err.ClearError(2043); // report this error only once
NewRelocation.Type = 0;
break;
case R_386_RELATIVE: // adjust by program base
default: // Unknown or unsupported relocation method
err.submit(2030, OldRelocation.r_type);
err.ClearError(2030); // report this error only once
NewRelocation.Type = 0;
break;
}
}
else { // WordSize == 64
switch(OldRelocation.r_type) {
case R_X86_64_NONE: // Ignored
NewRelocation.Type = COFF64_RELOC_ABS;
break;
case R_X86_64_64: // 64 bit absolute virtual addres
NewRelocation.Type = COFF64_RELOC_ABS64;
*(int64*)piaddend += OldRelocation.r_addend;
break;
case R_X86_64_IRELATIVE:
err.submit(1063); // Warning: Gnu indirect function cannot be converted
// continue in next case?:
case R_X86_64_32S: // 32 bit absolute virtual address, sign extended
case R_X86_64_32: // 32 bit absolute virtual address, zero extended
NewRelocation.Type = COFF64_RELOC_ABS32;
*piaddend += uint32(OldRelocation.r_addend);
break;
case R_X86_64_PC32: // 32 bit, self-relative
// See COFF2ELF.cpp for an explanation of the difference between
// COFF and ELF relative relocation methods
*piaddend += uint32(OldRelocation.r_addend);
if (*piaddend >= -8 && *piaddend <= -4) {
NewRelocation.Type = (uint16)(COFF64_RELOC_REL32 - *piaddend - 4);
*piaddend = 0;
}
else {
NewRelocation.Type = COFF64_RELOC_REL32;
*piaddend += 4;
}
break;
case R_X86_64_RELATIVE: // Adjust by program base
err.submit(2030, OldRelocation.r_type);
err.ClearError(2030); // report this error only once
NewRelocation.Type = 0;
break;
case R_X86_64_GOT32: case R_X86_64_GLOB_DAT: case R_X86_64_GOTPCREL:
// Global offset table
err.submit(2042); // cannot convert position-independent code
err.ClearError(2042); // report this error only once
NewRelocation.Type = 0;
break;
case R_X86_64_PLT32: case R_X86_64_JUMP_SLOT:
// procedure linkage table
err.submit(2042); // cannot convert import table
err.ClearError(2043); // report this error only once
NewRelocation.Type = 0;
break;
default: // Unknown or unsupported relocation method
err.submit(2030, OldRelocation.r_type);
err.ClearError(2030); // report this error only once
NewRelocation.Type = 0;
break;
}
}
// Store relocation entry
NewRawData.Push(&NewRelocation, SIZE_SCOFF_Relocation);
NewHeader.NRelocations++;
// Remember that symbol is used
if (OldRelocation.r_type) {
SymbolsUsed[NewRelocation.SymbolTableIndex]++;
}
} // End of relocations loop
} // End of if right relocation table
} // End of search for relocation table
// Align raw data for next section
NewRawData.Align(4);
// Store section header in file
ToFile.Push(&NewHeader, sizeof(NewHeader));
} // End of if section has program data
} // End of loop through old sections
} // End of function MakeSections
// Check for overflow when converting 64 bit symbol value to 32 bits.
// Value may be signed or unsigned
static int SymbolOverflow(uint64 x) {
uint32 Upper = HighDWord(x); // Upper 32 bits of 64 bit value
if (Upper == 0xFFFFFFFF) { // Check for signed overflow
return int32(x) >= 0; // Overflow if not signed
}
return Upper != 0; // Check for unsigned overflow
}
static int SymbolOverflow(uint32 x) { // Overloaded 32 bit version
return 0; // Cannot overflow if already 32 bits
}
// MakeSymbolTable(): Convert subfunction to make symbol table and string tables
template <class TELF_Header, class TELF_SectionHeader, class TELF_Symbol, class TELF_Relocation>
void CELF2COF<ELFSTRUCTURES>::MakeSymbolTable() {
uint32 oldsec; // Section number in old file
TELF_SectionHeader OldHeader; // Old section header
int FoundSymTab = 0; // Found symbol table
int8 * strtab; // Old symbol string table
int8 * symtab; // Old symbol table
uint32 symtabsize; // Size of old symbol table
uint32 stringtabsize; // Size of old string table
int8 * symtabend; // End of old symbol table
uint32 entrysize; // Size of each entry in old symbol table
uint32 OldSymI; // Symbol index in old symbol table
uint32 NewSymI = 0; // Symbol index in new symbol table
const char * symname = 0; // Symbol name
TELF_Symbol OldSym; // Old symbol table record
SCOFF_SymTableEntry NewSym; // New symbol table record
SCOFF_SymTableEntry AuxSym; // Auxiliary symbol table entry
uint32 numaux; // Number of auxiliary records for new entry
// Initialize new string table. make space for 4-bytes size
NewStringTable.Push(0, 4);
// Loop through old sections to find symbol table
for (oldsec = 0; oldsec < this->NSections; oldsec++) {
// Search for program data sections only
if (this->SectionHeaders[oldsec].sh_type == SHT_SYMTAB
|| this->SectionHeaders[oldsec].sh_type==SHT_DYNSYM) {
FoundSymTab++; numaux = 0;
// Copy symbol table header for convenience
OldHeader = this->SectionHeaders[oldsec];
// Find associated string table
if (OldHeader.sh_link >= this->NSections) {err.submit(2035); OldHeader.sh_link = 0;}
strtab = this->Buf() + uint32(this->SectionHeaders[OldHeader.sh_link].sh_offset);
stringtabsize = uint32(this->SectionHeaders[OldHeader.sh_link].sh_size);
// Find old symbol table
entrysize = uint32(OldHeader.sh_entsize);
if (entrysize < sizeof(TELF_Symbol)) {err.submit(2033); entrysize = sizeof(TELF_Symbol);}
symtab = this->Buf() + uint32(OldHeader.sh_offset);
symtabsize = uint32(OldHeader.sh_size);
symtabend = symtab + symtabsize;
// Loop through old symbol table
for (OldSymI = 0; symtab < symtabend; symtab += entrysize, OldSymI++) {
// Copy old symbol table entry
OldSym = *(TELF_Symbol*)symtab;
// Reset new symbol table entry
memset(&NewSym, 0, sizeof(NewSym));
// New symbol index
NewSymI = NewSymbolTable.GetNumEntries();
// Symbol type
int type = OldSym.st_type;
// Symbol storage class = binding
int binding = OldSym.st_bind;
// Get symbol name
if (OldSym.st_name < stringtabsize) {
symname = strtab + OldSym.st_name;
if (symname && *symname && type != STT_FILE) {
// Symbol has a name that we want to store
COFF_PutNameInSymbolTable(NewSym, symname, NewStringTable);
}
}
else { // points outside string table
err.submit(2112); continue;
}
// Value
NewSym.s.Value = uint32(OldSym.st_value);
// Check for overflow if converting 64 bit symbol value to 32 bits
if (SymbolOverflow(OldSym.st_value)) err.submit(2020, symname);
// Section
if (OldSym.st_shndx == SHN_UNDEF) {
NewSym.s.SectionNumber = COFF_SECTION_UNDEF; // External
}
else if ((int16)(OldSym.st_shndx) == SHN_ABS) {
NewSym.s.SectionNumber = COFF_SECTION_ABSOLUTE; // Absolute symbol
}
else if (OldSym.st_shndx >= this->NSections) {
err.submit(2036, OldSym.st_shndx); // Special/unknown section index or out of range
}
else {
// Normal section index.
// Look up in section index translation table and add 1 because it is 1-based
NewSym.s.SectionNumber = (int16)(NewSectIndex[OldSym.st_shndx] + 1);
}
// Convert binding/storage class
switch (binding) {
case STB_LOCAL:
NewSym.s.StorageClass = COFF_CLASS_STATIC; break;
case STB_GLOBAL:
NewSym.s.StorageClass = COFF_CLASS_EXTERNAL; break;
case STB_WEAK:
err.submit(1051, symname); // Weak public symbol not supported
NewSym.s.StorageClass = COFF_CLASS_WEAK_EXTERNAL; break;
default:
err.submit(2037, binding); // Other. Not supported
}
// Make record depending on type
switch (type) {
case STT_OBJECT: case STT_NOTYPE:
// Data object
NewSym.s.Type = COFF_TYPE_NOT_FUNCTION;
if (OldSymI > 0) { // First symbol entry in ELF file is unused
NewSymbolTable.Push(&NewSym, SIZE_SCOFF_SymTableEntry);
}
break;
case STT_GNU_IFUNC:
err.submit(1063); // Warning: Gnu indirect function cannot be converted
// continue in next case:
case STT_FUNC:
// Function
NewSym.s.Type = COFF_TYPE_FUNCTION;
NewSymbolTable.Push(&NewSym, SIZE_SCOFF_SymTableEntry);
// Aux records needed only if debug information included
break;
case STT_FILE: {
// File name record
memset(&NewSym, 0, sizeof(NewSym));
strcpy(NewSym.s.Name, ".file");
NewSym.s.StorageClass = COFF_CLASS_FILE;
NewSym.s.SectionNumber = COFF_SECTION_DEBUG;
// Remove path from file name
const char * shortname = symname;
uint32 len = (uint32)strlen(symname);
if (len > 1) {
// Scan backwards for last '/'
for (int scan = len-2; scan >= 0; scan--) {
if (symname[scan] == '/' || symname[scan] == '\\') {
// Path found. Short name starts after this character
shortname = symname + scan + 1;
break;
}
}
}
len = (uint32)strlen(shortname);
if (len > 35) len = 35; // arbitrary limit to file name length
// Number of auxiliary records for storing file name
numaux = (len + SIZE_SCOFF_SymTableEntry - 1) / SIZE_SCOFF_SymTableEntry;
NewSym.s.NumAuxSymbols = (uint8)numaux;
// Store regular record
NewSymbolTable.Push(&NewSym, SIZE_SCOFF_SymTableEntry);
// Store numaux auxiliary records for file name
for (uint32 i = 0; i < numaux; i++) { // Can't push all in one operation because NumEntries will be wrong
NewSymbolTable.Push(0, SIZE_SCOFF_SymTableEntry);
}
// copy name into NewSymbolTable aux records
int8 * PointAux = NewSymbolTable.Buf() + NewSymbolTable.GetDataSize();
memcpy(PointAux - numaux*SIZE_SCOFF_SymTableEntry, shortname, len);
break;}
case STT_SECTION: {
// Section name record
NewSym.s.Value = 0;
NewSym.s.Type = 0;
NewSym.s.StorageClass = COFF_CLASS_STATIC;
NewSym.s.NumAuxSymbols = (uint8)(numaux = 1);
// Find corresponding section header
TELF_SectionHeader * OldSecHdr = 0;
if (OldSym.st_shndx < this->NSections) {
OldSecHdr = &(this->SectionHeaders[OldSym.st_shndx]);
// Find section name
char * sname;
if (OldSecHdr->sh_name < this->SecStringTableLen) {
sname = this->SecStringTable + OldSecHdr->sh_name;
// Put into symbol table
COFF_PutNameInSymbolTable(NewSym, sname, NewStringTable);
}
}
// Store regular record
NewSymbolTable.Push(&NewSym, SIZE_SCOFF_SymTableEntry);
// Make auxiliary record
memset(&AuxSym, 0, sizeof(AuxSym));
if (OldSecHdr) {
AuxSym.section.Length = uint32(OldSecHdr->sh_size);
// Find corresponding relocation section header
// Assume that relocation section comes immediately after section record
if ((uint32)OldSym.st_shndx + 1 < this->NSections // if not last section
&& (OldSecHdr[1].sh_type == SHT_REL || OldSecHdr[1].sh_type == SHT_RELA) // and if next section is relocation
&& OldSecHdr[1].sh_info == OldSym.st_shndx // and if next section refers to current section
&& OldSecHdr[1].sh_entsize > 0) { // Avoid division by 0
// Calculate number of relocations
AuxSym.section.NumberOfRelocations = (uint16)(uint32(OldSecHdr[1].sh_size) / uint32(OldSecHdr[1].sh_entsize));
}
}
// Store auxiliary record
NewSymbolTable.Push(&AuxSym, SIZE_SCOFF_SymTableEntry);
break;}
case STT_COMMON:
default:
err.submit(2038, type); // Symbol type not supported
}
if (FoundSymTab == 1) {
// Make translation table from old symbol index to new symbol index,
// assuming there is only one symbol table.
// Make sure all old symbols have an entry in the NewSymbolIndex table,
// even if they are discarded.
NewSymbolIndex.Push(NewSymI);
}
} // End OldSymI loop
}
} // End search for symbol table
if (FoundSymTab == 0) err.submit(2034); // Symbol table not found
if (FoundSymTab > 1) err.submit(1032); // More than one symbol table found
// Allocate space for SymbolsUsed table
SymbolsUsed.SetNum(NewSymI+1);
SymbolsUsed.SetZero(); // Initialize
}
// HideUnusedSymbols(): Hide unused symbols if stripping debug info or exception info
template <class TELF_Header, class TELF_SectionHeader, class TELF_Symbol, class TELF_Relocation>
void CELF2COF<ELFSTRUCTURES>::HideUnusedSymbols() {
if (cmd.DebugInfo != CMDL_DEBUG_STRIP && cmd.ExeptionInfo != CMDL_EXCEPTION_STRIP) {
// No sections removed. Do nothing
return;
}
// Pointer to new symbol table
union {
SCOFF_SymTableEntry * p; // Symtab entry pointer
int8 * b; // Used for increment
} NewSymtab;
NewSymtab.b = NewSymbolTable.Buf();
int numaux = 0, isym;
int NumberOfSymbols = NewSymbolTable.GetNumEntries();
// Loop through new symbol table
for (isym = 0; isym < NumberOfSymbols; isym += numaux+1, NewSymtab.b += SIZE_SCOFF_SymTableEntry*(numaux+1)) {
// Number of auxiliary records belonging to same symbol
numaux = NewSymtab.p->s.NumAuxSymbols; if (numaux < 0) numaux = 0;
if (NewSymtab.p->s.StorageClass == COFF_CLASS_EXTERNAL
|| NewSymtab.p->s.StorageClass == COFF_CLASS_WEAK_EXTERNAL) {
if (NewSymtab.p->s.SectionNumber == COFF_SECTION_UNDEF) {
// External symbol. Check if it is used
if (!SymbolsUsed[isym]) {
// Symbol is unused. Hide it to prevent linking errors
NewSymtab.p->s.StorageClass = COFF_CLASS_NULL;
NewSymtab.p->s.SectionNumber = COFF_SECTION_UNDEF;
NewSymtab.p->s.Type = COFF_TYPE_NOT_FUNCTION;
cmd.CountSymbolsHidden();
}
}
}
}
}
// MakeBinaryFile(): Convert subfunction to put all sections together
template <class TELF_Header, class TELF_SectionHeader, class TELF_Symbol, class TELF_Relocation>
void CELF2COF<ELFSTRUCTURES>::MakeBinaryFile() {
// Insert string table size
//NewStringTable.Get<uint32>(0) = NewStringTable.GetDataSize();
// Some compilers fail with the double template here. Avoid the template:
*(uint32*)(NewStringTable.Buf()) = NewStringTable.GetDataSize();
// Update file header
NewFileHeader.NumberOfSections = (uint16)NumSectionsNew;
NewFileHeader.PSymbolTable = RawDataOffset + NewRawData.GetDataSize();
NewFileHeader.NumberOfSymbols = NewSymbolTable.GetNumEntries();
// Replace file header in new file with updated version
memcpy(ToFile.Buf(), &NewFileHeader, sizeof(NewFileHeader));
// Section headers have already been inserted.
// Insert raw data in file
ToFile.Push(NewRawData.Buf(), NewRawData.GetDataSize());
// Insert symbol table
ToFile.Push(NewSymbolTable.Buf(), NewSymbolTable.GetDataSize());
// Insert string table
ToFile.Push(NewStringTable.Buf(), NewStringTable.GetDataSize());
}
// Make template instances for 32 and 64 bits
template class CELF2COF<ELF32STRUCTURES>;
template class CELF2COF<ELF64STRUCTURES>;