blob: 944075d61978c8224761355ac3250c46a59cb001 [file] [log] [blame]
Eugene Zelenko0ad18f82017-11-01 21:16:06 +00001//===- Object.cpp ---------------------------------------------------------===//
Petr Hosek05a04cb2017-08-01 00:33:58 +00002//
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//===----------------------------------------------------------------------===//
Eugene Zelenko0ad18f82017-11-01 21:16:06 +00009
Petr Hosek05a04cb2017-08-01 00:33:58 +000010#include "Object.h"
11#include "llvm-objcopy.h"
Eugene Zelenko0ad18f82017-11-01 21:16:06 +000012#include "llvm/ADT/ArrayRef.h"
13#include "llvm/ADT/STLExtras.h"
14#include "llvm/ADT/StringRef.h"
15#include "llvm/ADT/Twine.h"
16#include "llvm/ADT/iterator_range.h"
17#include "llvm/BinaryFormat/ELF.h"
18#include "llvm/Object/ELFObjectFile.h"
19#include "llvm/Support/ErrorHandling.h"
20#include "llvm/Support/FileOutputBuffer.h"
Jake Ehrlichea07d3c2018-01-25 22:15:14 +000021#include "llvm/Support/Path.h"
Eugene Zelenko0ad18f82017-11-01 21:16:06 +000022#include <algorithm>
23#include <cstddef>
24#include <cstdint>
25#include <iterator>
26#include <utility>
27#include <vector>
Petr Hosek05a04cb2017-08-01 00:33:58 +000028
29using namespace llvm;
30using namespace object;
31using namespace ELF;
32
Aaron Ballman09f46a72018-01-25 21:03:38 +000033template <class ELFT> void Segment::writeHeader(FileOutputBuffer &Out) const {
Eugene Zelenko0ad18f82017-11-01 21:16:06 +000034 using Elf_Ehdr = typename ELFT::Ehdr;
35 using Elf_Phdr = typename ELFT::Phdr;
Petr Hosek05a04cb2017-08-01 00:33:58 +000036
Aaron Ballman09f46a72018-01-25 21:03:38 +000037 uint8_t *Buf = Out.getBufferStart();
38 Buf += sizeof(Elf_Ehdr) + Index * sizeof(Elf_Phdr);
Petr Hosek05a04cb2017-08-01 00:33:58 +000039 Elf_Phdr &Phdr = *reinterpret_cast<Elf_Phdr *>(Buf);
Aaron Ballman09f46a72018-01-25 21:03:38 +000040 Phdr.p_type = Type;
41 Phdr.p_flags = Flags;
42 Phdr.p_offset = Offset;
43 Phdr.p_vaddr = VAddr;
44 Phdr.p_paddr = PAddr;
45 Phdr.p_filesz = FileSize;
46 Phdr.p_memsz = MemSize;
47 Phdr.p_align = Align;
48}
49
50void Segment::writeSegment(FileOutputBuffer &Out) const {
51 uint8_t *Buf = Out.getBufferStart() + Offset;
52 // We want to maintain segments' interstitial data and contents exactly.
53 // This lets us just copy segments directly.
54 std::copy(std::begin(Contents), std::end(Contents), Buf);
Petr Hosekc4df10e2017-08-04 21:09:26 +000055}
56
Jake Ehrlich36a2eb32017-10-10 18:47:09 +000057void SectionBase::removeSectionReferences(const SectionBase *Sec) {}
Jake Ehrlichf5a43772017-09-25 20:37:28 +000058void SectionBase::initialize(SectionTableRef SecTable) {}
Petr Hosek05a04cb2017-08-01 00:33:58 +000059void SectionBase::finalize() {}
60
Aaron Ballman09f46a72018-01-25 21:03:38 +000061template <class ELFT>
62void SectionBase::writeHeader(FileOutputBuffer &Out) const {
63 uint8_t *Buf = Out.getBufferStart();
64 Buf += HeaderOffset;
Petr Hosek05a04cb2017-08-01 00:33:58 +000065 typename ELFT::Shdr &Shdr = *reinterpret_cast<typename ELFT::Shdr *>(Buf);
Aaron Ballman09f46a72018-01-25 21:03:38 +000066 Shdr.sh_name = NameIndex;
67 Shdr.sh_type = Type;
68 Shdr.sh_flags = Flags;
69 Shdr.sh_addr = Addr;
70 Shdr.sh_offset = Offset;
71 Shdr.sh_size = Size;
72 Shdr.sh_link = Link;
73 Shdr.sh_info = Info;
74 Shdr.sh_addralign = Align;
75 Shdr.sh_entsize = EntrySize;
Petr Hosek05a04cb2017-08-01 00:33:58 +000076}
77
Aaron Ballman09f46a72018-01-25 21:03:38 +000078void Section::writeSection(FileOutputBuffer &Out) const {
79 if (Type == SHT_NOBITS)
Petr Hosek05a04cb2017-08-01 00:33:58 +000080 return;
Aaron Ballman09f46a72018-01-25 21:03:38 +000081 uint8_t *Buf = Out.getBufferStart() + Offset;
82 std::copy(std::begin(Contents), std::end(Contents), Buf);
Petr Hosek05a04cb2017-08-01 00:33:58 +000083}
84
Aaron Ballman09f46a72018-01-25 21:03:38 +000085void OwnedDataSection::writeSection(FileOutputBuffer &Out) const {
86 uint8_t *Buf = Out.getBufferStart() + Offset;
87 std::copy(std::begin(Data), std::end(Data), Buf);
Jake Ehrliche8437de2017-12-19 00:47:30 +000088}
89
Petr Hosek05a04cb2017-08-01 00:33:58 +000090void StringTableSection::addString(StringRef Name) {
91 StrTabBuilder.add(Name);
92 Size = StrTabBuilder.getSize();
93}
94
95uint32_t StringTableSection::findIndex(StringRef Name) const {
96 return StrTabBuilder.getOffset(Name);
97}
98
99void StringTableSection::finalize() { StrTabBuilder.finalize(); }
100
Aaron Ballman09f46a72018-01-25 21:03:38 +0000101void StringTableSection::writeSection(FileOutputBuffer &Out) const {
102 StrTabBuilder.write(Out.getBufferStart() + Offset);
Petr Hosek05a04cb2017-08-01 00:33:58 +0000103}
104
Petr Hosekc1135772017-09-13 03:04:50 +0000105static bool isValidReservedSectionIndex(uint16_t Index, uint16_t Machine) {
Petr Hosekec2b3fc2017-09-07 23:02:50 +0000106 switch (Index) {
107 case SHN_ABS:
108 case SHN_COMMON:
Petr Hosekec2b3fc2017-09-07 23:02:50 +0000109 return true;
Petr Hosekec2b3fc2017-09-07 23:02:50 +0000110 }
Petr Hosekc1135772017-09-13 03:04:50 +0000111 if (Machine == EM_HEXAGON) {
112 switch (Index) {
113 case SHN_HEXAGON_SCOMMON:
114 case SHN_HEXAGON_SCOMMON_2:
115 case SHN_HEXAGON_SCOMMON_4:
116 case SHN_HEXAGON_SCOMMON_8:
117 return true;
118 }
119 }
120 return false;
Petr Hosekec2b3fc2017-09-07 23:02:50 +0000121}
122
123uint16_t Symbol::getShndx() const {
124 if (DefinedIn != nullptr) {
125 return DefinedIn->Index;
126 }
127 switch (ShndxType) {
128 // This means that we don't have a defined section but we do need to
129 // output a legitimate section index.
130 case SYMBOL_SIMPLE_INDEX:
131 return SHN_UNDEF;
132 case SYMBOL_ABS:
133 case SYMBOL_COMMON:
134 case SYMBOL_HEXAGON_SCOMMON:
135 case SYMBOL_HEXAGON_SCOMMON_2:
136 case SYMBOL_HEXAGON_SCOMMON_4:
137 case SYMBOL_HEXAGON_SCOMMON_8:
138 return static_cast<uint16_t>(ShndxType);
139 }
140 llvm_unreachable("Symbol with invalid ShndxType encountered");
141}
142
Petr Hosek79cee9e2017-08-29 02:12:03 +0000143void SymbolTableSection::addSymbol(StringRef Name, uint8_t Bind, uint8_t Type,
144 SectionBase *DefinedIn, uint64_t Value,
Jake Ehrlich30d927a2018-01-02 23:01:24 +0000145 uint8_t Visibility, uint16_t Shndx,
146 uint64_t Sz) {
Petr Hosek79cee9e2017-08-29 02:12:03 +0000147 Symbol Sym;
148 Sym.Name = Name;
149 Sym.Binding = Bind;
150 Sym.Type = Type;
151 Sym.DefinedIn = DefinedIn;
Petr Hosekec2b3fc2017-09-07 23:02:50 +0000152 if (DefinedIn == nullptr) {
Petr Hosekc1135772017-09-13 03:04:50 +0000153 if (Shndx >= SHN_LORESERVE)
Petr Hosekec2b3fc2017-09-07 23:02:50 +0000154 Sym.ShndxType = static_cast<SymbolShndxType>(Shndx);
155 else
156 Sym.ShndxType = SYMBOL_SIMPLE_INDEX;
157 }
Petr Hosek79cee9e2017-08-29 02:12:03 +0000158 Sym.Value = Value;
Jake Ehrlich30d927a2018-01-02 23:01:24 +0000159 Sym.Visibility = Visibility;
Petr Hosek79cee9e2017-08-29 02:12:03 +0000160 Sym.Size = Sz;
161 Sym.Index = Symbols.size();
162 Symbols.emplace_back(llvm::make_unique<Symbol>(Sym));
163 Size += this->EntrySize;
164}
165
Jake Ehrlich36a2eb32017-10-10 18:47:09 +0000166void SymbolTableSection::removeSectionReferences(const SectionBase *Sec) {
167 if (SymbolNames == Sec) {
168 error("String table " + SymbolNames->Name +
169 " cannot be removed because it is referenced by the symbol table " +
170 this->Name);
171 }
172 auto Iter =
173 std::remove_if(std::begin(Symbols), std::end(Symbols),
174 [=](const SymPtr &Sym) { return Sym->DefinedIn == Sec; });
175 Size -= (std::end(Symbols) - Iter) * this->EntrySize;
176 Symbols.erase(Iter, std::end(Symbols));
177}
178
Jake Ehrlich27a29b02018-01-05 19:19:09 +0000179void SymbolTableSection::localize(
180 std::function<bool(const Symbol &)> ToLocalize) {
181 for (const auto &Sym : Symbols) {
182 if (ToLocalize(*Sym))
183 Sym->Binding = STB_LOCAL;
184 }
185
186 // Now that the local symbols aren't grouped at the start we have to reorder
187 // the symbols to respect this property.
188 std::stable_partition(
189 std::begin(Symbols), std::end(Symbols),
190 [](const SymPtr &Sym) { return Sym->Binding == STB_LOCAL; });
191
192 // Lastly we fix the symbol indexes.
193 uint32_t Index = 0;
194 for (auto &Sym : Symbols)
195 Sym->Index = Index++;
196}
197
Jake Ehrlichf5a43772017-09-25 20:37:28 +0000198void SymbolTableSection::initialize(SectionTableRef SecTable) {
199 Size = 0;
200 setStrTab(SecTable.getSectionOfType<StringTableSection>(
201 Link,
202 "Symbol table has link index of " + Twine(Link) +
203 " which is not a valid index",
204 "Symbol table has link index of " + Twine(Link) +
205 " which is not a string table"));
206}
207
Petr Hosek79cee9e2017-08-29 02:12:03 +0000208void SymbolTableSection::finalize() {
209 // Make sure SymbolNames is finalized before getting name indexes.
210 SymbolNames->finalize();
211
212 uint32_t MaxLocalIndex = 0;
213 for (auto &Sym : Symbols) {
214 Sym->NameIndex = SymbolNames->findIndex(Sym->Name);
215 if (Sym->Binding == STB_LOCAL)
216 MaxLocalIndex = std::max(MaxLocalIndex, Sym->Index);
217 }
218 // Now we need to set the Link and Info fields.
219 Link = SymbolNames->Index;
220 Info = MaxLocalIndex + 1;
221}
222
223void SymbolTableSection::addSymbolNames() {
224 // Add all of our strings to SymbolNames so that SymbolNames has the right
225 // size before layout is decided.
226 for (auto &Sym : Symbols)
227 SymbolNames->addString(Sym->Name);
228}
229
230const Symbol *SymbolTableSection::getSymbolByIndex(uint32_t Index) const {
231 if (Symbols.size() <= Index)
232 error("Invalid symbol index: " + Twine(Index));
233 return Symbols[Index].get();
234}
235
236template <class ELFT>
Aaron Ballman09f46a72018-01-25 21:03:38 +0000237void SymbolTableSectionImpl<ELFT>::writeSection(FileOutputBuffer &Out) const {
Petr Hosek79cee9e2017-08-29 02:12:03 +0000238 uint8_t *Buf = Out.getBufferStart();
Aaron Ballman09f46a72018-01-25 21:03:38 +0000239 Buf += Offset;
Petr Hosek79cee9e2017-08-29 02:12:03 +0000240 typename ELFT::Sym *Sym = reinterpret_cast<typename ELFT::Sym *>(Buf);
241 // Loop though symbols setting each entry of the symbol table.
Aaron Ballman09f46a72018-01-25 21:03:38 +0000242 for (auto &Symbol : Symbols) {
Petr Hosek79cee9e2017-08-29 02:12:03 +0000243 Sym->st_name = Symbol->NameIndex;
244 Sym->st_value = Symbol->Value;
245 Sym->st_size = Symbol->Size;
Jake Ehrlich30d927a2018-01-02 23:01:24 +0000246 Sym->st_other = Symbol->Visibility;
Petr Hosek79cee9e2017-08-29 02:12:03 +0000247 Sym->setBinding(Symbol->Binding);
248 Sym->setType(Symbol->Type);
Petr Hosekec2b3fc2017-09-07 23:02:50 +0000249 Sym->st_shndx = Symbol->getShndx();
Petr Hosek79cee9e2017-08-29 02:12:03 +0000250 ++Sym;
251 }
252}
253
Jake Ehrlich9f1a3902017-09-26 18:02:25 +0000254template <class SymTabType>
Jake Ehrlich36a2eb32017-10-10 18:47:09 +0000255void RelocSectionWithSymtabBase<SymTabType>::removeSectionReferences(
256 const SectionBase *Sec) {
257 if (Symbols == Sec) {
Jake Ehrlich777fb002017-12-15 20:17:55 +0000258 error("Symbol table " + Symbols->Name + " cannot be removed because it is "
259 "referenced by the relocation "
260 "section " +
Jake Ehrlich36a2eb32017-10-10 18:47:09 +0000261 this->Name);
262 }
263}
264
265template <class SymTabType>
266void RelocSectionWithSymtabBase<SymTabType>::initialize(
267 SectionTableRef SecTable) {
Jake Ehrlich9f1a3902017-09-26 18:02:25 +0000268 setSymTab(SecTable.getSectionOfType<SymTabType>(
Jake Ehrlichf5a43772017-09-25 20:37:28 +0000269 Link,
270 "Link field value " + Twine(Link) + " in section " + Name + " is invalid",
271 "Link field value " + Twine(Link) + " in section " + Name +
272 " is not a symbol table"));
273
Jake Ehrlich9f1a3902017-09-26 18:02:25 +0000274 if (Info != SHN_UNDEF)
Jake Ehrlich777fb002017-12-15 20:17:55 +0000275 setSection(SecTable.getSection(Info,
276 "Info field value " + Twine(Info) +
277 " in section " + Name + " is invalid"));
James Y Knight2ea995a2017-09-26 22:44:01 +0000278 else
279 setSection(nullptr);
Jake Ehrlichf5a43772017-09-25 20:37:28 +0000280}
281
Jake Ehrlich36a2eb32017-10-10 18:47:09 +0000282template <class SymTabType>
283void RelocSectionWithSymtabBase<SymTabType>::finalize() {
Petr Hosekd7df9b22017-09-06 23:41:02 +0000284 this->Link = Symbols->Index;
Jake Ehrlich9f1a3902017-09-26 18:02:25 +0000285 if (SecToApplyRel != nullptr)
286 this->Info = SecToApplyRel->Index;
Petr Hosekd7df9b22017-09-06 23:41:02 +0000287}
288
289template <class ELFT>
290void setAddend(Elf_Rel_Impl<ELFT, false> &Rel, uint64_t Addend) {}
291
292template <class ELFT>
293void setAddend(Elf_Rel_Impl<ELFT, true> &Rela, uint64_t Addend) {
294 Rela.r_addend = Addend;
295}
296
Aaron Ballman09f46a72018-01-25 21:03:38 +0000297template <class ELFT>
298template <class T>
299void RelocationSection<ELFT>::writeRel(T *Buf) const {
Petr Hosekd7df9b22017-09-06 23:41:02 +0000300 for (const auto &Reloc : Relocations) {
301 Buf->r_offset = Reloc.Offset;
302 setAddend(*Buf, Reloc.Addend);
303 Buf->setSymbolAndType(Reloc.RelocSymbol->Index, Reloc.Type, false);
304 ++Buf;
305 }
306}
307
308template <class ELFT>
Aaron Ballman09f46a72018-01-25 21:03:38 +0000309void RelocationSection<ELFT>::writeSection(FileOutputBuffer &Out) const {
310 uint8_t *Buf = Out.getBufferStart() + Offset;
311 if (Type == SHT_REL)
312 writeRel(reinterpret_cast<Elf_Rel *>(Buf));
Petr Hosekd7df9b22017-09-06 23:41:02 +0000313 else
Aaron Ballman09f46a72018-01-25 21:03:38 +0000314 writeRel(reinterpret_cast<Elf_Rela *>(Buf));
Petr Hosekd7df9b22017-09-06 23:41:02 +0000315}
316
Aaron Ballman09f46a72018-01-25 21:03:38 +0000317void DynamicRelocationSection::writeSection(FileOutputBuffer &Out) const {
318 std::copy(std::begin(Contents), std::end(Contents),
319 Out.getBufferStart() + Offset);
Jake Ehrlich9f1a3902017-09-26 18:02:25 +0000320}
321
Jake Ehrlich36a2eb32017-10-10 18:47:09 +0000322void SectionWithStrTab::removeSectionReferences(const SectionBase *Sec) {
323 if (StrTab == Sec) {
Jake Ehrlich777fb002017-12-15 20:17:55 +0000324 error("String table " + StrTab->Name + " cannot be removed because it is "
325 "referenced by the section " +
Jake Ehrlich36a2eb32017-10-10 18:47:09 +0000326 this->Name);
327 }
328}
329
Jake Ehrliche5d424b2017-09-20 17:11:58 +0000330bool SectionWithStrTab::classof(const SectionBase *S) {
331 return isa<DynamicSymbolTableSection>(S) || isa<DynamicSection>(S);
332}
333
Jake Ehrlichf5a43772017-09-25 20:37:28 +0000334void SectionWithStrTab::initialize(SectionTableRef SecTable) {
Jake Ehrlich777fb002017-12-15 20:17:55 +0000335 auto StrTab = SecTable.getSection(Link,
336 "Link field value " + Twine(Link) +
337 " in section " + Name + " is invalid");
Jake Ehrlich70bd75f2017-10-10 21:28:22 +0000338 if (StrTab->Type != SHT_STRTAB) {
339 error("Link field value " + Twine(Link) + " in section " + Name +
340 " is not a string table");
341 }
342 setStrTab(StrTab);
Jake Ehrlichf5a43772017-09-25 20:37:28 +0000343}
344
Jake Ehrliche5d424b2017-09-20 17:11:58 +0000345void SectionWithStrTab::finalize() { this->Link = StrTab->Index; }
346
Jake Ehrlichea07d3c2018-01-25 22:15:14 +0000347template <class ELFT>
348void GnuDebugLinkSection<ELFT>::init(StringRef File, StringRef Data) {
349 FileName = sys::path::stem(File);
350 // The format for the .gnu_debuglink starts with the stemmed file name and is
351 // followed by a null terminator and then the CRC32 of the file. The CRC32
352 // should be 4 byte aligned. So we add the FileName size, a 1 for the null
353 // byte, and then finally push the size to alignment and add 4.
354 Size = alignTo(FileName.size() + 1, 4) + 4;
355 // The CRC32 will only be aligned if we align the whole section.
356 Align = 4;
357 Type = ELF::SHT_PROGBITS;
358 Name = ".gnu_debuglink";
359 // For sections not found in segments, OriginalOffset is only used to
360 // establish the order that sections should go in. By using the maximum
361 // possible offset we cause this section to wind up at the end.
362 OriginalOffset = std::numeric_limits<uint64_t>::max();
363 JamCRC crc;
364 crc.update(ArrayRef<char>(Data.data(), Data.size()));
365 // The CRC32 value needs to be complemented because the JamCRC dosn't
366 // finalize the CRC32 value. It also dosn't negate the initial CRC32 value
367 // but it starts by default at 0xFFFFFFFF which is the complement of zero.
368 CRC32 = ~crc.getCRC();
369}
370
371template <class ELFT>
372GnuDebugLinkSection<ELFT>::GnuDebugLinkSection(StringRef File)
373 : FileName(File) {
374 // Read in the file to compute the CRC of it.
375 auto DebugOrErr = MemoryBuffer::getFile(File);
376 if (!DebugOrErr)
377 error("'" + File + "': " + DebugOrErr.getError().message());
378 auto Debug = std::move(*DebugOrErr);
379 init(File, Debug->getBuffer());
380}
381
382template <class ELFT>
383void GnuDebugLinkSection<ELFT>::writeSection(FileOutputBuffer &Out) const {
384 auto Buf = Out.getBufferStart() + Offset;
385 char *File = reinterpret_cast<char *>(Buf);
386 Elf_Word *CRC = reinterpret_cast<Elf_Word *>(Buf + Size - sizeof(Elf_Word));
387 *CRC = CRC32;
388 std::copy(std::begin(FileName), std::end(FileName), File);
389}
390
Petr Hosek05a04cb2017-08-01 00:33:58 +0000391// Returns true IFF a section is wholly inside the range of a segment
392static bool sectionWithinSegment(const SectionBase &Section,
393 const Segment &Segment) {
394 // If a section is empty it should be treated like it has a size of 1. This is
395 // to clarify the case when an empty section lies on a boundary between two
396 // segments and ensures that the section "belongs" to the second segment and
397 // not the first.
398 uint64_t SecSize = Section.Size ? Section.Size : 1;
399 return Segment.Offset <= Section.OriginalOffset &&
400 Segment.Offset + Segment.FileSize >= Section.OriginalOffset + SecSize;
401}
402
Jake Ehrlichd246b0a2017-09-19 21:37:35 +0000403// Returns true IFF a segment's original offset is inside of another segment's
404// range.
405static bool segmentOverlapsSegment(const Segment &Child,
406 const Segment &Parent) {
407
408 return Parent.OriginalOffset <= Child.OriginalOffset &&
409 Parent.OriginalOffset + Parent.FileSize > Child.OriginalOffset;
410}
411
Jake Ehrlich46814be2018-01-22 19:27:30 +0000412static bool compareSegmentsByOffset(const Segment *A, const Segment *B) {
Jake Ehrlichd49c92b2017-11-15 19:13:31 +0000413 // Any segment without a parent segment should come before a segment
414 // that has a parent segment.
415 if (A->OriginalOffset < B->OriginalOffset)
416 return true;
417 if (A->OriginalOffset > B->OriginalOffset)
418 return false;
419 return A->Index < B->Index;
420}
421
Jake Ehrlich46814be2018-01-22 19:27:30 +0000422static bool compareSegmentsByPAddr(const Segment *A, const Segment *B) {
423 if (A->PAddr < B->PAddr)
424 return true;
425 if (A->PAddr > B->PAddr)
426 return false;
427 return A->Index < B->Index;
428}
429
Aaron Ballman09f46a72018-01-25 21:03:38 +0000430template <class ELFT>
431void Object<ELFT>::readProgramHeaders(const ELFFile<ELFT> &ElfFile) {
Petr Hosek05a04cb2017-08-01 00:33:58 +0000432 uint32_t Index = 0;
433 for (const auto &Phdr : unwrapOrError(ElfFile.program_headers())) {
Petr Hosekc4df10e2017-08-04 21:09:26 +0000434 ArrayRef<uint8_t> Data{ElfFile.base() + Phdr.p_offset,
435 (size_t)Phdr.p_filesz};
Aaron Ballman09f46a72018-01-25 21:03:38 +0000436 Segments.emplace_back(llvm::make_unique<Segment>(Data));
437 Segment &Seg = *Segments.back();
Petr Hosek05a04cb2017-08-01 00:33:58 +0000438 Seg.Type = Phdr.p_type;
439 Seg.Flags = Phdr.p_flags;
Petr Hosek3f383832017-08-26 01:32:20 +0000440 Seg.OriginalOffset = Phdr.p_offset;
Petr Hosek05a04cb2017-08-01 00:33:58 +0000441 Seg.Offset = Phdr.p_offset;
442 Seg.VAddr = Phdr.p_vaddr;
443 Seg.PAddr = Phdr.p_paddr;
444 Seg.FileSize = Phdr.p_filesz;
445 Seg.MemSize = Phdr.p_memsz;
446 Seg.Align = Phdr.p_align;
447 Seg.Index = Index++;
Aaron Ballman09f46a72018-01-25 21:03:38 +0000448 for (auto &Section : Sections) {
449 if (sectionWithinSegment(*Section, Seg)) {
450 Seg.addSection(&*Section);
451 if (!Section->ParentSegment ||
452 Section->ParentSegment->Offset > Seg.Offset) {
453 Section->ParentSegment = &Seg;
Petr Hosek05a04cb2017-08-01 00:33:58 +0000454 }
455 }
456 }
457 }
Jake Ehrlichd246b0a2017-09-19 21:37:35 +0000458 // Now we do an O(n^2) loop through the segments in order to match up
459 // segments.
Aaron Ballman09f46a72018-01-25 21:03:38 +0000460 for (auto &Child : Segments) {
461 for (auto &Parent : Segments) {
Jake Ehrlichd246b0a2017-09-19 21:37:35 +0000462 // Every segment will overlap with itself but we don't want a segment to
463 // be it's own parent so we avoid that situation.
Aaron Ballman09f46a72018-01-25 21:03:38 +0000464 if (&Child != &Parent && segmentOverlapsSegment(*Child, *Parent)) {
Jake Ehrlichd246b0a2017-09-19 21:37:35 +0000465 // We want a canonical "most parental" segment but this requires
466 // inspecting the ParentSegment.
Aaron Ballman09f46a72018-01-25 21:03:38 +0000467 if (compareSegmentsByOffset(Parent.get(), Child.get()))
468 if (Child->ParentSegment == nullptr ||
469 compareSegmentsByOffset(Parent.get(), Child->ParentSegment)) {
470 Child->ParentSegment = Parent.get();
Jake Ehrlichd246b0a2017-09-19 21:37:35 +0000471 }
Jake Ehrlichd246b0a2017-09-19 21:37:35 +0000472 }
473 }
474 }
Petr Hosek05a04cb2017-08-01 00:33:58 +0000475}
476
477template <class ELFT>
Aaron Ballman09f46a72018-01-25 21:03:38 +0000478void Object<ELFT>::initSymbolTable(const object::ELFFile<ELFT> &ElfFile,
479 SymbolTableSection *SymTab,
480 SectionTableRef SecTable) {
Petr Hosek79cee9e2017-08-29 02:12:03 +0000481 const Elf_Shdr &Shdr = *unwrapOrError(ElfFile.getSection(SymTab->Index));
482 StringRef StrTabData = unwrapOrError(ElfFile.getStringTableForSymtab(Shdr));
483
484 for (const auto &Sym : unwrapOrError(ElfFile.symbols(&Shdr))) {
485 SectionBase *DefSection = nullptr;
486 StringRef Name = unwrapOrError(Sym.getName(StrTabData));
Jake Ehrliche5d424b2017-09-20 17:11:58 +0000487
Petr Hosekec2b3fc2017-09-07 23:02:50 +0000488 if (Sym.st_shndx >= SHN_LORESERVE) {
Aaron Ballman09f46a72018-01-25 21:03:38 +0000489 if (!isValidReservedSectionIndex(Sym.st_shndx, Machine)) {
Petr Hosekec2b3fc2017-09-07 23:02:50 +0000490 error(
491 "Symbol '" + Name +
492 "' has unsupported value greater than or equal to SHN_LORESERVE: " +
493 Twine(Sym.st_shndx));
494 }
495 } else if (Sym.st_shndx != SHN_UNDEF) {
Aaron Ballman09f46a72018-01-25 21:03:38 +0000496 DefSection = SecTable.getSection(
Jake Ehrlich777fb002017-12-15 20:17:55 +0000497 Sym.st_shndx,
498 "Symbol '" + Name + "' is defined in invalid section with index " +
499 Twine(Sym.st_shndx));
Petr Hosek79cee9e2017-08-29 02:12:03 +0000500 }
Jake Ehrliche5d424b2017-09-20 17:11:58 +0000501
Petr Hosek79cee9e2017-08-29 02:12:03 +0000502 SymTab->addSymbol(Name, Sym.getBinding(), Sym.getType(), DefSection,
Jake Ehrlich30d927a2018-01-02 23:01:24 +0000503 Sym.getValue(), Sym.st_other, Sym.st_shndx, Sym.st_size);
Petr Hosek79cee9e2017-08-29 02:12:03 +0000504 }
505}
506
507template <class ELFT>
Petr Hosekd7df9b22017-09-06 23:41:02 +0000508static void getAddend(uint64_t &ToSet, const Elf_Rel_Impl<ELFT, false> &Rel) {}
509
510template <class ELFT>
511static void getAddend(uint64_t &ToSet, const Elf_Rel_Impl<ELFT, true> &Rela) {
512 ToSet = Rela.r_addend;
513}
514
Aaron Ballman09f46a72018-01-25 21:03:38 +0000515template <class ELFT, class T>
516void initRelocations(RelocationSection<ELFT> *Relocs,
517 SymbolTableSection *SymbolTable, T RelRange) {
Petr Hosekd7df9b22017-09-06 23:41:02 +0000518 for (const auto &Rel : RelRange) {
519 Relocation ToAdd;
520 ToAdd.Offset = Rel.r_offset;
521 getAddend(ToAdd.Addend, Rel);
522 ToAdd.Type = Rel.getType(false);
523 ToAdd.RelocSymbol = SymbolTable->getSymbolByIndex(Rel.getSymbol(false));
524 Relocs->addRelocation(ToAdd);
525 }
526}
527
Zachary Turner41a9ee92017-10-11 23:54:34 +0000528SectionBase *SectionTableRef::getSection(uint16_t Index, Twine ErrMsg) {
Jake Ehrlichf5a43772017-09-25 20:37:28 +0000529 if (Index == SHN_UNDEF || Index > Sections.size())
530 error(ErrMsg);
531 return Sections[Index - 1].get();
532}
533
534template <class T>
Zachary Turner41a9ee92017-10-11 23:54:34 +0000535T *SectionTableRef::getSectionOfType(uint16_t Index, Twine IndexErrMsg,
536 Twine TypeErrMsg) {
Eugene Zelenko0ad18f82017-11-01 21:16:06 +0000537 if (T *Sec = dyn_cast<T>(getSection(Index, IndexErrMsg)))
Jake Ehrlichf5a43772017-09-25 20:37:28 +0000538 return Sec;
539 error(TypeErrMsg);
540}
541
Petr Hosekd7df9b22017-09-06 23:41:02 +0000542template <class ELFT>
Aaron Ballman09f46a72018-01-25 21:03:38 +0000543std::unique_ptr<SectionBase>
544Object<ELFT>::makeSection(const object::ELFFile<ELFT> &ElfFile,
545 const Elf_Shdr &Shdr) {
Petr Hosek05a04cb2017-08-01 00:33:58 +0000546 ArrayRef<uint8_t> Data;
547 switch (Shdr.sh_type) {
Petr Hosekd7df9b22017-09-06 23:41:02 +0000548 case SHT_REL:
549 case SHT_RELA:
Jake Ehrlich9f1a3902017-09-26 18:02:25 +0000550 if (Shdr.sh_flags & SHF_ALLOC) {
551 Data = unwrapOrError(ElfFile.getSectionContents(&Shdr));
Aaron Ballman09f46a72018-01-25 21:03:38 +0000552 return llvm::make_unique<DynamicRelocationSection>(Data);
Jake Ehrlich9f1a3902017-09-26 18:02:25 +0000553 }
Aaron Ballman09f46a72018-01-25 21:03:38 +0000554 return llvm::make_unique<RelocationSection<ELFT>>();
Petr Hosek05a04cb2017-08-01 00:33:58 +0000555 case SHT_STRTAB:
Jake Ehrliche5d424b2017-09-20 17:11:58 +0000556 // If a string table is allocated we don't want to mess with it. That would
557 // mean altering the memory image. There are no special link types or
558 // anything so we can just use a Section.
559 if (Shdr.sh_flags & SHF_ALLOC) {
560 Data = unwrapOrError(ElfFile.getSectionContents(&Shdr));
Aaron Ballman09f46a72018-01-25 21:03:38 +0000561 return llvm::make_unique<Section>(Data);
Jake Ehrliche5d424b2017-09-20 17:11:58 +0000562 }
Aaron Ballman09f46a72018-01-25 21:03:38 +0000563 return llvm::make_unique<StringTableSection>();
Jake Ehrliche5d424b2017-09-20 17:11:58 +0000564 case SHT_HASH:
565 case SHT_GNU_HASH:
566 // Hash tables should refer to SHT_DYNSYM which we're not going to change.
567 // Because of this we don't need to mess with the hash tables either.
568 Data = unwrapOrError(ElfFile.getSectionContents(&Shdr));
Aaron Ballman09f46a72018-01-25 21:03:38 +0000569 return llvm::make_unique<Section>(Data);
Jake Ehrliche5d424b2017-09-20 17:11:58 +0000570 case SHT_DYNSYM:
571 Data = unwrapOrError(ElfFile.getSectionContents(&Shdr));
Aaron Ballman09f46a72018-01-25 21:03:38 +0000572 return llvm::make_unique<DynamicSymbolTableSection>(Data);
Jake Ehrliche5d424b2017-09-20 17:11:58 +0000573 case SHT_DYNAMIC:
574 Data = unwrapOrError(ElfFile.getSectionContents(&Shdr));
Aaron Ballman09f46a72018-01-25 21:03:38 +0000575 return llvm::make_unique<DynamicSection>(Data);
Petr Hosek79cee9e2017-08-29 02:12:03 +0000576 case SHT_SYMTAB: {
Aaron Ballman09f46a72018-01-25 21:03:38 +0000577 auto SymTab = llvm::make_unique<SymbolTableSectionImpl<ELFT>>();
578 SymbolTable = SymTab.get();
579 return std::move(SymTab);
Petr Hosek79cee9e2017-08-29 02:12:03 +0000580 }
Petr Hosek05a04cb2017-08-01 00:33:58 +0000581 case SHT_NOBITS:
Aaron Ballman09f46a72018-01-25 21:03:38 +0000582 return llvm::make_unique<Section>(Data);
Petr Hosek05a04cb2017-08-01 00:33:58 +0000583 default:
584 Data = unwrapOrError(ElfFile.getSectionContents(&Shdr));
Aaron Ballman09f46a72018-01-25 21:03:38 +0000585 return llvm::make_unique<Section>(Data);
Petr Hosekc4df10e2017-08-04 21:09:26 +0000586 }
Petr Hosek05a04cb2017-08-01 00:33:58 +0000587}
588
Aaron Ballman09f46a72018-01-25 21:03:38 +0000589template <class ELFT>
590SectionTableRef Object<ELFT>::readSectionHeaders(const ELFFile<ELFT> &ElfFile) {
Petr Hosek05a04cb2017-08-01 00:33:58 +0000591 uint32_t Index = 0;
592 for (const auto &Shdr : unwrapOrError(ElfFile.sections())) {
593 if (Index == 0) {
594 ++Index;
595 continue;
596 }
Aaron Ballman09f46a72018-01-25 21:03:38 +0000597 SecPtr Sec = makeSection(ElfFile, Shdr);
598 Sec->Name = unwrapOrError(ElfFile.getSectionName(&Shdr));
599 Sec->Type = Shdr.sh_type;
600 Sec->Flags = Shdr.sh_flags;
601 Sec->Addr = Shdr.sh_addr;
602 Sec->Offset = Shdr.sh_offset;
603 Sec->OriginalOffset = Shdr.sh_offset;
604 Sec->Size = Shdr.sh_size;
605 Sec->Link = Shdr.sh_link;
606 Sec->Info = Shdr.sh_info;
607 Sec->Align = Shdr.sh_addralign;
608 Sec->EntrySize = Shdr.sh_entsize;
609 Sec->Index = Index++;
610 Sections.push_back(std::move(Sec));
Petr Hosek05a04cb2017-08-01 00:33:58 +0000611 }
Petr Hosek79cee9e2017-08-29 02:12:03 +0000612
Aaron Ballman09f46a72018-01-25 21:03:38 +0000613 SectionTableRef SecTable(Sections);
614
Petr Hosek79cee9e2017-08-29 02:12:03 +0000615 // Now that all of the sections have been added we can fill out some extra
Jake Ehrlichf5a43772017-09-25 20:37:28 +0000616 // details about symbol tables. We need the symbol table filled out before
617 // any relocations.
Aaron Ballman09f46a72018-01-25 21:03:38 +0000618 if (SymbolTable) {
619 SymbolTable->initialize(SecTable);
620 initSymbolTable(ElfFile, SymbolTable, SecTable);
Jake Ehrlichf5a43772017-09-25 20:37:28 +0000621 }
Petr Hosekd7df9b22017-09-06 23:41:02 +0000622
623 // Now that all sections and symbols have been added we can add
624 // relocations that reference symbols and set the link and info fields for
625 // relocation sections.
Aaron Ballman09f46a72018-01-25 21:03:38 +0000626 for (auto &Section : Sections) {
627 if (Section.get() == SymbolTable)
Jake Ehrlichf5a43772017-09-25 20:37:28 +0000628 continue;
Aaron Ballman09f46a72018-01-25 21:03:38 +0000629 Section->initialize(SecTable);
630 if (auto RelSec = dyn_cast<RelocationSection<ELFT>>(Section.get())) {
Petr Hosekd7df9b22017-09-06 23:41:02 +0000631 auto Shdr = unwrapOrError(ElfFile.sections()).begin() + RelSec->Index;
632 if (RelSec->Type == SHT_REL)
Aaron Ballman09f46a72018-01-25 21:03:38 +0000633 initRelocations(RelSec, SymbolTable, unwrapOrError(ElfFile.rels(Shdr)));
Petr Hosekd7df9b22017-09-06 23:41:02 +0000634 else
Aaron Ballman09f46a72018-01-25 21:03:38 +0000635 initRelocations(RelSec, SymbolTable,
Jake Ehrlichf5a43772017-09-25 20:37:28 +0000636 unwrapOrError(ElfFile.relas(Shdr)));
Petr Hosekd7df9b22017-09-06 23:41:02 +0000637 }
638 }
Aaron Ballman09f46a72018-01-25 21:03:38 +0000639
640 return SecTable;
Petr Hosek05a04cb2017-08-01 00:33:58 +0000641}
642
Aaron Ballman09f46a72018-01-25 21:03:38 +0000643template <class ELFT> Object<ELFT>::Object(const ELFObjectFile<ELFT> &Obj) {
644 const auto &ElfFile = *Obj.getELFFile();
Petr Hosek05a04cb2017-08-01 00:33:58 +0000645 const auto &Ehdr = *ElfFile.getHeader();
646
Aaron Ballman09f46a72018-01-25 21:03:38 +0000647 std::copy(Ehdr.e_ident, Ehdr.e_ident + 16, Ident);
648 Type = Ehdr.e_type;
649 Machine = Ehdr.e_machine;
650 Version = Ehdr.e_version;
651 Entry = Ehdr.e_entry;
652 Flags = Ehdr.e_flags;
Petr Hosek05a04cb2017-08-01 00:33:58 +0000653
Aaron Ballman09f46a72018-01-25 21:03:38 +0000654 SectionTableRef SecTable = readSectionHeaders(ElfFile);
655 readProgramHeaders(ElfFile);
Petr Hosek05a04cb2017-08-01 00:33:58 +0000656
Aaron Ballman09f46a72018-01-25 21:03:38 +0000657 SectionNames = SecTable.getSectionOfType<StringTableSection>(
658 Ehdr.e_shstrndx,
659 "e_shstrndx field value " + Twine(Ehdr.e_shstrndx) + " in elf header " +
660 " is invalid",
661 "e_shstrndx field value " + Twine(Ehdr.e_shstrndx) + " in elf header " +
662 " is not a string table");
Petr Hosek05a04cb2017-08-01 00:33:58 +0000663}
664
Aaron Ballman09f46a72018-01-25 21:03:38 +0000665template <class ELFT>
666void Object<ELFT>::writeHeader(FileOutputBuffer &Out) const {
667 uint8_t *Buf = Out.getBufferStart();
Petr Hosek05a04cb2017-08-01 00:33:58 +0000668 Elf_Ehdr &Ehdr = *reinterpret_cast<Elf_Ehdr *>(Buf);
Aaron Ballman09f46a72018-01-25 21:03:38 +0000669 std::copy(Ident, Ident + 16, Ehdr.e_ident);
670 Ehdr.e_type = Type;
671 Ehdr.e_machine = Machine;
672 Ehdr.e_version = Version;
673 Ehdr.e_entry = Entry;
Petr Hosek05a04cb2017-08-01 00:33:58 +0000674 Ehdr.e_phoff = sizeof(Elf_Ehdr);
Aaron Ballman09f46a72018-01-25 21:03:38 +0000675 Ehdr.e_flags = Flags;
Petr Hosek05a04cb2017-08-01 00:33:58 +0000676 Ehdr.e_ehsize = sizeof(Elf_Ehdr);
677 Ehdr.e_phentsize = sizeof(Elf_Phdr);
Aaron Ballman09f46a72018-01-25 21:03:38 +0000678 Ehdr.e_phnum = Segments.size();
Petr Hosek05a04cb2017-08-01 00:33:58 +0000679 Ehdr.e_shentsize = sizeof(Elf_Shdr);
Jake Ehrlichf03384d2017-10-11 18:09:18 +0000680 if (WriteSectionHeaders) {
Aaron Ballman09f46a72018-01-25 21:03:38 +0000681 Ehdr.e_shoff = SHOffset;
682 Ehdr.e_shnum = Sections.size() + 1;
683 Ehdr.e_shstrndx = SectionNames->Index;
Jake Ehrlichf03384d2017-10-11 18:09:18 +0000684 } else {
685 Ehdr.e_shoff = 0;
686 Ehdr.e_shnum = 0;
687 Ehdr.e_shstrndx = 0;
688 }
Petr Hosek05a04cb2017-08-01 00:33:58 +0000689}
690
Aaron Ballman09f46a72018-01-25 21:03:38 +0000691template <class ELFT>
692void Object<ELFT>::writeProgramHeaders(FileOutputBuffer &Out) const {
693 for (auto &Phdr : Segments)
694 Phdr->template writeHeader<ELFT>(Out);
Petr Hosek05a04cb2017-08-01 00:33:58 +0000695}
696
Aaron Ballman09f46a72018-01-25 21:03:38 +0000697template <class ELFT>
698void Object<ELFT>::writeSectionHeaders(FileOutputBuffer &Out) const {
699 uint8_t *Buf = Out.getBufferStart() + SHOffset;
Petr Hosek05a04cb2017-08-01 00:33:58 +0000700 // This reference serves to write the dummy section header at the begining
Jake Ehrlich425ec9f2017-09-15 22:04:09 +0000701 // of the file. It is not used for anything else
Petr Hosek05a04cb2017-08-01 00:33:58 +0000702 Elf_Shdr &Shdr = *reinterpret_cast<Elf_Shdr *>(Buf);
703 Shdr.sh_name = 0;
704 Shdr.sh_type = SHT_NULL;
705 Shdr.sh_flags = 0;
706 Shdr.sh_addr = 0;
707 Shdr.sh_offset = 0;
708 Shdr.sh_size = 0;
709 Shdr.sh_link = 0;
710 Shdr.sh_info = 0;
711 Shdr.sh_addralign = 0;
712 Shdr.sh_entsize = 0;
713
Aaron Ballman09f46a72018-01-25 21:03:38 +0000714 for (auto &Section : Sections)
715 Section->template writeHeader<ELFT>(Out);
Petr Hosek05a04cb2017-08-01 00:33:58 +0000716}
717
Aaron Ballman09f46a72018-01-25 21:03:38 +0000718template <class ELFT>
719void Object<ELFT>::writeSectionData(FileOutputBuffer &Out) const {
720 for (auto &Section : Sections)
721 Section->writeSection(Out);
Petr Hosek05a04cb2017-08-01 00:33:58 +0000722}
723
Aaron Ballman09f46a72018-01-25 21:03:38 +0000724template <class ELFT>
725void Object<ELFT>::removeSections(
726 std::function<bool(const SectionBase &)> ToRemove) {
Jake Ehrlich36a2eb32017-10-10 18:47:09 +0000727
728 auto Iter = std::stable_partition(
729 std::begin(Sections), std::end(Sections), [=](const SecPtr &Sec) {
730 if (ToRemove(*Sec))
731 return false;
Jake Ehrlichf03384d2017-10-11 18:09:18 +0000732 if (auto RelSec = dyn_cast<RelocationSectionBase>(Sec.get())) {
733 if (auto ToRelSec = RelSec->getSection())
734 return !ToRemove(*ToRelSec);
735 }
Jake Ehrlich36a2eb32017-10-10 18:47:09 +0000736 return true;
737 });
738 if (SymbolTable != nullptr && ToRemove(*SymbolTable))
739 SymbolTable = nullptr;
Aaron Ballman09f46a72018-01-25 21:03:38 +0000740 if (ToRemove(*SectionNames)) {
741 if (WriteSectionHeaders)
742 error("Cannot remove " + SectionNames->Name +
743 " because it is the section header string table.");
Jake Ehrlichf03384d2017-10-11 18:09:18 +0000744 SectionNames = nullptr;
Jake Ehrlich36a2eb32017-10-10 18:47:09 +0000745 }
746 // Now make sure there are no remaining references to the sections that will
747 // be removed. Sometimes it is impossible to remove a reference so we emit
748 // an error here instead.
749 for (auto &RemoveSec : make_range(Iter, std::end(Sections))) {
750 for (auto &Segment : Segments)
751 Segment->removeSection(RemoveSec.get());
752 for (auto &KeepSec : make_range(std::begin(Sections), Iter))
753 KeepSec->removeSectionReferences(RemoveSec.get());
754 }
755 // Now finally get rid of them all togethor.
756 Sections.erase(Iter, std::end(Sections));
757}
758
Aaron Ballman09f46a72018-01-25 21:03:38 +0000759template <class ELFT>
760void Object<ELFT>::addSection(StringRef SecName, ArrayRef<uint8_t> Data) {
761 auto Sec = llvm::make_unique<OwnedDataSection>(SecName, Data);
762 Sec->OriginalOffset = ~0ULL;
763 Sections.push_back(std::move(Sec));
764}
765
Jake Ehrlichea07d3c2018-01-25 22:15:14 +0000766template <class ELFT> void Object<ELFT>::addGnuDebugLink(StringRef File) {
767 Sections.emplace_back(llvm::make_unique<GnuDebugLinkSection<ELFT>>(File));
768}
769
Aaron Ballman09f46a72018-01-25 21:03:38 +0000770template <class ELFT> void ELFObject<ELFT>::sortSections() {
Petr Hosekc4df10e2017-08-04 21:09:26 +0000771 // Put all sections in offset order. Maintain the ordering as closely as
772 // possible while meeting that demand however.
773 auto CompareSections = [](const SecPtr &A, const SecPtr &B) {
774 return A->OriginalOffset < B->OriginalOffset;
775 };
776 std::stable_sort(std::begin(this->Sections), std::end(this->Sections),
777 CompareSections);
778}
779
Jake Ehrlich13153ee2017-11-02 23:24:04 +0000780static uint64_t alignToAddr(uint64_t Offset, uint64_t Addr, uint64_t Align) {
781 // Calculate Diff such that (Offset + Diff) & -Align == Addr & -Align.
782 if (Align == 0)
783 Align = 1;
784 auto Diff =
785 static_cast<int64_t>(Addr % Align) - static_cast<int64_t>(Offset % Align);
786 // We only want to add to Offset, however, so if Diff < 0 we can add Align and
787 // (Offset + Diff) & -Align == Addr & -Align will still hold.
788 if (Diff < 0)
789 Diff += Align;
790 return Offset + Diff;
791}
792
Jake Ehrlichd49c92b2017-11-15 19:13:31 +0000793// Orders segments such that if x = y->ParentSegment then y comes before x.
794static void OrderSegments(std::vector<Segment *> &Segments) {
Jake Ehrlich46814be2018-01-22 19:27:30 +0000795 std::stable_sort(std::begin(Segments), std::end(Segments),
796 compareSegmentsByOffset);
Jake Ehrlichd49c92b2017-11-15 19:13:31 +0000797}
798
799// This function finds a consistent layout for a list of segments starting from
800// an Offset. It assumes that Segments have been sorted by OrderSegments and
801// returns an Offset one past the end of the last segment.
802static uint64_t LayoutSegments(std::vector<Segment *> &Segments,
803 uint64_t Offset) {
804 assert(std::is_sorted(std::begin(Segments), std::end(Segments),
Jake Ehrlich46814be2018-01-22 19:27:30 +0000805 compareSegmentsByOffset));
Petr Hosek3f383832017-08-26 01:32:20 +0000806 // The only way a segment should move is if a section was between two
807 // segments and that section was removed. If that section isn't in a segment
808 // then it's acceptable, but not ideal, to simply move it to after the
809 // segments. So we can simply layout segments one after the other accounting
810 // for alignment.
Jake Ehrlichd49c92b2017-11-15 19:13:31 +0000811 for (auto &Segment : Segments) {
Jake Ehrlichd246b0a2017-09-19 21:37:35 +0000812 // We assume that segments have been ordered by OriginalOffset and Index
813 // such that a parent segment will always come before a child segment in
814 // OrderedSegments. This means that the Offset of the ParentSegment should
815 // already be set and we can set our offset relative to it.
816 if (Segment->ParentSegment != nullptr) {
817 auto Parent = Segment->ParentSegment;
818 Segment->Offset =
819 Parent->Offset + Segment->OriginalOffset - Parent->OriginalOffset;
820 } else {
Jake Ehrlich13153ee2017-11-02 23:24:04 +0000821 Offset = alignToAddr(Offset, Segment->VAddr, Segment->Align);
Jake Ehrlichd246b0a2017-09-19 21:37:35 +0000822 Segment->Offset = Offset;
Jake Ehrlichd246b0a2017-09-19 21:37:35 +0000823 }
Jake Ehrlich084400b2017-10-04 17:44:42 +0000824 Offset = std::max(Offset, Segment->Offset + Segment->FileSize);
Petr Hosek3f383832017-08-26 01:32:20 +0000825 }
Jake Ehrlichd49c92b2017-11-15 19:13:31 +0000826 return Offset;
827}
828
829// This function finds a consistent layout for a list of sections. It assumes
830// that the ->ParentSegment of each section has already been laid out. The
831// supplied starting Offset is used for the starting offset of any section that
832// does not have a ParentSegment. It returns either the offset given if all
833// sections had a ParentSegment or an offset one past the last section if there
834// was a section that didn't have a ParentSegment.
Aaron Ballman09f46a72018-01-25 21:03:38 +0000835template <class SecPtr>
836static uint64_t LayoutSections(std::vector<SecPtr> &Sections, uint64_t Offset) {
Petr Hosek3f383832017-08-26 01:32:20 +0000837 // Now the offset of every segment has been set we can assign the offsets
838 // of each section. For sections that are covered by a segment we should use
839 // the segment's original offset and the section's original offset to compute
840 // the offset from the start of the segment. Using the offset from the start
841 // of the segment we can assign a new offset to the section. For sections not
842 // covered by segments we can just bump Offset to the next valid location.
843 uint32_t Index = 1;
Jake Ehrlichd49c92b2017-11-15 19:13:31 +0000844 for (auto &Section : Sections) {
Aaron Ballman09f46a72018-01-25 21:03:38 +0000845 Section->Index = Index++;
846 if (Section->ParentSegment != nullptr) {
847 auto Segment = Section->ParentSegment;
848 Section->Offset =
849 Segment->Offset + (Section->OriginalOffset - Segment->OriginalOffset);
Petr Hosek3f383832017-08-26 01:32:20 +0000850 } else {
Aaron Ballman09f46a72018-01-25 21:03:38 +0000851 Offset = alignTo(Offset, Section->Align == 0 ? 1 : Section->Align);
852 Section->Offset = Offset;
853 if (Section->Type != SHT_NOBITS)
854 Offset += Section->Size;
Petr Hosek3f383832017-08-26 01:32:20 +0000855 }
856 }
Jake Ehrlichd49c92b2017-11-15 19:13:31 +0000857 return Offset;
858}
Petr Hosek3f383832017-08-26 01:32:20 +0000859
Aaron Ballman09f46a72018-01-25 21:03:38 +0000860template <class ELFT> void ELFObject<ELFT>::assignOffsets() {
Jake Ehrlichd49c92b2017-11-15 19:13:31 +0000861 // We need a temporary list of segments that has a special order to it
862 // so that we know that anytime ->ParentSegment is set that segment has
863 // already had its offset properly set.
864 std::vector<Segment *> OrderedSegments;
Aaron Ballman09f46a72018-01-25 21:03:38 +0000865 for (auto &Segment : this->Segments)
866 OrderedSegments.push_back(Segment.get());
Jake Ehrlichd49c92b2017-11-15 19:13:31 +0000867 OrderSegments(OrderedSegments);
868 // The size of ELF + program headers will not change so it is ok to assume
869 // that the first offset of the first segment is a good place to start
870 // outputting sections. This covers both the standard case and the PT_PHDR
871 // case.
872 uint64_t Offset;
873 if (!OrderedSegments.empty()) {
874 Offset = OrderedSegments[0]->Offset;
875 } else {
876 Offset = sizeof(Elf_Ehdr);
Jake Ehrlichf03384d2017-10-11 18:09:18 +0000877 }
Jake Ehrlichd49c92b2017-11-15 19:13:31 +0000878 Offset = LayoutSegments(OrderedSegments, Offset);
Aaron Ballman09f46a72018-01-25 21:03:38 +0000879 Offset = LayoutSections(this->Sections, Offset);
Jake Ehrlichd49c92b2017-11-15 19:13:31 +0000880 // If we need to write the section header table out then we need to align the
881 // Offset so that SHOffset is valid.
Aaron Ballman09f46a72018-01-25 21:03:38 +0000882 if (this->WriteSectionHeaders)
Jake Ehrlichd49c92b2017-11-15 19:13:31 +0000883 Offset = alignTo(Offset, sizeof(typename ELFT::Addr));
Aaron Ballman09f46a72018-01-25 21:03:38 +0000884 this->SHOffset = Offset;
Petr Hosekc4df10e2017-08-04 21:09:26 +0000885}
886
Aaron Ballman09f46a72018-01-25 21:03:38 +0000887template <class ELFT> size_t ELFObject<ELFT>::totalSize() const {
Petr Hosekc4df10e2017-08-04 21:09:26 +0000888 // We already have the section header offset so we can calculate the total
889 // size by just adding up the size of each section header.
Aaron Ballman09f46a72018-01-25 21:03:38 +0000890 auto NullSectionSize = this->WriteSectionHeaders ? sizeof(Elf_Shdr) : 0;
891 return this->SHOffset + this->Sections.size() * sizeof(Elf_Shdr) +
Jake Ehrlichf03384d2017-10-11 18:09:18 +0000892 NullSectionSize;
Petr Hosekc4df10e2017-08-04 21:09:26 +0000893}
894
Aaron Ballman09f46a72018-01-25 21:03:38 +0000895template <class ELFT> void ELFObject<ELFT>::write(FileOutputBuffer &Out) const {
896 this->writeHeader(Out);
897 this->writeProgramHeaders(Out);
898 this->writeSectionData(Out);
899 if (this->WriteSectionHeaders)
900 this->writeSectionHeaders(Out);
Petr Hosekc4df10e2017-08-04 21:09:26 +0000901}
902
Aaron Ballman09f46a72018-01-25 21:03:38 +0000903template <class ELFT> void ELFObject<ELFT>::finalize() {
Petr Hosek79cee9e2017-08-29 02:12:03 +0000904 // Make sure we add the names of all the sections.
Aaron Ballman09f46a72018-01-25 21:03:38 +0000905 if (this->SectionNames != nullptr)
906 for (const auto &Section : this->Sections) {
907 this->SectionNames->addString(Section->Name);
Jake Ehrlichf03384d2017-10-11 18:09:18 +0000908 }
Petr Hosek79cee9e2017-08-29 02:12:03 +0000909 // Make sure we add the names of all the symbols.
Aaron Ballman09f46a72018-01-25 21:03:38 +0000910 if (this->SymbolTable != nullptr)
911 this->SymbolTable->addSymbolNames();
Petr Hosekc4df10e2017-08-04 21:09:26 +0000912
Aaron Ballman09f46a72018-01-25 21:03:38 +0000913 sortSections();
Petr Hosekc4df10e2017-08-04 21:09:26 +0000914 assignOffsets();
915
916 // Finalize SectionNames first so that we can assign name indexes.
Aaron Ballman09f46a72018-01-25 21:03:38 +0000917 if (this->SectionNames != nullptr)
918 this->SectionNames->finalize();
Petr Hosekc4df10e2017-08-04 21:09:26 +0000919 // Finally now that all offsets and indexes have been set we can finalize any
920 // remaining issues.
Aaron Ballman09f46a72018-01-25 21:03:38 +0000921 uint64_t Offset = this->SHOffset + sizeof(Elf_Shdr);
922 for (auto &Section : this->Sections) {
923 Section->HeaderOffset = Offset;
Petr Hosekc4df10e2017-08-04 21:09:26 +0000924 Offset += sizeof(Elf_Shdr);
Aaron Ballman09f46a72018-01-25 21:03:38 +0000925 if (this->WriteSectionHeaders)
926 Section->NameIndex = this->SectionNames->findIndex(Section->Name);
927 Section->finalize();
Petr Hosekc4df10e2017-08-04 21:09:26 +0000928 }
Petr Hosekc4df10e2017-08-04 21:09:26 +0000929}
930
Aaron Ballman09f46a72018-01-25 21:03:38 +0000931template <class ELFT> size_t BinaryObject<ELFT>::totalSize() const {
932 return TotalSize;
933}
934
935template <class ELFT>
936void BinaryObject<ELFT>::write(FileOutputBuffer &Out) const {
937 for (auto &Section : this->Sections) {
938 if ((Section->Flags & SHF_ALLOC) == 0)
Jake Ehrlichd49c92b2017-11-15 19:13:31 +0000939 continue;
Aaron Ballman09f46a72018-01-25 21:03:38 +0000940 Section->writeSection(Out);
Petr Hosekc4df10e2017-08-04 21:09:26 +0000941 }
942}
943
Aaron Ballman09f46a72018-01-25 21:03:38 +0000944template <class ELFT> void BinaryObject<ELFT>::finalize() {
Jake Ehrlichd49c92b2017-11-15 19:13:31 +0000945 // TODO: Create a filter range to construct OrderedSegments from so that this
946 // code can be deduped with assignOffsets above. This should also solve the
947 // todo below for LayoutSections.
948 // We need a temporary list of segments that has a special order to it
949 // so that we know that anytime ->ParentSegment is set that segment has
950 // already had it's offset properly set. We only want to consider the segments
951 // that will affect layout of allocated sections so we only add those.
952 std::vector<Segment *> OrderedSegments;
Aaron Ballman09f46a72018-01-25 21:03:38 +0000953 for (auto &Section : this->Sections) {
954 if ((Section->Flags & SHF_ALLOC) != 0 &&
955 Section->ParentSegment != nullptr) {
956 OrderedSegments.push_back(Section->ParentSegment);
Petr Hosekc4df10e2017-08-04 21:09:26 +0000957 }
958 }
Jake Ehrlich46814be2018-01-22 19:27:30 +0000959
960 // For binary output, we're going to use physical addresses instead of
961 // virtual addresses, since a binary output is used for cases like ROM
962 // loading and physical addresses are intended for ROM loading.
963 // However, if no segment has a physical address, we'll fallback to using
964 // virtual addresses for all.
965 if (std::all_of(std::begin(OrderedSegments), std::end(OrderedSegments),
966 [](const Segment *Segment) { return Segment->PAddr == 0; }))
967 for (const auto &Segment : OrderedSegments)
968 Segment->PAddr = Segment->VAddr;
969
970 std::stable_sort(std::begin(OrderedSegments), std::end(OrderedSegments),
971 compareSegmentsByPAddr);
972
Jake Ehrlichd49c92b2017-11-15 19:13:31 +0000973 // Because we add a ParentSegment for each section we might have duplicate
974 // segments in OrderedSegments. If there were duplicates then LayoutSegments
975 // would do very strange things.
976 auto End =
977 std::unique(std::begin(OrderedSegments), std::end(OrderedSegments));
978 OrderedSegments.erase(End, std::end(OrderedSegments));
979
Jake Ehrlich46814be2018-01-22 19:27:30 +0000980 uint64_t Offset = 0;
981
Jake Ehrlichd49c92b2017-11-15 19:13:31 +0000982 // Modify the first segment so that there is no gap at the start. This allows
983 // our layout algorithm to proceed as expected while not out writing out the
984 // gap at the start.
985 if (!OrderedSegments.empty()) {
986 auto Seg = OrderedSegments[0];
987 auto Sec = Seg->firstSection();
988 auto Diff = Sec->OriginalOffset - Seg->OriginalOffset;
989 Seg->OriginalOffset += Diff;
Jake Ehrlich46814be2018-01-22 19:27:30 +0000990 // The size needs to be shrunk as well.
Jake Ehrlichd49c92b2017-11-15 19:13:31 +0000991 Seg->FileSize -= Diff;
Jake Ehrlich46814be2018-01-22 19:27:30 +0000992 // The PAddr needs to be increased to remove the gap before the first
993 // section.
994 Seg->PAddr += Diff;
995 uint64_t LowestPAddr = Seg->PAddr;
996 for (auto &Segment : OrderedSegments) {
997 Segment->Offset = Segment->PAddr - LowestPAddr;
998 Offset = std::max(Offset, Segment->Offset + Segment->FileSize);
999 }
Jake Ehrlichd49c92b2017-11-15 19:13:31 +00001000 }
1001
Jake Ehrlichd49c92b2017-11-15 19:13:31 +00001002 // TODO: generalize LayoutSections to take a range. Pass a special range
1003 // constructed from an iterator that skips values for which a predicate does
1004 // not hold. Then pass such a range to LayoutSections instead of constructing
1005 // AllocatedSections here.
1006 std::vector<SectionBase *> AllocatedSections;
Aaron Ballman09f46a72018-01-25 21:03:38 +00001007 for (auto &Section : this->Sections) {
1008 if ((Section->Flags & SHF_ALLOC) == 0)
Jake Ehrlichd49c92b2017-11-15 19:13:31 +00001009 continue;
Aaron Ballman09f46a72018-01-25 21:03:38 +00001010 AllocatedSections.push_back(Section.get());
Jake Ehrlichd49c92b2017-11-15 19:13:31 +00001011 }
Aaron Ballman09f46a72018-01-25 21:03:38 +00001012 LayoutSections(AllocatedSections, Offset);
Jake Ehrlichd49c92b2017-11-15 19:13:31 +00001013
1014 // Now that every section has been laid out we just need to compute the total
1015 // file size. This might not be the same as the offset returned by
1016 // LayoutSections, because we want to truncate the last segment to the end of
1017 // its last section, to match GNU objcopy's behaviour.
1018 TotalSize = 0;
1019 for (const auto &Section : AllocatedSections) {
1020 if (Section->Type != SHT_NOBITS)
1021 TotalSize = std::max(TotalSize, Section->Offset + Section->Size);
1022 }
Petr Hosek05a04cb2017-08-01 00:33:58 +00001023}
1024
Eugene Zelenko0ad18f82017-11-01 21:16:06 +00001025namespace llvm {
1026
Aaron Ballman09f46a72018-01-25 21:03:38 +00001027template class Object<ELF64LE>;
1028template class Object<ELF64BE>;
1029template class Object<ELF32LE>;
1030template class Object<ELF32BE>;
Petr Hosekc4df10e2017-08-04 21:09:26 +00001031
Aaron Ballman09f46a72018-01-25 21:03:38 +00001032template class ELFObject<ELF64LE>;
1033template class ELFObject<ELF64BE>;
1034template class ELFObject<ELF32LE>;
1035template class ELFObject<ELF32BE>;
1036
1037template class BinaryObject<ELF64LE>;
1038template class BinaryObject<ELF64BE>;
1039template class BinaryObject<ELF32LE>;
1040template class BinaryObject<ELF32BE>;
Eugene Zelenko0ad18f82017-11-01 21:16:06 +00001041
1042} // end namespace llvm