forked from OSchip/llvm-project
[LLD][COFF] Implement /filealign parameter
Patch by Stefan Schmidt. This adds the /filealign parameter to lld, which allows to specify the section alignment in the output file (as it does on Microsoft's link.exe). This is required to be able to load dynamically linked libraries on the original Xbox, where the debugger monitor expects the section alignment in the file to be the same as in memory. llvm-svn: 361634
This commit is contained in:
parent
8362cbe13b
commit
74de6203ef
|
@ -180,6 +180,7 @@ struct Configuration {
|
|||
std::string MapFile;
|
||||
|
||||
uint64_t ImageBase = -1;
|
||||
uint64_t FileAlign = 512;
|
||||
uint64_t StackReserve = 1024 * 1024;
|
||||
uint64_t StackCommit = 4096;
|
||||
uint64_t HeapReserve = 1024 * 1024;
|
||||
|
|
|
@ -1197,6 +1197,13 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
|
|||
if (auto *Arg = Args.getLastArg(OPT_base))
|
||||
parseNumbers(Arg->getValue(), &Config->ImageBase);
|
||||
|
||||
// Handle /filealign
|
||||
if (auto *Arg = Args.getLastArg(OPT_filealign)) {
|
||||
parseNumbers(Arg->getValue(), &Config->FileAlign);
|
||||
if (!isPowerOf2_64(Config->FileAlign))
|
||||
error("/filealign: not a power of two: " + Twine(Config->FileAlign));
|
||||
}
|
||||
|
||||
// Handle /stack
|
||||
if (auto *Arg = Args.getLastArg(OPT_stack))
|
||||
parseNumbers(Arg->getValue(), &Config->StackReserve, &Config->StackCommit);
|
||||
|
|
|
@ -32,6 +32,7 @@ def errorlimit : P<"errorlimit",
|
|||
def export : P<"export", "Export a function">;
|
||||
// No help text because /failifmismatch is not intended to be used by the user.
|
||||
def failifmismatch : P<"failifmismatch", "">;
|
||||
def filealign : P<"filealign", "Section alignment in the output file">;
|
||||
def functionpadmin : F<"functionpadmin">;
|
||||
def functionpadmin_opt : P<"functionpadmin", "Prepares an image for hotpatching">;
|
||||
def guard : P<"guard", "Control flow guard">;
|
||||
|
|
|
@ -73,7 +73,6 @@ static unsigned char DOSProgram[] = {
|
|||
static_assert(sizeof(DOSProgram) % 8 == 0,
|
||||
"DOSProgram size must be multiple of 8");
|
||||
|
||||
static const int SectorSize = 512;
|
||||
static const int DOSStubSize = sizeof(dos_header) + sizeof(DOSProgram);
|
||||
static_assert(DOSStubSize % 8 == 0, "DOSStub size must be multiple of 8");
|
||||
|
||||
|
@ -1100,7 +1099,7 @@ void Writer::createSymbolAndStringTable() {
|
|||
PointerToSymbolTable = FileOff;
|
||||
FileOff += OutputSymtab.size() * sizeof(coff_symbol16);
|
||||
FileOff += 4 + Strtab.size();
|
||||
FileSize = alignTo(FileOff, SectorSize);
|
||||
FileSize = alignTo(FileOff, Config->FileAlign);
|
||||
}
|
||||
|
||||
void Writer::mergeSections() {
|
||||
|
@ -1142,7 +1141,7 @@ void Writer::assignAddresses() {
|
|||
sizeof(coff_section) * OutputSections.size();
|
||||
SizeOfHeaders +=
|
||||
Config->is64() ? sizeof(pe32plus_header) : sizeof(pe32_header);
|
||||
SizeOfHeaders = alignTo(SizeOfHeaders, SectorSize);
|
||||
SizeOfHeaders = alignTo(SizeOfHeaders, Config->FileAlign);
|
||||
uint64_t RVA = PageSize; // The first page is kept unmapped.
|
||||
FileSize = SizeOfHeaders;
|
||||
|
||||
|
@ -1167,7 +1166,7 @@ void Writer::assignAddresses() {
|
|||
C->setRVA(RVA + VirtualSize);
|
||||
VirtualSize += C->getSize();
|
||||
if (C->hasData())
|
||||
RawSize = alignTo(VirtualSize, SectorSize);
|
||||
RawSize = alignTo(VirtualSize, Config->FileAlign);
|
||||
}
|
||||
if (VirtualSize > UINT32_MAX)
|
||||
error("section larger than 4 GiB: " + Sec->Name);
|
||||
|
@ -1176,7 +1175,7 @@ void Writer::assignAddresses() {
|
|||
if (RawSize != 0)
|
||||
Sec->Header.PointerToRawData = FileSize;
|
||||
RVA += alignTo(VirtualSize, PageSize);
|
||||
FileSize += alignTo(RawSize, SectorSize);
|
||||
FileSize += alignTo(RawSize, Config->FileAlign);
|
||||
}
|
||||
SizeOfImage = alignTo(RVA, PageSize);
|
||||
|
||||
|
@ -1248,7 +1247,7 @@ template <typename PEHeaderTy> void Writer::writeHeader() {
|
|||
|
||||
PE->ImageBase = Config->ImageBase;
|
||||
PE->SectionAlignment = PageSize;
|
||||
PE->FileAlignment = SectorSize;
|
||||
PE->FileAlignment = Config->FileAlign;
|
||||
PE->MajorImageVersion = Config->MajorImageVersion;
|
||||
PE->MinorImageVersion = Config->MinorImageVersion;
|
||||
PE->MajorOperatingSystemVersion = Config->MajorOSVersion;
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
# RUN: yaml2obj < %s > %t.obj
|
||||
|
||||
# RUN: lld-link /out:%t.exe /entry:main %t.obj
|
||||
# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=DEFAULT-HEADER %s
|
||||
|
||||
# DEFAULT-HEADER: FileAlignment: 512
|
||||
|
||||
# RUN: lld-link /out:%t.exe /entry:main %t.obj /filealign:4096
|
||||
# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=FILEALIGN-HEADER %s
|
||||
|
||||
# FILEALIGN-HEADER: FileAlignment: 4096
|
||||
|
||||
--- !COFF
|
||||
header:
|
||||
Machine: IMAGE_FILE_MACHINE_AMD64
|
||||
Characteristics: []
|
||||
sections:
|
||||
- Name: .text
|
||||
Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
|
||||
Alignment: 4096
|
||||
SectionData: 0000000000000000
|
||||
Relocations:
|
||||
- VirtualAddress: 0
|
||||
SymbolName: __ImageBase
|
||||
Type: IMAGE_REL_AMD64_ADDR64
|
||||
symbols:
|
||||
- Name: .text
|
||||
Value: 0
|
||||
SectionNumber: 1
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||
StorageClass: IMAGE_SYM_CLASS_STATIC
|
||||
SectionDefinition:
|
||||
Length: 8
|
||||
NumberOfRelocations: 1
|
||||
NumberOfLinenumbers: 0
|
||||
CheckSum: 0
|
||||
Number: 0
|
||||
- Name: main
|
||||
Value: 0
|
||||
SectionNumber: 1
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
|
||||
- Name: __ImageBase
|
||||
Value: 0
|
||||
SectionNumber: 0
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
|
||||
...
|
Loading…
Reference in New Issue