[ELF] Fix first PT_LOAD segment VA calculation, when linker script is used

llvm-svn: 274342
This commit is contained in:
Eugene Leviant 2016-07-01 10:27:36 +00:00
parent beb24f5b20
commit 467c4d5538
3 changed files with 39 additions and 10 deletions

View File

@ -21,6 +21,7 @@
#include "ScriptParser.h"
#include "Strings.h"
#include "SymbolTable.h"
#include "Target.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/ELF.h"
#include "llvm/Support/FileSystem.h"
@ -220,7 +221,8 @@ void LinkerScript<ELFT>::assignAddresses(
}
// Assign addresses as instructed by linker script SECTIONS sub-commands.
Dot = Out<ELFT>::ElfHeader->getSize() + Out<ELFT>::ProgramHeaders->getSize();
Dot = Out<ELFT>::ElfHeader->getSize() + Out<ELFT>::ProgramHeaders->getSize();
uintX_t MinVA = std::numeric_limits<uintX_t>::max();
uintX_t ThreadBssOffset = 0;
for (SectionsCommand &Cmd : Opt.Commands) {
@ -247,11 +249,20 @@ void LinkerScript<ELFT>::assignAddresses(
if (Sec->getFlags() & SHF_ALLOC) {
Dot = alignTo(Dot, Sec->getAlignment());
Sec->setVA(Dot);
MinVA = std::min(MinVA, Dot);
Dot += Sec->getSize();
continue;
}
}
}
// ELF and Program headers need to be right before the first section in memory.
// Set their addresses accordingly.
MinVA = alignDown(MinVA - Out<ELFT>::ElfHeader->getSize() -
Out<ELFT>::ProgramHeaders->getSize(),
Target->PageSize);
Out<ELFT>::ElfHeader->setVA(MinVA);
Out<ELFT>::ProgramHeaders->setVA(Out<ELFT>::ElfHeader->getSize() + MinVA);
}
template <class ELFT>

View File

@ -1131,11 +1131,9 @@ template <class ELFT> void Writer<ELFT>::fixSectionAlignments() {
// list, but have them to simplify the code.
template <class ELFT> void Writer<ELFT>::fixHeaders() {
uintX_t BaseVA = ScriptConfig->DoLayout ? 0 : Target->getVAStart();
Out<ELFT>::ElfHeader->setVA(BaseVA);
Out<ELFT>::ElfHeader->setFileOffset(0);
Out<ELFT>::ElfHeader->setVA(BaseVA);
uintX_t Off = Out<ELFT>::ElfHeader->getSize();
Out<ELFT>::ProgramHeaders->setVA(Off + BaseVA);
Out<ELFT>::ProgramHeaders->setFileOffset(Off);
Out<ELFT>::ProgramHeaders->setVA(Off + BaseVA);
}
// Assign VAs (addresses at run-time) to output sections.
@ -1183,19 +1181,24 @@ static uintX_t getFileAlignment(uintX_t Off, OutputSectionBase<ELFT> *Sec) {
// Assign file offsets to output sections.
template <class ELFT> void Writer<ELFT>::assignFileOffsets() {
uintX_t Off =
Out<ELFT>::ElfHeader->getSize() + Out<ELFT>::ProgramHeaders->getSize();
uintX_t Off = 0;
for (OutputSectionBase<ELFT> *Sec : OutputSections) {
auto Set = [&](OutputSectionBase<ELFT> *Sec) {
if (Sec->getType() == SHT_NOBITS) {
Sec->setFileOffset(Off);
continue;
return;
}
Off = getFileAlignment<ELFT>(Off, Sec);
Sec->setFileOffset(Off);
Off += Sec->getSize();
}
};
Set(Out<ELFT>::ElfHeader);
Set(Out<ELFT>::ProgramHeaders);
for (OutputSectionBase<ELFT> *Sec : OutputSections)
Set(Sec);
SectionHeaderOff = alignTo(Off, sizeof(uintX_t));
FileSize = SectionHeaderOff + (OutputSections.size() + 1) * sizeof(Elf_Shdr);
}

View File

@ -0,0 +1,15 @@
# REQUIRES: x86
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
# RUN: echo "SECTIONS { . = 0x10000000; .text : {*(.text.*)} }" > %t.script
# RUN: ld.lld -o %t1 --script %t.script %t
# RUN: llvm-readobj -program-headers %t1 | FileCheck %s
# CHECK: ProgramHeaders [
# CHECK-NEXT: ProgramHeader {
# CHECK-NEXT: Type: PT_PHDR (0x6)
# CHECK-NEXT: Offset: 0x40
# CHECK-NEXT: VirtualAddress: 0xFFFF040
.global _start
_start:
nop