forked from OSchip/llvm-project
[ELF] Fix first PT_LOAD segment VA calculation, when linker script is used
llvm-svn: 274342
This commit is contained in:
parent
beb24f5b20
commit
467c4d5538
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
Loading…
Reference in New Issue