[llvm-commits] [lld] r171709 - in /lld/trunk: lib/ReaderWriter/ELF/WriterELF.cpp test/elf/phdr.objtxt test/elf/sections.objtxt test/elf/x86_64-kinds.test
Michael J. Spencer
bigcheesegs at gmail.com
Mon Jan 7 00:00:05 PST 2013
Author: mspencer
Date: Mon Jan 7 02:00:04 2013
New Revision: 171709
URL: http://llvm.org/viewvc/llvm-project?rev=171709&view=rev
Log:
[ELF] Emit the file header and program headers at the beginning of the first segment.
This is required for the loader to correctly set AT_PHDR.
With this lld can correctly link against dietlibc and get to main.
Modified:
lld/trunk/lib/ReaderWriter/ELF/WriterELF.cpp
lld/trunk/test/elf/phdr.objtxt
lld/trunk/test/elf/sections.objtxt
lld/trunk/test/elf/x86_64-kinds.test
Modified: lld/trunk/lib/ReaderWriter/ELF/WriterELF.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/WriterELF.cpp?rev=171709&r1=171708&r2=171709&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/WriterELF.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/WriterELF.cpp Mon Jan 7 02:00:04 2013
@@ -747,6 +747,11 @@
this->_align2 = section->align2();
}
+ /// Prepend a generic chunk to the segment.
+ void prepend(Chunk<target_endianness, max_align, is64Bits> *c) {
+ _sections.insert(_sections.begin(), c);
+ }
+
/// Sort segments depending on the property
/// If we have a Program Header segment, it should appear first
/// If we have a INTERP segment, that should appear after the Program Header
@@ -869,27 +874,19 @@
}
/// \brief Assign virtual addresses to the slices
- void assignVirtualAddress(uint64_t &addr, bool isFirstSegment) {
+ void assignVirtualAddress(uint64_t &addr) {
for (auto sei = slices_begin(), see = slices_end(); sei != see; ++sei) {
- bool firstSlice = (sei == slices_begin());
- // The first segment has distinct since it contains the
- // ELF header and the Program Header, if we get to the first segment
- // and the first slice, set it to the baseaddress
- // which is the segment address
- if (isFirstSegment && firstSlice)
- (*sei)->setVAddr(this->virtualAddr());
- else {
- // Align to a page
- addr = llvm::RoundUpToAlignment(addr, _options.pageSize());
- // Align to the slice alignment
- addr = llvm::RoundUpToAlignment(addr, (*sei)->align2());
- }
+ // Align to a page
+ addr = llvm::RoundUpToAlignment(addr, _options.pageSize());
+ // Align to the slice alignment
+ addr = llvm::RoundUpToAlignment(addr, (*sei)->align2());
+
bool virtualAddressSet = false;
for (auto si = (*sei)->sections_begin(), se = (*sei)->sections_end();
si != se; ++si) {
// Align the section address
addr = llvm::RoundUpToAlignment(addr, (*si)->align2());
- if (!isFirstSegment && !virtualAddressSet) {
+ if (!virtualAddressSet) {
(*sei)->setVAddr(addr);
virtualAddressSet = true;
}
@@ -897,6 +894,8 @@
if (auto s =
dyn_cast<Section<target_endianness, max_align, is64Bits>>(*si))
s->assignVirtualAddress(addr);
+ else
+ addr += (*si)->memSize();
(*si)->setMemSize(addr - (*si)->virtualAddr());
}
(*sei)->setMemSize(addr - (*sei)->virtualAddr());
@@ -1161,6 +1160,9 @@
ELFHeader()
: Chunk<target_endianness, max_align, is64Bits>(
"elfhdr", Chunk<target_endianness, max_align, is64Bits>::K_ELFHeader) {
+ this->_align2 = is64Bits ? 8 : 4;
+ this->_fsize = sizeof(Elf_Ehdr);
+ this->_msize = sizeof(Elf_Ehdr);
memset(_eh.e_ident, 0, llvm::ELF::EI_NIDENT);
e_ident(ELF::EI_MAG0, 0x7f);
e_ident(ELF::EI_MAG1, 'E');
@@ -1217,6 +1219,7 @@
: Chunk<target_endianness, max_align, is64Bits>(
"elfphdr",
Chunk<target_endianness, max_align, is64Bits>::K_ELFProgramHeader) {
+ this->_align2 = is64Bits ? 8 : 4;
resetProgramHeaders();
}
@@ -1245,6 +1248,10 @@
phdr->p_align = (phdr->p_type == llvm::ELF::PT_LOAD) ?
segment->pageSize() : (*sei)->align2();
}
+
+ this->_fsize = fileSize();
+ this->_msize = this->_fsize;
+
return ret;
}
@@ -1252,13 +1259,8 @@
_phi = _ph.begin();
}
- void setVAddr(uint64_t addr) {
- this->_start = llvm::RoundUpToAlignment(addr, 8);
- this->_fsize = this->_start - addr;
- }
-
uint64_t fileSize() {
- return this->_fsize + (sizeof (Elf_Phdr) * _ph.size());
+ return sizeof(Elf_Phdr) * _ph.size();
}
static inline bool classof(
@@ -1745,27 +1747,27 @@
}
void assignVirtualAddress() {
+ if (_segments.empty())
+ return;
+
uint64_t virtualAddress = _options.baseAddress();
- // Add the ELF Header
- if (_elfHeader) {
- _elfHeader->setFileOffset(0);
- _elfHeader->setVAddr(virtualAddress);
- }
- // Add the program header
- if (_programHeader) {
- _programHeader->setVAddr(
- uint64_t(virtualAddress + _elfHeader->fileSize()));
- _programHeader->setFileOffset(_elfHeader->fileSize());
- }
+ // HACK: This is a super dirty hack. The elf header and program header are
+ // not part of a section, but we need them to be loaded at the base address
+ // so that AT_PHDR is set correctly by the loader and so they are accessible
+ // at runtime. To do this we simply prepend them to the first Segment and
+ // let the layout logic take care of it.
+ _segments[0]->prepend(_programHeader);
+ _segments[0]->prepend(_elfHeader);
+
bool newSegmentHeaderAdded = true;
- while (true && !_segments.empty()) {
+ while (true) {
for (auto si : _segments) {
newSegmentHeaderAdded = _programHeader->addSegment(si);
}
if (!newSegmentHeaderAdded)
break;
- uint64_t fileoffset = _elfHeader->fileSize() + _programHeader->fileSize();
+ uint64_t fileoffset = 0;
uint64_t address = virtualAddress;
// Fix the offsets after adding the program header
for (auto &si : _segments) {
@@ -1780,7 +1782,7 @@
// The first segment has the virtualAddress set to the base address as
// we have added the file header and the program header dont align the
// first segment to the pagesize
- (*si)->assignVirtualAddress(address, (si == _segments.begin()));
+ (*si)->assignVirtualAddress(address);
(*si)->setMemSize(address - virtualAddress);
virtualAddress = llvm::RoundUpToAlignment(address, _options.pageSize());
}
@@ -2136,9 +2138,6 @@
if (ec)
return ec;
- for (auto si = _layout->sections_begin(); si != _layout->sections_end(); ++si)
- (*si)->write(this, buffer);
-
_elfHeader->e_ident(ELF::EI_CLASS, (_options.is64Bit() ? ELF::ELFCLASS64
: ELF::ELFCLASS32));
_elfHeader->e_ident(ELF::EI_DATA, _options.endianness() == llvm::support::big
@@ -2159,9 +2158,16 @@
uint64_t virtualAddr = 0;
_layout->findAtomAddrByName("_start", virtualAddr);
_elfHeader->e_entry(virtualAddr);
+
+ // HACK: We have to write out the header and program header here even though
+ // they are a member of a segment because only sections are written in the
+ // following loop.
_elfHeader->write(this, buffer);
_programHeader->write(this, buffer);
+ for (auto si = _layout->sections_begin(); si != _layout->sections_end(); ++si)
+ (*si)->write(this, buffer);
+
return buffer->commit();
}
Modified: lld/trunk/test/elf/phdr.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/phdr.objtxt?rev=171709&r1=171708&r2=171709&view=diff
==============================================================================
--- lld/trunk/test/elf/phdr.objtxt (original)
+++ lld/trunk/test/elf/phdr.objtxt Mon Jan 7 02:00:04 2013
@@ -3,17 +3,17 @@
ED: # Program Header 0
ED: (('p_type', 0x00000001)
ED: ('p_flags', 0x00000005)
-ED: ('p_offset', 0x00001000)
+ED: ('p_offset', 0x00000000)
ED: ('p_vaddr', 0x00000000)
ED: ('p_paddr', 0x00000000)
-ED: ('p_filesz', 0x00000025)
-ED: ('p_memsz', 0x00000025)
+ED: ('p_filesz', 0x000000d9)
+ED: ('p_memsz', 0x000000d9)
ED: ('p_align', 0x00001000)
ED: ),
ED: # Program Header 1
ED: (('p_type', 0x00000001)
ED: ('p_flags', 0x00000006)
-ED: ('p_offset', 0x00002000)
+ED: ('p_offset', 0x00001000)
ED: ('p_vaddr', 0x00001000)
ED: ('p_paddr', 0x00001000)
ED: ('p_filesz', 0x00000104)
Modified: lld/trunk/test/elf/sections.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/sections.objtxt?rev=171709&r1=171708&r2=171709&view=diff
==============================================================================
--- lld/trunk/test/elf/sections.objtxt (original)
+++ lld/trunk/test/elf/sections.objtxt Mon Jan 7 02:00:04 2013
@@ -1,9 +1,10 @@
-RUN: lld-core -reader ELF -writer ELF -o %t1 %p/Inputs/section-test.i386 | llvm-objdump -section-headers %t1 | FileCheck -check-prefix=OBJDUMP %s
+RUN: lld-core -reader ELF -writer ELF -o %t1 %p/Inputs/section-test.i386
+RUN: llvm-objdump -section-headers %t1 | FileCheck -check-prefix=OBJDUMP %s
RUN: llvm-readobj %t1 | FileCheck -check-prefix=READOBJ %s
RUN: elf-dump --dump-section %t1 | FileCheck -check-prefix=ED %s
OBJDUMP: 0 000000000 00000000000000000
-OBJDUMP: 1 .text 00000000a 00000000000000000 TEXT DATA
+OBJDUMP: 1 .text 00000000a 00000000000000074 TEXT DATA
OBJDUMP: 2 .data 000000004 00000000000001000 DATA
OBJDUMP: 3 .special 000000004 00000000000001004 DATA
OBJDUMP: 4 .anotherspecial 000000004 00000000000001008 DATA
@@ -16,8 +17,8 @@
READOBJ: Arch : i386
READOBJ: Address Size: 32 bits
READOBJ: Symbols
-READOBJ: baz FUNC 0 a 1000 global
-READOBJ: y DATA 1004 4 3008 global
+READOBJ: baz FUNC 74 a e8 global
+READOBJ: y DATA 1004 4 2008 global
ED: 'e_indent[EI_DATA]', 0x01
ED: 'e_machine', 0x0003
Modified: lld/trunk/test/elf/x86_64-kinds.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/x86_64-kinds.test?rev=171709&r1=171708&r2=171709&view=diff
==============================================================================
--- lld/trunk/test/elf/x86_64-kinds.test (original)
+++ lld/trunk/test/elf/x86_64-kinds.test Mon Jan 7 02:00:04 2013
@@ -1,11 +1,8 @@
-RUN: lld -flavor ld -target x86_64-linux -o %t && llvm-objdump -p %t \
-RUN: | FileCheck %s
-
-CHECK: ELF64-x86-64
-
RUN: lld -flavor ld -target x86_64-linux -o %t1 %p/Inputs/relocs.x86-64 \
RUN: && llvm-objdump -d %t1 | FileCheck %s -check-prefix=RELOCS
+RELOCS: ELF64-x86-64
+
// R_X86_64_32S
RELOCS: c7 04 25
RELOCS-NOT: 00 00 00 00
More information about the llvm-commits
mailing list