diff options
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/WriterELF.cpp | 82 | ||||
| -rw-r--r-- | lld/test/elf/phdr.objtxt | 8 | ||||
| -rw-r--r-- | lld/test/elf/sections.objtxt | 9 | ||||
| -rw-r--r-- | lld/test/elf/x86_64-kinds.test | 7 |
4 files changed, 55 insertions, 51 deletions
diff --git a/lld/lib/ReaderWriter/ELF/WriterELF.cpp b/lld/lib/ReaderWriter/ELF/WriterELF.cpp index 2dcbbce3ffb..b6e847ef4db 100644 --- a/lld/lib/ReaderWriter/ELF/WriterELF.cpp +++ b/lld/lib/ReaderWriter/ELF/WriterELF.cpp @@ -747,6 +747,11 @@ public: 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 @@ public: } /// \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 @@ public: 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 @@ public: 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 @@ public: : 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 @@ public: 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 @@ public: _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 @@ public: } 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 @@ public: // 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 @@ error_code ELFExecutableWriter<target_endianness, max_align, is64Bits> 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 @@ error_code ELFExecutableWriter<target_endianness, max_align, is64Bits> 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(); } diff --git a/lld/test/elf/phdr.objtxt b/lld/test/elf/phdr.objtxt index ea17ae6c003..79a4e42bc84 100644 --- a/lld/test/elf/phdr.objtxt +++ b/lld/test/elf/phdr.objtxt @@ -3,17 +3,17 @@ RUN: lld-core -reader ELF -writer ELF -o %t1 %p/Inputs/phdr.i386 | elf-dump %t1 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) diff --git a/lld/test/elf/sections.objtxt b/lld/test/elf/sections.objtxt index e8338aa17cf..e53aa8b812e 100644 --- a/lld/test/elf/sections.objtxt +++ b/lld/test/elf/sections.objtxt @@ -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: File Format : ELF32-i386 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 diff --git a/lld/test/elf/x86_64-kinds.test b/lld/test/elf/x86_64-kinds.test index 61c0eaead8a..cb09b00a826 100644 --- a/lld/test/elf/x86_64-kinds.test +++ b/lld/test/elf/x86_64-kinds.test @@ -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 |

