blob: adb25435a5b43ca04c59fd1fbd5a5267ac1c99ae [file] [log] [blame]
Petr Hosek05a04cb2017-08-01 00:33:58 +00001//===- Object.cpp -----------------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9#include "Object.h"
10#include "llvm-objcopy.h"
11
12using namespace llvm;
13using namespace object;
14using namespace ELF;
15
16template <class ELFT> void Segment::writeHeader(FileOutputBuffer &Out) const {
17 typedef typename ELFT::Ehdr Elf_Ehdr;
18 typedef typename ELFT::Phdr Elf_Phdr;
19
20 uint8_t *Buf = Out.getBufferStart();
21 Buf += sizeof(Elf_Ehdr) + Index * sizeof(Elf_Phdr);
22 Elf_Phdr &Phdr = *reinterpret_cast<Elf_Phdr *>(Buf);
23 Phdr.p_type = Type;
24 Phdr.p_flags = Flags;
25 Phdr.p_offset = Offset;
26 Phdr.p_vaddr = VAddr;
27 Phdr.p_paddr = PAddr;
28 Phdr.p_filesz = FileSize;
29 Phdr.p_memsz = MemSize;
30 Phdr.p_align = Align;
31}
32
33void Segment::finalize() {
34 auto FirstSec = firstSection();
35 if (FirstSec) {
36 // It is possible for a gap to be at the begining of a segment. Because of
37 // this we need to compute the new offset based on how large this gap was
38 // in the source file. Section layout should have already ensured that this
39 // space is not used for something else.
40 uint64_t OriginalOffset = Offset;
41 Offset = FirstSec->Offset - (FirstSec->OriginalOffset - OriginalOffset);
42 }
43}
44
Petr Hosekc4df10e2017-08-04 21:09:26 +000045void Segment::writeSegment(FileOutputBuffer &Out) const {
46 uint8_t *Buf = Out.getBufferStart() + Offset;
47 // We want to maintain segments' interstitial data and contents exactly.
48 // This lets us just copy segments directly.
49 std::copy(std::begin(Contents), std::end(Contents), Buf);
50}
51
Petr Hosek05a04cb2017-08-01 00:33:58 +000052void SectionBase::finalize() {}
53
54template <class ELFT>
55void SectionBase::writeHeader(FileOutputBuffer &Out) const {
56 uint8_t *Buf = Out.getBufferStart();
57 Buf += HeaderOffset;
58 typename ELFT::Shdr &Shdr = *reinterpret_cast<typename ELFT::Shdr *>(Buf);
59 Shdr.sh_name = NameIndex;
60 Shdr.sh_type = Type;
61 Shdr.sh_flags = Flags;
62 Shdr.sh_addr = Addr;
63 Shdr.sh_offset = Offset;
64 Shdr.sh_size = Size;
65 Shdr.sh_link = Link;
66 Shdr.sh_info = Info;
67 Shdr.sh_addralign = Align;
68 Shdr.sh_entsize = EntrySize;
69}
70
71void Section::writeSection(FileOutputBuffer &Out) const {
72 if (Type == SHT_NOBITS)
73 return;
74 uint8_t *Buf = Out.getBufferStart() + Offset;
75 std::copy(std::begin(Contents), std::end(Contents), Buf);
76}
77
78void StringTableSection::addString(StringRef Name) {
79 StrTabBuilder.add(Name);
80 Size = StrTabBuilder.getSize();
81}
82
83uint32_t StringTableSection::findIndex(StringRef Name) const {
84 return StrTabBuilder.getOffset(Name);
85}
86
87void StringTableSection::finalize() { StrTabBuilder.finalize(); }
88
89void StringTableSection::writeSection(FileOutputBuffer &Out) const {
90 StrTabBuilder.write(Out.getBufferStart() + Offset);
91}
92
93// Returns true IFF a section is wholly inside the range of a segment
94static bool sectionWithinSegment(const SectionBase &Section,
95 const Segment &Segment) {
96 // If a section is empty it should be treated like it has a size of 1. This is
97 // to clarify the case when an empty section lies on a boundary between two
98 // segments and ensures that the section "belongs" to the second segment and
99 // not the first.
100 uint64_t SecSize = Section.Size ? Section.Size : 1;
101 return Segment.Offset <= Section.OriginalOffset &&
102 Segment.Offset + Segment.FileSize >= Section.OriginalOffset + SecSize;
103}
104
105template <class ELFT>
106void Object<ELFT>::readProgramHeaders(const ELFFile<ELFT> &ElfFile) {
107 uint32_t Index = 0;
108 for (const auto &Phdr : unwrapOrError(ElfFile.program_headers())) {
Petr Hosekc4df10e2017-08-04 21:09:26 +0000109 ArrayRef<uint8_t> Data{ElfFile.base() + Phdr.p_offset,
110 (size_t)Phdr.p_filesz};
111 Segments.emplace_back(llvm::make_unique<Segment>(Data));
Petr Hosek05a04cb2017-08-01 00:33:58 +0000112 Segment &Seg = *Segments.back();
113 Seg.Type = Phdr.p_type;
114 Seg.Flags = Phdr.p_flags;
115 Seg.Offset = Phdr.p_offset;
116 Seg.VAddr = Phdr.p_vaddr;
117 Seg.PAddr = Phdr.p_paddr;
118 Seg.FileSize = Phdr.p_filesz;
119 Seg.MemSize = Phdr.p_memsz;
120 Seg.Align = Phdr.p_align;
121 Seg.Index = Index++;
122 for (auto &Section : Sections) {
123 if (sectionWithinSegment(*Section, Seg)) {
124 Seg.addSection(&*Section);
125 if (!Section->ParentSegment ||
126 Section->ParentSegment->Offset > Seg.Offset) {
127 Section->ParentSegment = &Seg;
128 }
129 }
130 }
131 }
132}
133
134template <class ELFT>
135std::unique_ptr<SectionBase>
136Object<ELFT>::makeSection(const llvm::object::ELFFile<ELFT> &ElfFile,
137 const Elf_Shdr &Shdr) {
138 ArrayRef<uint8_t> Data;
139 switch (Shdr.sh_type) {
140 case SHT_STRTAB:
141 return llvm::make_unique<StringTableSection>();
142 case SHT_NOBITS:
143 return llvm::make_unique<Section>(Data);
144 default:
145 Data = unwrapOrError(ElfFile.getSectionContents(&Shdr));
146 return llvm::make_unique<Section>(Data);
Petr Hosekc4df10e2017-08-04 21:09:26 +0000147 }
Petr Hosek05a04cb2017-08-01 00:33:58 +0000148}
149
150template <class ELFT>
151void Object<ELFT>::readSectionHeaders(const ELFFile<ELFT> &ElfFile) {
152 uint32_t Index = 0;
153 for (const auto &Shdr : unwrapOrError(ElfFile.sections())) {
154 if (Index == 0) {
155 ++Index;
156 continue;
157 }
158 SecPtr Sec = makeSection(ElfFile, Shdr);
159 Sec->Name = unwrapOrError(ElfFile.getSectionName(&Shdr));
160 Sec->Type = Shdr.sh_type;
161 Sec->Flags = Shdr.sh_flags;
162 Sec->Addr = Shdr.sh_addr;
163 Sec->Offset = Shdr.sh_offset;
164 Sec->OriginalOffset = Shdr.sh_offset;
165 Sec->Size = Shdr.sh_size;
166 Sec->Link = Shdr.sh_link;
167 Sec->Info = Shdr.sh_info;
168 Sec->Align = Shdr.sh_addralign;
169 Sec->EntrySize = Shdr.sh_entsize;
170 Sec->Index = Index++;
171 Sections.push_back(std::move(Sec));
172 }
173}
174
Petr Hosek05a04cb2017-08-01 00:33:58 +0000175template <class ELFT> Object<ELFT>::Object(const ELFObjectFile<ELFT> &Obj) {
176 const auto &ElfFile = *Obj.getELFFile();
177 const auto &Ehdr = *ElfFile.getHeader();
178
179 std::copy(Ehdr.e_ident, Ehdr.e_ident + 16, Ident);
180 Type = Ehdr.e_type;
181 Machine = Ehdr.e_machine;
182 Version = Ehdr.e_version;
183 Entry = Ehdr.e_entry;
184 Flags = Ehdr.e_flags;
185
186 readSectionHeaders(ElfFile);
187 readProgramHeaders(ElfFile);
188
189 SectionNames =
190 dyn_cast<StringTableSection>(Sections[Ehdr.e_shstrndx - 1].get());
191}
192
Petr Hosek05a04cb2017-08-01 00:33:58 +0000193template <class ELFT>
194void Object<ELFT>::writeHeader(FileOutputBuffer &Out) const {
195 uint8_t *Buf = Out.getBufferStart();
196 Elf_Ehdr &Ehdr = *reinterpret_cast<Elf_Ehdr *>(Buf);
197 std::copy(Ident, Ident + 16, Ehdr.e_ident);
198 Ehdr.e_type = Type;
199 Ehdr.e_machine = Machine;
200 Ehdr.e_version = Version;
201 Ehdr.e_entry = Entry;
202 Ehdr.e_phoff = sizeof(Elf_Ehdr);
203 Ehdr.e_shoff = SHOffset;
204 Ehdr.e_flags = Flags;
205 Ehdr.e_ehsize = sizeof(Elf_Ehdr);
206 Ehdr.e_phentsize = sizeof(Elf_Phdr);
207 Ehdr.e_phnum = Segments.size();
208 Ehdr.e_shentsize = sizeof(Elf_Shdr);
209 Ehdr.e_shnum = Sections.size() + 1;
210 Ehdr.e_shstrndx = SectionNames->Index;
211}
212
213template <class ELFT>
214void Object<ELFT>::writeProgramHeaders(FileOutputBuffer &Out) const {
215 for (auto &Phdr : Segments)
216 Phdr->template writeHeader<ELFT>(Out);
217}
218
219template <class ELFT>
220void Object<ELFT>::writeSectionHeaders(FileOutputBuffer &Out) const {
221 uint8_t *Buf = Out.getBufferStart() + SHOffset;
222 // This reference serves to write the dummy section header at the begining
223 // of the file.
224 Elf_Shdr &Shdr = *reinterpret_cast<Elf_Shdr *>(Buf);
225 Shdr.sh_name = 0;
226 Shdr.sh_type = SHT_NULL;
227 Shdr.sh_flags = 0;
228 Shdr.sh_addr = 0;
229 Shdr.sh_offset = 0;
230 Shdr.sh_size = 0;
231 Shdr.sh_link = 0;
232 Shdr.sh_info = 0;
233 Shdr.sh_addralign = 0;
234 Shdr.sh_entsize = 0;
235
236 for (auto &Section : Sections)
237 Section->template writeHeader<ELFT>(Out);
238}
239
240template <class ELFT>
241void Object<ELFT>::writeSectionData(FileOutputBuffer &Out) const {
242 for (auto &Section : Sections)
243 Section->writeSection(Out);
244}
245
Petr Hosekc4df10e2017-08-04 21:09:26 +0000246template <class ELFT> void ELFObject<ELFT>::sortSections() {
247 // Put all sections in offset order. Maintain the ordering as closely as
248 // possible while meeting that demand however.
249 auto CompareSections = [](const SecPtr &A, const SecPtr &B) {
250 return A->OriginalOffset < B->OriginalOffset;
251 };
252 std::stable_sort(std::begin(this->Sections), std::end(this->Sections),
253 CompareSections);
254}
255
256template <class ELFT> void ELFObject<ELFT>::assignOffsets() {
257 // Decide file offsets and indexes.
258 size_t PhdrSize = this->Segments.size() * sizeof(Elf_Phdr);
259 // We can put section data after the ELF header and the program headers.
260 uint64_t Offset = sizeof(Elf_Ehdr) + PhdrSize;
261 uint64_t Index = 1;
262 for (auto &Section : this->Sections) {
263 // The segment can have a different alignment than the section. In the case
264 // that there is a parent segment then as long as we satisfy the alignment
265 // of the segment it should follow that that the section is aligned.
266 if (Section->ParentSegment) {
267 auto FirstInSeg = Section->ParentSegment->firstSection();
268 if (FirstInSeg == Section.get()) {
269 Offset = alignTo(Offset, Section->ParentSegment->Align);
270 // There can be gaps at the start of a segment before the first section.
271 // So first we assign the alignment of the segment and then assign the
272 // location of the section from there
273 Section->Offset =
274 Offset + Section->OriginalOffset - Section->ParentSegment->Offset;
275 }
276 // We should respect interstitial gaps of allocated sections. We *must*
277 // maintain the memory image so that addresses are preserved. As, with the
278 // exception of SHT_NOBITS sections at the end of segments, the memory
279 // image is a copy of the file image, we preserve the file image as well.
280 // There's a strange case where a thread local SHT_NOBITS can cause the
281 // memory image and file image to not be the same. This occurs, on some
282 // systems, when a thread local SHT_NOBITS is between two SHT_PROGBITS
283 // and the thread local SHT_NOBITS section is at the end of a TLS segment.
284 // In this case to faithfully copy the segment file image we must use
285 // relative offsets. In any other case this would be the same as using the
286 // relative addresses so this should maintian the memory image as desired.
287 Offset = FirstInSeg->Offset + Section->OriginalOffset -
288 FirstInSeg->OriginalOffset;
289 }
290 // Alignment should have already been handled by the above if statement if
291 // this if this section is in a segment. Technically this shouldn't do
292 // anything bad if the alignments of the sections are all correct and the
293 // file image isn't corrupted. Still in sticking with the motto "maintain
294 // the file image" we should avoid messing up the file image if the
295 // alignment disagrees with the file image.
296 if (!Section->ParentSegment && Section->Align)
297 Offset = alignTo(Offset, Section->Align);
298 Section->Offset = Offset;
299 Section->Index = Index++;
300 if (Section->Type != SHT_NOBITS)
301 Offset += Section->Size;
302 }
303 // 'offset' should now be just after all the section data so we should set the
304 // section header table offset to be exactly here. This spot might not be
305 // aligned properly however so we should align it as needed. For 32-bit ELF
306 // this needs to be 4-byte aligned and on 64-bit it needs to be 8-byte aligned
307 // so the size of ELFT::Addr is used to ensure this.
308 Offset = alignTo(Offset, sizeof(typename ELFT::Addr));
309 this->SHOffset = Offset;
310}
311
312template <class ELFT> size_t ELFObject<ELFT>::totalSize() const {
313 // We already have the section header offset so we can calculate the total
314 // size by just adding up the size of each section header.
315 return this->SHOffset + this->Sections.size() * sizeof(Elf_Shdr) +
316 sizeof(Elf_Shdr);
317}
318
319template <class ELFT> void ELFObject<ELFT>::write(FileOutputBuffer &Out) const {
320 this->writeHeader(Out);
321 this->writeProgramHeaders(Out);
322 this->writeSectionData(Out);
323 this->writeSectionHeaders(Out);
324}
325
326template <class ELFT> void ELFObject<ELFT>::finalize() {
327 for (const auto &Section : this->Sections) {
328 this->SectionNames->addString(Section->Name);
329 }
330
331 sortSections();
332 assignOffsets();
333
334 // Finalize SectionNames first so that we can assign name indexes.
335 this->SectionNames->finalize();
336 // Finally now that all offsets and indexes have been set we can finalize any
337 // remaining issues.
338 uint64_t Offset = this->SHOffset + sizeof(Elf_Shdr);
339 for (auto &Section : this->Sections) {
340 Section->HeaderOffset = Offset;
341 Offset += sizeof(Elf_Shdr);
342 Section->NameIndex = this->SectionNames->findIndex(Section->Name);
343 Section->finalize();
344 }
345
346 for (auto &Segment : this->Segments)
347 Segment->finalize();
348}
349
350template <class ELFT> size_t BinaryObject<ELFT>::totalSize() const {
351 return TotalSize;
352}
353
354template <class ELFT>
355void BinaryObject<ELFT>::write(FileOutputBuffer &Out) const {
356 for (auto &Segment : this->Segments) {
Petr Hosekd53951d2017-08-04 23:18:18 +0000357 // GNU objcopy does not output segments that do not cover a section. Such
358 // segments can sometimes be produced by LLD due to how LLD handles PT_PHDR.
359 if (Segment->Type == llvm::ELF::PT_LOAD &&
360 Segment->firstSection() != nullptr) {
Petr Hosekc4df10e2017-08-04 21:09:26 +0000361 Segment->writeSegment(Out);
362 }
363 }
364}
365
366template <class ELFT> void BinaryObject<ELFT>::finalize() {
367 for (auto &Segment : this->Segments)
368 Segment->finalize();
369
370 // Put all segments in offset order.
371 auto CompareSegments = [](const SegPtr &A, const SegPtr &B) {
372 return A->Offset < B->Offset;
373 };
374 std::sort(std::begin(this->Segments), std::end(this->Segments),
375 CompareSegments);
376
377 uint64_t Offset = 0;
378 for (auto &Segment : this->Segments) {
Petr Hosekd53951d2017-08-04 23:18:18 +0000379 if (Segment->Type == llvm::ELF::PT_LOAD &&
380 Segment->firstSection() != nullptr) {
Petr Hosekc4df10e2017-08-04 21:09:26 +0000381 Offset = alignTo(Offset, Segment->Align);
382 Segment->Offset = Offset;
383 Offset += Segment->FileSize;
384 }
385 }
386 TotalSize = Offset;
Petr Hosek05a04cb2017-08-01 00:33:58 +0000387}
388
Petr Hosek35fdbd52017-08-01 05:31:50 +0000389template class Object<ELF64LE>;
390template class Object<ELF64BE>;
391template class Object<ELF32LE>;
392template class Object<ELF32BE>;
Petr Hosekc4df10e2017-08-04 21:09:26 +0000393
394template class ELFObject<ELF64LE>;
395template class ELFObject<ELF64BE>;
396template class ELFObject<ELF32LE>;
397template class ELFObject<ELF32BE>;
398
399template class BinaryObject<ELF64LE>;
400template class BinaryObject<ELF64BE>;
401template class BinaryObject<ELF32LE>;
402template class BinaryObject<ELF32BE>;