summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/COFF/Config.h1
-rw-r--r--lld/COFF/Driver.cpp7
-rw-r--r--lld/COFF/Options.td1
-rw-r--r--lld/COFF/Writer.cpp11
-rw-r--r--lld/test/COFF/filealign.test51
5 files changed, 65 insertions, 6 deletions
diff --git a/lld/COFF/Config.h b/lld/COFF/Config.h
index 3b2fe2769c6..ba2bbcdebaf 100644
--- a/lld/COFF/Config.h
+++ b/lld/COFF/Config.h
@@ -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;
diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp
index 006984309e1..df374f518d9 100644
--- a/lld/COFF/Driver.cpp
+++ b/lld/COFF/Driver.cpp
@@ -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);
diff --git a/lld/COFF/Options.td b/lld/COFF/Options.td
index d87183c7e80..f92349f27bd 100644
--- a/lld/COFF/Options.td
+++ b/lld/COFF/Options.td
@@ -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">;
diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp
index d673fc8de85..19614058a2b 100644
--- a/lld/COFF/Writer.cpp
+++ b/lld/COFF/Writer.cpp
@@ -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;
diff --git a/lld/test/COFF/filealign.test b/lld/test/COFF/filealign.test
new file mode 100644
index 00000000000..d6535101c4a
--- /dev/null
+++ b/lld/test/COFF/filealign.test
@@ -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
+...
OpenPOWER on IntegriCloud