mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 12:41:49 +01:00
yaml2obj: Support bigobj
Teach yaml2obj how to make a bigobj COFF file. Like the rest of LLVM, we automatically decide whether or not to use regular COFF or bigobj COFF on the fly depending on how many sections the resulting object would have. This ends the task of adding bigobj support to LLVM. N.B. This was tested by forcing yaml2obj to be used in bigobj mode regardless of the number of sections. While a dedicated test was written, the smallest I could make it was 36 MB (!) of yaml and it still took a significant amount of time to execute on a powerful machine. llvm-svn: 217858
This commit is contained in:
parent
5577ef4461
commit
7b9da9e01d
@ -63,7 +63,7 @@ namespace COFF {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct BigObjHeader {
|
struct BigObjHeader {
|
||||||
enum { MinBigObjectVersion = 2 };
|
enum : uint16_t { MinBigObjectVersion = 2 };
|
||||||
|
|
||||||
uint16_t Sig1; ///< Must be IMAGE_FILE_MACHINE_UNKNOWN (0).
|
uint16_t Sig1; ///< Must be IMAGE_FILE_MACHINE_UNKNOWN (0).
|
||||||
uint16_t Sig2; ///< Must be 0xFFFF.
|
uint16_t Sig2; ///< Must be 0xFFFF.
|
||||||
|
@ -6,7 +6,7 @@ symbols:
|
|||||||
- !Symbol
|
- !Symbol
|
||||||
Name: .file
|
Name: .file
|
||||||
Value: 0
|
Value: 0
|
||||||
SectionNumber: 65534
|
SectionNumber: -2
|
||||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||||
ComplexType: IMAGE_SYM_DTYPE_NULL
|
ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||||
StorageClass: IMAGE_SYM_CLASS_FILE
|
StorageClass: IMAGE_SYM_CLASS_FILE
|
||||||
@ -14,7 +14,7 @@ symbols:
|
|||||||
- !Symbol
|
- !Symbol
|
||||||
Name: '@comp.id'
|
Name: '@comp.id'
|
||||||
Value: 13485607
|
Value: 13485607
|
||||||
SectionNumber: 65535
|
SectionNumber: -1
|
||||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||||
ComplexType: IMAGE_SYM_DTYPE_NULL
|
ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||||
StorageClass: IMAGE_SYM_CLASS_STATIC
|
StorageClass: IMAGE_SYM_CLASS_STATIC
|
||||||
|
@ -6,7 +6,7 @@ symbols:
|
|||||||
- !Symbol
|
- !Symbol
|
||||||
Name: .file
|
Name: .file
|
||||||
Value: 0
|
Value: 0
|
||||||
SectionNumber: 65534
|
SectionNumber: -2
|
||||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||||
ComplexType: IMAGE_SYM_DTYPE_NULL
|
ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||||
StorageClass: IMAGE_SYM_CLASS_FILE
|
StorageClass: IMAGE_SYM_CLASS_FILE
|
||||||
@ -14,7 +14,7 @@ symbols:
|
|||||||
- !Symbol
|
- !Symbol
|
||||||
Name: '@comp.id'
|
Name: '@comp.id'
|
||||||
Value: 13485607
|
Value: 13485607
|
||||||
SectionNumber: 65535
|
SectionNumber: -1
|
||||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||||
ComplexType: IMAGE_SYM_DTYPE_NULL
|
ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||||
StorageClass: IMAGE_SYM_CLASS_STATIC
|
StorageClass: IMAGE_SYM_CLASS_STATIC
|
||||||
|
@ -36,6 +36,18 @@ struct COFFParser {
|
|||||||
StringTable.append(4, char(0));
|
StringTable.append(4, char(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool useBigObj() const {
|
||||||
|
return Obj.Sections.size() > COFF::MaxNumberOfSections16;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned getHeaderSize() const {
|
||||||
|
return useBigObj() ? COFF::Header32Size : COFF::Header16Size;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned getSymbolSize() const {
|
||||||
|
return useBigObj() ? COFF::Symbol32Size : COFF::Symbol16Size;
|
||||||
|
}
|
||||||
|
|
||||||
bool parseSections() {
|
bool parseSections() {
|
||||||
for (std::vector<COFFYAML::Section>::iterator i = Obj.Sections.begin(),
|
for (std::vector<COFFYAML::Section>::iterator i = Obj.Sections.begin(),
|
||||||
e = Obj.Sections.end(); i != e; ++i) {
|
e = Obj.Sections.end(); i != e; ++i) {
|
||||||
@ -121,7 +133,7 @@ static bool layoutCOFF(COFFParser &CP) {
|
|||||||
|
|
||||||
// The section table starts immediately after the header, including the
|
// The section table starts immediately after the header, including the
|
||||||
// optional header.
|
// optional header.
|
||||||
SectionTableStart = COFF::Header16Size + CP.Obj.Header.SizeOfOptionalHeader;
|
SectionTableStart = CP.getHeaderSize() + CP.Obj.Header.SizeOfOptionalHeader;
|
||||||
SectionTableSize = COFF::SectionSize * CP.Obj.Sections.size();
|
SectionTableSize = COFF::SectionSize * CP.Obj.Sections.size();
|
||||||
|
|
||||||
uint32_t CurrentSectionDataOffset = SectionTableStart + SectionTableSize;
|
uint32_t CurrentSectionDataOffset = SectionTableStart + SectionTableSize;
|
||||||
@ -163,7 +175,7 @@ static bool layoutCOFF(COFFParser &CP) {
|
|||||||
NumberOfAuxSymbols += 1;
|
NumberOfAuxSymbols += 1;
|
||||||
if (!i->File.empty())
|
if (!i->File.empty())
|
||||||
NumberOfAuxSymbols +=
|
NumberOfAuxSymbols +=
|
||||||
(i->File.size() + COFF::Symbol16Size - 1) / COFF::Symbol16Size;
|
(i->File.size() + CP.getSymbolSize() - 1) / CP.getSymbolSize();
|
||||||
if (i->SectionDefinition)
|
if (i->SectionDefinition)
|
||||||
NumberOfAuxSymbols += 1;
|
NumberOfAuxSymbols += 1;
|
||||||
if (i->CLRToken)
|
if (i->CLRToken)
|
||||||
@ -222,14 +234,46 @@ zeros_impl<sizeof(T)> zeros(const T &) {
|
|||||||
return zeros_impl<sizeof(T)>();
|
return zeros_impl<sizeof(T)>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct num_zeros_impl {
|
||||||
|
size_t N;
|
||||||
|
num_zeros_impl(size_t N) : N(N) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
raw_ostream &operator<<(raw_ostream &OS, const num_zeros_impl &NZI) {
|
||||||
|
for (size_t I = 0; I != NZI.N; ++I)
|
||||||
|
OS.write(0);
|
||||||
|
return OS;
|
||||||
|
}
|
||||||
|
|
||||||
|
num_zeros_impl num_zeros(size_t N) {
|
||||||
|
num_zeros_impl NZI(N);
|
||||||
|
return NZI;
|
||||||
|
}
|
||||||
|
|
||||||
bool writeCOFF(COFFParser &CP, raw_ostream &OS) {
|
bool writeCOFF(COFFParser &CP, raw_ostream &OS) {
|
||||||
OS << binary_le(CP.Obj.Header.Machine)
|
if (CP.useBigObj()) {
|
||||||
<< binary_le(static_cast<int16_t>(CP.Obj.Header.NumberOfSections))
|
OS << binary_le(static_cast<uint16_t>(COFF::IMAGE_FILE_MACHINE_UNKNOWN))
|
||||||
<< binary_le(CP.Obj.Header.TimeDateStamp)
|
<< binary_le(static_cast<uint16_t>(0xffff))
|
||||||
<< binary_le(CP.Obj.Header.PointerToSymbolTable)
|
<< binary_le(static_cast<uint16_t>(COFF::BigObjHeader::MinBigObjectVersion))
|
||||||
<< binary_le(CP.Obj.Header.NumberOfSymbols)
|
<< binary_le(CP.Obj.Header.Machine)
|
||||||
<< binary_le(CP.Obj.Header.SizeOfOptionalHeader)
|
<< binary_le(CP.Obj.Header.TimeDateStamp);
|
||||||
<< binary_le(CP.Obj.Header.Characteristics);
|
OS.write(COFF::BigObjMagic, sizeof(COFF::BigObjMagic));
|
||||||
|
OS << zeros(uint32_t(0))
|
||||||
|
<< zeros(uint32_t(0))
|
||||||
|
<< zeros(uint32_t(0))
|
||||||
|
<< zeros(uint32_t(0))
|
||||||
|
<< binary_le(CP.Obj.Header.NumberOfSections)
|
||||||
|
<< binary_le(CP.Obj.Header.PointerToSymbolTable)
|
||||||
|
<< binary_le(CP.Obj.Header.NumberOfSymbols);
|
||||||
|
} else {
|
||||||
|
OS << binary_le(CP.Obj.Header.Machine)
|
||||||
|
<< binary_le(static_cast<int16_t>(CP.Obj.Header.NumberOfSections))
|
||||||
|
<< binary_le(CP.Obj.Header.TimeDateStamp)
|
||||||
|
<< binary_le(CP.Obj.Header.PointerToSymbolTable)
|
||||||
|
<< binary_le(CP.Obj.Header.NumberOfSymbols)
|
||||||
|
<< binary_le(CP.Obj.Header.SizeOfOptionalHeader)
|
||||||
|
<< binary_le(CP.Obj.Header.Characteristics);
|
||||||
|
}
|
||||||
|
|
||||||
// Output section table.
|
// Output section table.
|
||||||
for (std::vector<COFFYAML::Section>::iterator i = CP.Obj.Sections.begin(),
|
for (std::vector<COFFYAML::Section>::iterator i = CP.Obj.Sections.begin(),
|
||||||
@ -276,9 +320,12 @@ bool writeCOFF(COFFParser &CP, raw_ostream &OS) {
|
|||||||
e = CP.Obj.Symbols.end();
|
e = CP.Obj.Symbols.end();
|
||||||
i != e; ++i) {
|
i != e; ++i) {
|
||||||
OS.write(i->Header.Name, COFF::NameSize);
|
OS.write(i->Header.Name, COFF::NameSize);
|
||||||
OS << binary_le(i->Header.Value)
|
OS << binary_le(i->Header.Value);
|
||||||
<< binary_le(static_cast<int16_t>(i->Header.SectionNumber))
|
if (CP.useBigObj())
|
||||||
<< binary_le(i->Header.Type)
|
OS << binary_le(i->Header.SectionNumber);
|
||||||
|
else
|
||||||
|
OS << binary_le(static_cast<int16_t>(i->Header.SectionNumber));
|
||||||
|
OS << binary_le(i->Header.Type)
|
||||||
<< binary_le(i->Header.StorageClass)
|
<< binary_le(i->Header.StorageClass)
|
||||||
<< binary_le(i->Header.NumberOfAuxSymbols);
|
<< binary_le(i->Header.NumberOfAuxSymbols);
|
||||||
|
|
||||||
@ -287,25 +334,28 @@ bool writeCOFF(COFFParser &CP, raw_ostream &OS) {
|
|||||||
<< binary_le(i->FunctionDefinition->TotalSize)
|
<< binary_le(i->FunctionDefinition->TotalSize)
|
||||||
<< binary_le(i->FunctionDefinition->PointerToLinenumber)
|
<< binary_le(i->FunctionDefinition->PointerToLinenumber)
|
||||||
<< binary_le(i->FunctionDefinition->PointerToNextFunction)
|
<< binary_le(i->FunctionDefinition->PointerToNextFunction)
|
||||||
<< zeros(i->FunctionDefinition->unused);
|
<< zeros(i->FunctionDefinition->unused)
|
||||||
|
<< num_zeros(CP.getSymbolSize() - COFF::Symbol16Size);
|
||||||
if (i->bfAndefSymbol)
|
if (i->bfAndefSymbol)
|
||||||
OS << zeros(i->bfAndefSymbol->unused1)
|
OS << zeros(i->bfAndefSymbol->unused1)
|
||||||
<< binary_le(i->bfAndefSymbol->Linenumber)
|
<< binary_le(i->bfAndefSymbol->Linenumber)
|
||||||
<< zeros(i->bfAndefSymbol->unused2)
|
<< zeros(i->bfAndefSymbol->unused2)
|
||||||
<< binary_le(i->bfAndefSymbol->PointerToNextFunction)
|
<< binary_le(i->bfAndefSymbol->PointerToNextFunction)
|
||||||
<< zeros(i->bfAndefSymbol->unused3);
|
<< zeros(i->bfAndefSymbol->unused3)
|
||||||
|
<< num_zeros(CP.getSymbolSize() - COFF::Symbol16Size);
|
||||||
if (i->WeakExternal)
|
if (i->WeakExternal)
|
||||||
OS << binary_le(i->WeakExternal->TagIndex)
|
OS << binary_le(i->WeakExternal->TagIndex)
|
||||||
<< binary_le(i->WeakExternal->Characteristics)
|
<< binary_le(i->WeakExternal->Characteristics)
|
||||||
<< zeros(i->WeakExternal->unused);
|
<< zeros(i->WeakExternal->unused)
|
||||||
|
<< num_zeros(CP.getSymbolSize() - COFF::Symbol16Size);
|
||||||
if (!i->File.empty()) {
|
if (!i->File.empty()) {
|
||||||
|
unsigned SymbolSize = CP.getSymbolSize();
|
||||||
uint32_t NumberOfAuxRecords =
|
uint32_t NumberOfAuxRecords =
|
||||||
(i->File.size() + COFF::Symbol16Size - 1) / COFF::Symbol16Size;
|
(i->File.size() + SymbolSize - 1) / SymbolSize;
|
||||||
uint32_t NumberOfAuxBytes = NumberOfAuxRecords * COFF::Symbol16Size;
|
uint32_t NumberOfAuxBytes = NumberOfAuxRecords * SymbolSize;
|
||||||
uint32_t NumZeros = NumberOfAuxBytes - i->File.size();
|
uint32_t NumZeros = NumberOfAuxBytes - i->File.size();
|
||||||
OS.write(i->File.data(), i->File.size());
|
OS.write(i->File.data(), i->File.size());
|
||||||
for (uint32_t Padding = 0; Padding < NumZeros; ++Padding)
|
OS << num_zeros(NumZeros);
|
||||||
OS.write(0);
|
|
||||||
}
|
}
|
||||||
if (i->SectionDefinition)
|
if (i->SectionDefinition)
|
||||||
OS << binary_le(i->SectionDefinition->Length)
|
OS << binary_le(i->SectionDefinition->Length)
|
||||||
@ -315,12 +365,14 @@ bool writeCOFF(COFFParser &CP, raw_ostream &OS) {
|
|||||||
<< binary_le(static_cast<int16_t>(i->SectionDefinition->Number))
|
<< binary_le(static_cast<int16_t>(i->SectionDefinition->Number))
|
||||||
<< binary_le(i->SectionDefinition->Selection)
|
<< binary_le(i->SectionDefinition->Selection)
|
||||||
<< zeros(i->SectionDefinition->unused)
|
<< zeros(i->SectionDefinition->unused)
|
||||||
<< binary_le(static_cast<int16_t>(i->SectionDefinition->Number >> 16));
|
<< binary_le(static_cast<int16_t>(i->SectionDefinition->Number >> 16))
|
||||||
|
<< num_zeros(CP.getSymbolSize() - COFF::Symbol16Size);
|
||||||
if (i->CLRToken)
|
if (i->CLRToken)
|
||||||
OS << binary_le(i->CLRToken->AuxType)
|
OS << binary_le(i->CLRToken->AuxType)
|
||||||
<< zeros(i->CLRToken->unused1)
|
<< zeros(i->CLRToken->unused1)
|
||||||
<< binary_le(i->CLRToken->SymbolTableIndex)
|
<< binary_le(i->CLRToken->SymbolTableIndex)
|
||||||
<< zeros(i->CLRToken->unused2);
|
<< zeros(i->CLRToken->unused2)
|
||||||
|
<< num_zeros(CP.getSymbolSize() - COFF::Symbol16Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Output string table.
|
// Output string table.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user