xref: /freebsd-src/contrib/llvm-project/lld/MachO/SyntheticSections.cpp (revision 5ffd83dbcc34f10e07f6d3e968ae6365869615f4)
1*5ffd83dbSDimitry Andric //===- SyntheticSections.cpp ---------------------------------------------===//
2*5ffd83dbSDimitry Andric //
3*5ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*5ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*5ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*5ffd83dbSDimitry Andric //
7*5ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
8*5ffd83dbSDimitry Andric 
9*5ffd83dbSDimitry Andric #include "SyntheticSections.h"
10*5ffd83dbSDimitry Andric #include "Config.h"
11*5ffd83dbSDimitry Andric #include "ExportTrie.h"
12*5ffd83dbSDimitry Andric #include "InputFiles.h"
13*5ffd83dbSDimitry Andric #include "MachOStructs.h"
14*5ffd83dbSDimitry Andric #include "MergedOutputSection.h"
15*5ffd83dbSDimitry Andric #include "OutputSegment.h"
16*5ffd83dbSDimitry Andric #include "SymbolTable.h"
17*5ffd83dbSDimitry Andric #include "Symbols.h"
18*5ffd83dbSDimitry Andric #include "Writer.h"
19*5ffd83dbSDimitry Andric 
20*5ffd83dbSDimitry Andric #include "lld/Common/ErrorHandler.h"
21*5ffd83dbSDimitry Andric #include "lld/Common/Memory.h"
22*5ffd83dbSDimitry Andric #include "llvm/Support/EndianStream.h"
23*5ffd83dbSDimitry Andric #include "llvm/Support/LEB128.h"
24*5ffd83dbSDimitry Andric 
25*5ffd83dbSDimitry Andric using namespace llvm;
26*5ffd83dbSDimitry Andric using namespace llvm::support;
27*5ffd83dbSDimitry Andric using namespace llvm::support::endian;
28*5ffd83dbSDimitry Andric using namespace lld;
29*5ffd83dbSDimitry Andric using namespace lld::macho;
30*5ffd83dbSDimitry Andric 
31*5ffd83dbSDimitry Andric InStruct macho::in;
32*5ffd83dbSDimitry Andric std::vector<SyntheticSection *> macho::syntheticSections;
33*5ffd83dbSDimitry Andric 
34*5ffd83dbSDimitry Andric SyntheticSection::SyntheticSection(const char *segname, const char *name)
35*5ffd83dbSDimitry Andric     : OutputSection(SyntheticKind, name), segname(segname) {
36*5ffd83dbSDimitry Andric   syntheticSections.push_back(this);
37*5ffd83dbSDimitry Andric }
38*5ffd83dbSDimitry Andric 
39*5ffd83dbSDimitry Andric // dyld3's MachOLoaded::getSlide() assumes that the __TEXT segment starts
40*5ffd83dbSDimitry Andric // from the beginning of the file (i.e. the header).
41*5ffd83dbSDimitry Andric MachHeaderSection::MachHeaderSection()
42*5ffd83dbSDimitry Andric     : SyntheticSection(segment_names::text, section_names::header) {}
43*5ffd83dbSDimitry Andric 
44*5ffd83dbSDimitry Andric void MachHeaderSection::addLoadCommand(LoadCommand *lc) {
45*5ffd83dbSDimitry Andric   loadCommands.push_back(lc);
46*5ffd83dbSDimitry Andric   sizeOfCmds += lc->getSize();
47*5ffd83dbSDimitry Andric }
48*5ffd83dbSDimitry Andric 
49*5ffd83dbSDimitry Andric uint64_t MachHeaderSection::getSize() const {
50*5ffd83dbSDimitry Andric   return sizeof(MachO::mach_header_64) + sizeOfCmds;
51*5ffd83dbSDimitry Andric }
52*5ffd83dbSDimitry Andric 
53*5ffd83dbSDimitry Andric void MachHeaderSection::writeTo(uint8_t *buf) const {
54*5ffd83dbSDimitry Andric   auto *hdr = reinterpret_cast<MachO::mach_header_64 *>(buf);
55*5ffd83dbSDimitry Andric   hdr->magic = MachO::MH_MAGIC_64;
56*5ffd83dbSDimitry Andric   hdr->cputype = MachO::CPU_TYPE_X86_64;
57*5ffd83dbSDimitry Andric   hdr->cpusubtype = MachO::CPU_SUBTYPE_X86_64_ALL | MachO::CPU_SUBTYPE_LIB64;
58*5ffd83dbSDimitry Andric   hdr->filetype = config->outputType;
59*5ffd83dbSDimitry Andric   hdr->ncmds = loadCommands.size();
60*5ffd83dbSDimitry Andric   hdr->sizeofcmds = sizeOfCmds;
61*5ffd83dbSDimitry Andric   hdr->flags = MachO::MH_NOUNDEFS | MachO::MH_DYLDLINK | MachO::MH_TWOLEVEL;
62*5ffd83dbSDimitry Andric   if (config->outputType == MachO::MH_DYLIB && !config->hasReexports)
63*5ffd83dbSDimitry Andric     hdr->flags |= MachO::MH_NO_REEXPORTED_DYLIBS;
64*5ffd83dbSDimitry Andric 
65*5ffd83dbSDimitry Andric   uint8_t *p = reinterpret_cast<uint8_t *>(hdr + 1);
66*5ffd83dbSDimitry Andric   for (LoadCommand *lc : loadCommands) {
67*5ffd83dbSDimitry Andric     lc->writeTo(p);
68*5ffd83dbSDimitry Andric     p += lc->getSize();
69*5ffd83dbSDimitry Andric   }
70*5ffd83dbSDimitry Andric }
71*5ffd83dbSDimitry Andric 
72*5ffd83dbSDimitry Andric PageZeroSection::PageZeroSection()
73*5ffd83dbSDimitry Andric     : SyntheticSection(segment_names::pageZero, section_names::pageZero) {}
74*5ffd83dbSDimitry Andric 
75*5ffd83dbSDimitry Andric GotSection::GotSection()
76*5ffd83dbSDimitry Andric     : SyntheticSection(segment_names::dataConst, section_names::got) {
77*5ffd83dbSDimitry Andric   align = 8;
78*5ffd83dbSDimitry Andric   flags = MachO::S_NON_LAZY_SYMBOL_POINTERS;
79*5ffd83dbSDimitry Andric 
80*5ffd83dbSDimitry Andric   // TODO: section_64::reserved1 should be an index into the indirect symbol
81*5ffd83dbSDimitry Andric   // table, which we do not currently emit
82*5ffd83dbSDimitry Andric }
83*5ffd83dbSDimitry Andric 
84*5ffd83dbSDimitry Andric void GotSection::addEntry(Symbol &sym) {
85*5ffd83dbSDimitry Andric   if (entries.insert(&sym)) {
86*5ffd83dbSDimitry Andric     sym.gotIndex = entries.size() - 1;
87*5ffd83dbSDimitry Andric   }
88*5ffd83dbSDimitry Andric }
89*5ffd83dbSDimitry Andric 
90*5ffd83dbSDimitry Andric void GotSection::writeTo(uint8_t *buf) const {
91*5ffd83dbSDimitry Andric   for (size_t i = 0, n = entries.size(); i < n; ++i)
92*5ffd83dbSDimitry Andric     if (auto *defined = dyn_cast<Defined>(entries[i]))
93*5ffd83dbSDimitry Andric       write64le(&buf[i * WordSize], defined->getVA());
94*5ffd83dbSDimitry Andric }
95*5ffd83dbSDimitry Andric 
96*5ffd83dbSDimitry Andric BindingSection::BindingSection()
97*5ffd83dbSDimitry Andric     : SyntheticSection(segment_names::linkEdit, section_names::binding) {}
98*5ffd83dbSDimitry Andric 
99*5ffd83dbSDimitry Andric bool BindingSection::isNeeded() const {
100*5ffd83dbSDimitry Andric   return bindings.size() != 0 || in.got->isNeeded();
101*5ffd83dbSDimitry Andric }
102*5ffd83dbSDimitry Andric 
103*5ffd83dbSDimitry Andric namespace {
104*5ffd83dbSDimitry Andric struct Binding {
105*5ffd83dbSDimitry Andric   OutputSegment *segment = nullptr;
106*5ffd83dbSDimitry Andric   uint64_t offset = 0;
107*5ffd83dbSDimitry Andric   int64_t addend = 0;
108*5ffd83dbSDimitry Andric   uint8_t ordinal = 0;
109*5ffd83dbSDimitry Andric };
110*5ffd83dbSDimitry Andric } // namespace
111*5ffd83dbSDimitry Andric 
112*5ffd83dbSDimitry Andric // Encode a sequence of opcodes that tell dyld to write the address of dysym +
113*5ffd83dbSDimitry Andric // addend at osec->addr + outSecOff.
114*5ffd83dbSDimitry Andric //
115*5ffd83dbSDimitry Andric // The bind opcode "interpreter" remembers the values of each binding field, so
116*5ffd83dbSDimitry Andric // we only need to encode the differences between bindings. Hence the use of
117*5ffd83dbSDimitry Andric // lastBinding.
118*5ffd83dbSDimitry Andric static void encodeBinding(const DylibSymbol &dysym, const OutputSection *osec,
119*5ffd83dbSDimitry Andric                           uint64_t outSecOff, int64_t addend,
120*5ffd83dbSDimitry Andric                           Binding &lastBinding, raw_svector_ostream &os) {
121*5ffd83dbSDimitry Andric   using namespace llvm::MachO;
122*5ffd83dbSDimitry Andric   OutputSegment *seg = osec->parent;
123*5ffd83dbSDimitry Andric   uint64_t offset = osec->getSegmentOffset() + outSecOff;
124*5ffd83dbSDimitry Andric   if (lastBinding.segment != seg) {
125*5ffd83dbSDimitry Andric     os << static_cast<uint8_t>(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB |
126*5ffd83dbSDimitry Andric                                seg->index);
127*5ffd83dbSDimitry Andric     encodeULEB128(offset, os);
128*5ffd83dbSDimitry Andric     lastBinding.segment = seg;
129*5ffd83dbSDimitry Andric     lastBinding.offset = offset;
130*5ffd83dbSDimitry Andric   } else if (lastBinding.offset != offset) {
131*5ffd83dbSDimitry Andric     assert(lastBinding.offset <= offset);
132*5ffd83dbSDimitry Andric     os << static_cast<uint8_t>(BIND_OPCODE_ADD_ADDR_ULEB);
133*5ffd83dbSDimitry Andric     encodeULEB128(offset - lastBinding.offset, os);
134*5ffd83dbSDimitry Andric     lastBinding.offset = offset;
135*5ffd83dbSDimitry Andric   }
136*5ffd83dbSDimitry Andric 
137*5ffd83dbSDimitry Andric   if (lastBinding.ordinal != dysym.file->ordinal) {
138*5ffd83dbSDimitry Andric     if (dysym.file->ordinal <= BIND_IMMEDIATE_MASK) {
139*5ffd83dbSDimitry Andric       os << static_cast<uint8_t>(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM |
140*5ffd83dbSDimitry Andric                                  dysym.file->ordinal);
141*5ffd83dbSDimitry Andric     } else {
142*5ffd83dbSDimitry Andric       error("TODO: Support larger dylib symbol ordinals");
143*5ffd83dbSDimitry Andric       return;
144*5ffd83dbSDimitry Andric     }
145*5ffd83dbSDimitry Andric     lastBinding.ordinal = dysym.file->ordinal;
146*5ffd83dbSDimitry Andric   }
147*5ffd83dbSDimitry Andric 
148*5ffd83dbSDimitry Andric   if (lastBinding.addend != addend) {
149*5ffd83dbSDimitry Andric     os << static_cast<uint8_t>(BIND_OPCODE_SET_ADDEND_SLEB);
150*5ffd83dbSDimitry Andric     encodeSLEB128(addend, os);
151*5ffd83dbSDimitry Andric     lastBinding.addend = addend;
152*5ffd83dbSDimitry Andric   }
153*5ffd83dbSDimitry Andric 
154*5ffd83dbSDimitry Andric   os << static_cast<uint8_t>(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM)
155*5ffd83dbSDimitry Andric      << dysym.getName() << '\0'
156*5ffd83dbSDimitry Andric      << static_cast<uint8_t>(BIND_OPCODE_SET_TYPE_IMM | BIND_TYPE_POINTER)
157*5ffd83dbSDimitry Andric      << static_cast<uint8_t>(BIND_OPCODE_DO_BIND);
158*5ffd83dbSDimitry Andric   // DO_BIND causes dyld to both perform the binding and increment the offset
159*5ffd83dbSDimitry Andric   lastBinding.offset += WordSize;
160*5ffd83dbSDimitry Andric }
161*5ffd83dbSDimitry Andric 
162*5ffd83dbSDimitry Andric // Emit bind opcodes, which are a stream of byte-sized opcodes that dyld
163*5ffd83dbSDimitry Andric // interprets to update a record with the following fields:
164*5ffd83dbSDimitry Andric //  * segment index (of the segment to write the symbol addresses to, typically
165*5ffd83dbSDimitry Andric //    the __DATA_CONST segment which contains the GOT)
166*5ffd83dbSDimitry Andric //  * offset within the segment, indicating the next location to write a binding
167*5ffd83dbSDimitry Andric //  * symbol type
168*5ffd83dbSDimitry Andric //  * symbol library ordinal (the index of its library's LC_LOAD_DYLIB command)
169*5ffd83dbSDimitry Andric //  * symbol name
170*5ffd83dbSDimitry Andric //  * addend
171*5ffd83dbSDimitry Andric // When dyld sees BIND_OPCODE_DO_BIND, it uses the current record state to bind
172*5ffd83dbSDimitry Andric // a symbol in the GOT, and increments the segment offset to point to the next
173*5ffd83dbSDimitry Andric // entry. It does *not* clear the record state after doing the bind, so
174*5ffd83dbSDimitry Andric // subsequent opcodes only need to encode the differences between bindings.
175*5ffd83dbSDimitry Andric void BindingSection::finalizeContents() {
176*5ffd83dbSDimitry Andric   raw_svector_ostream os{contents};
177*5ffd83dbSDimitry Andric   Binding lastBinding;
178*5ffd83dbSDimitry Andric   bool didEncode = false;
179*5ffd83dbSDimitry Andric   size_t gotIdx = 0;
180*5ffd83dbSDimitry Andric   for (const Symbol *sym : in.got->getEntries()) {
181*5ffd83dbSDimitry Andric     if (const auto *dysym = dyn_cast<DylibSymbol>(sym)) {
182*5ffd83dbSDimitry Andric       didEncode = true;
183*5ffd83dbSDimitry Andric       encodeBinding(*dysym, in.got, gotIdx * WordSize, 0, lastBinding, os);
184*5ffd83dbSDimitry Andric     }
185*5ffd83dbSDimitry Andric     ++gotIdx;
186*5ffd83dbSDimitry Andric   }
187*5ffd83dbSDimitry Andric 
188*5ffd83dbSDimitry Andric   // Sorting the relocations by segment and address allows us to encode them
189*5ffd83dbSDimitry Andric   // more compactly.
190*5ffd83dbSDimitry Andric   llvm::sort(bindings, [](const BindingEntry &a, const BindingEntry &b) {
191*5ffd83dbSDimitry Andric     OutputSegment *segA = a.isec->parent->parent;
192*5ffd83dbSDimitry Andric     OutputSegment *segB = b.isec->parent->parent;
193*5ffd83dbSDimitry Andric     if (segA != segB)
194*5ffd83dbSDimitry Andric       return segA->fileOff < segB->fileOff;
195*5ffd83dbSDimitry Andric     OutputSection *osecA = a.isec->parent;
196*5ffd83dbSDimitry Andric     OutputSection *osecB = b.isec->parent;
197*5ffd83dbSDimitry Andric     if (osecA != osecB)
198*5ffd83dbSDimitry Andric       return osecA->addr < osecB->addr;
199*5ffd83dbSDimitry Andric     if (a.isec != b.isec)
200*5ffd83dbSDimitry Andric       return a.isec->outSecOff < b.isec->outSecOff;
201*5ffd83dbSDimitry Andric     return a.offset < b.offset;
202*5ffd83dbSDimitry Andric   });
203*5ffd83dbSDimitry Andric   for (const BindingEntry &b : bindings) {
204*5ffd83dbSDimitry Andric     didEncode = true;
205*5ffd83dbSDimitry Andric     encodeBinding(*b.dysym, b.isec->parent, b.isec->outSecOff + b.offset,
206*5ffd83dbSDimitry Andric                   b.addend, lastBinding, os);
207*5ffd83dbSDimitry Andric   }
208*5ffd83dbSDimitry Andric   if (didEncode)
209*5ffd83dbSDimitry Andric     os << static_cast<uint8_t>(MachO::BIND_OPCODE_DONE);
210*5ffd83dbSDimitry Andric }
211*5ffd83dbSDimitry Andric 
212*5ffd83dbSDimitry Andric void BindingSection::writeTo(uint8_t *buf) const {
213*5ffd83dbSDimitry Andric   memcpy(buf, contents.data(), contents.size());
214*5ffd83dbSDimitry Andric }
215*5ffd83dbSDimitry Andric 
216*5ffd83dbSDimitry Andric StubsSection::StubsSection()
217*5ffd83dbSDimitry Andric     : SyntheticSection(segment_names::text, "__stubs") {}
218*5ffd83dbSDimitry Andric 
219*5ffd83dbSDimitry Andric uint64_t StubsSection::getSize() const {
220*5ffd83dbSDimitry Andric   return entries.size() * target->stubSize;
221*5ffd83dbSDimitry Andric }
222*5ffd83dbSDimitry Andric 
223*5ffd83dbSDimitry Andric void StubsSection::writeTo(uint8_t *buf) const {
224*5ffd83dbSDimitry Andric   size_t off = 0;
225*5ffd83dbSDimitry Andric   for (const DylibSymbol *sym : in.stubs->getEntries()) {
226*5ffd83dbSDimitry Andric     target->writeStub(buf + off, *sym);
227*5ffd83dbSDimitry Andric     off += target->stubSize;
228*5ffd83dbSDimitry Andric   }
229*5ffd83dbSDimitry Andric }
230*5ffd83dbSDimitry Andric 
231*5ffd83dbSDimitry Andric void StubsSection::addEntry(DylibSymbol &sym) {
232*5ffd83dbSDimitry Andric   if (entries.insert(&sym))
233*5ffd83dbSDimitry Andric     sym.stubsIndex = entries.size() - 1;
234*5ffd83dbSDimitry Andric }
235*5ffd83dbSDimitry Andric 
236*5ffd83dbSDimitry Andric StubHelperSection::StubHelperSection()
237*5ffd83dbSDimitry Andric     : SyntheticSection(segment_names::text, "__stub_helper") {}
238*5ffd83dbSDimitry Andric 
239*5ffd83dbSDimitry Andric uint64_t StubHelperSection::getSize() const {
240*5ffd83dbSDimitry Andric   return target->stubHelperHeaderSize +
241*5ffd83dbSDimitry Andric          in.stubs->getEntries().size() * target->stubHelperEntrySize;
242*5ffd83dbSDimitry Andric }
243*5ffd83dbSDimitry Andric 
244*5ffd83dbSDimitry Andric bool StubHelperSection::isNeeded() const {
245*5ffd83dbSDimitry Andric   return !in.stubs->getEntries().empty();
246*5ffd83dbSDimitry Andric }
247*5ffd83dbSDimitry Andric 
248*5ffd83dbSDimitry Andric void StubHelperSection::writeTo(uint8_t *buf) const {
249*5ffd83dbSDimitry Andric   target->writeStubHelperHeader(buf);
250*5ffd83dbSDimitry Andric   size_t off = target->stubHelperHeaderSize;
251*5ffd83dbSDimitry Andric   for (const DylibSymbol *sym : in.stubs->getEntries()) {
252*5ffd83dbSDimitry Andric     target->writeStubHelperEntry(buf + off, *sym, addr + off);
253*5ffd83dbSDimitry Andric     off += target->stubHelperEntrySize;
254*5ffd83dbSDimitry Andric   }
255*5ffd83dbSDimitry Andric }
256*5ffd83dbSDimitry Andric 
257*5ffd83dbSDimitry Andric void StubHelperSection::setup() {
258*5ffd83dbSDimitry Andric   stubBinder = dyn_cast_or_null<DylibSymbol>(symtab->find("dyld_stub_binder"));
259*5ffd83dbSDimitry Andric   if (stubBinder == nullptr) {
260*5ffd83dbSDimitry Andric     error("symbol dyld_stub_binder not found (normally in libSystem.dylib). "
261*5ffd83dbSDimitry Andric           "Needed to perform lazy binding.");
262*5ffd83dbSDimitry Andric     return;
263*5ffd83dbSDimitry Andric   }
264*5ffd83dbSDimitry Andric   in.got->addEntry(*stubBinder);
265*5ffd83dbSDimitry Andric 
266*5ffd83dbSDimitry Andric   inputSections.push_back(in.imageLoaderCache);
267*5ffd83dbSDimitry Andric   symtab->addDefined("__dyld_private", in.imageLoaderCache, 0);
268*5ffd83dbSDimitry Andric }
269*5ffd83dbSDimitry Andric 
270*5ffd83dbSDimitry Andric ImageLoaderCacheSection::ImageLoaderCacheSection() {
271*5ffd83dbSDimitry Andric   segname = segment_names::data;
272*5ffd83dbSDimitry Andric   name = "__data";
273*5ffd83dbSDimitry Andric   uint8_t *arr = bAlloc.Allocate<uint8_t>(WordSize);
274*5ffd83dbSDimitry Andric   memset(arr, 0, WordSize);
275*5ffd83dbSDimitry Andric   data = {arr, WordSize};
276*5ffd83dbSDimitry Andric }
277*5ffd83dbSDimitry Andric 
278*5ffd83dbSDimitry Andric LazyPointerSection::LazyPointerSection()
279*5ffd83dbSDimitry Andric     : SyntheticSection(segment_names::data, "__la_symbol_ptr") {
280*5ffd83dbSDimitry Andric   align = 8;
281*5ffd83dbSDimitry Andric   flags = MachO::S_LAZY_SYMBOL_POINTERS;
282*5ffd83dbSDimitry Andric }
283*5ffd83dbSDimitry Andric 
284*5ffd83dbSDimitry Andric uint64_t LazyPointerSection::getSize() const {
285*5ffd83dbSDimitry Andric   return in.stubs->getEntries().size() * WordSize;
286*5ffd83dbSDimitry Andric }
287*5ffd83dbSDimitry Andric 
288*5ffd83dbSDimitry Andric bool LazyPointerSection::isNeeded() const {
289*5ffd83dbSDimitry Andric   return !in.stubs->getEntries().empty();
290*5ffd83dbSDimitry Andric }
291*5ffd83dbSDimitry Andric 
292*5ffd83dbSDimitry Andric void LazyPointerSection::writeTo(uint8_t *buf) const {
293*5ffd83dbSDimitry Andric   size_t off = 0;
294*5ffd83dbSDimitry Andric   for (const DylibSymbol *sym : in.stubs->getEntries()) {
295*5ffd83dbSDimitry Andric     uint64_t stubHelperOffset = target->stubHelperHeaderSize +
296*5ffd83dbSDimitry Andric                                 sym->stubsIndex * target->stubHelperEntrySize;
297*5ffd83dbSDimitry Andric     write64le(buf + off, in.stubHelper->addr + stubHelperOffset);
298*5ffd83dbSDimitry Andric     off += WordSize;
299*5ffd83dbSDimitry Andric   }
300*5ffd83dbSDimitry Andric }
301*5ffd83dbSDimitry Andric 
302*5ffd83dbSDimitry Andric LazyBindingSection::LazyBindingSection()
303*5ffd83dbSDimitry Andric     : SyntheticSection(segment_names::linkEdit, section_names::lazyBinding) {}
304*5ffd83dbSDimitry Andric 
305*5ffd83dbSDimitry Andric bool LazyBindingSection::isNeeded() const { return in.stubs->isNeeded(); }
306*5ffd83dbSDimitry Andric 
307*5ffd83dbSDimitry Andric void LazyBindingSection::finalizeContents() {
308*5ffd83dbSDimitry Andric   // TODO: Just precompute output size here instead of writing to a temporary
309*5ffd83dbSDimitry Andric   // buffer
310*5ffd83dbSDimitry Andric   for (DylibSymbol *sym : in.stubs->getEntries())
311*5ffd83dbSDimitry Andric     sym->lazyBindOffset = encode(*sym);
312*5ffd83dbSDimitry Andric }
313*5ffd83dbSDimitry Andric 
314*5ffd83dbSDimitry Andric void LazyBindingSection::writeTo(uint8_t *buf) const {
315*5ffd83dbSDimitry Andric   memcpy(buf, contents.data(), contents.size());
316*5ffd83dbSDimitry Andric }
317*5ffd83dbSDimitry Andric 
318*5ffd83dbSDimitry Andric // Unlike the non-lazy binding section, the bind opcodes in this section aren't
319*5ffd83dbSDimitry Andric // interpreted all at once. Rather, dyld will start interpreting opcodes at a
320*5ffd83dbSDimitry Andric // given offset, typically only binding a single symbol before it finds a
321*5ffd83dbSDimitry Andric // BIND_OPCODE_DONE terminator. As such, unlike in the non-lazy-binding case,
322*5ffd83dbSDimitry Andric // we cannot encode just the differences between symbols; we have to emit the
323*5ffd83dbSDimitry Andric // complete bind information for each symbol.
324*5ffd83dbSDimitry Andric uint32_t LazyBindingSection::encode(const DylibSymbol &sym) {
325*5ffd83dbSDimitry Andric   uint32_t opstreamOffset = contents.size();
326*5ffd83dbSDimitry Andric   OutputSegment *dataSeg = in.lazyPointers->parent;
327*5ffd83dbSDimitry Andric   os << static_cast<uint8_t>(MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB |
328*5ffd83dbSDimitry Andric                              dataSeg->index);
329*5ffd83dbSDimitry Andric   uint64_t offset = in.lazyPointers->addr - dataSeg->firstSection()->addr +
330*5ffd83dbSDimitry Andric                     sym.stubsIndex * WordSize;
331*5ffd83dbSDimitry Andric   encodeULEB128(offset, os);
332*5ffd83dbSDimitry Andric   if (sym.file->ordinal <= MachO::BIND_IMMEDIATE_MASK)
333*5ffd83dbSDimitry Andric     os << static_cast<uint8_t>(MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM |
334*5ffd83dbSDimitry Andric                                sym.file->ordinal);
335*5ffd83dbSDimitry Andric   else
336*5ffd83dbSDimitry Andric     fatal("TODO: Support larger dylib symbol ordinals");
337*5ffd83dbSDimitry Andric 
338*5ffd83dbSDimitry Andric   os << static_cast<uint8_t>(MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM)
339*5ffd83dbSDimitry Andric      << sym.getName() << '\0'
340*5ffd83dbSDimitry Andric      << static_cast<uint8_t>(MachO::BIND_OPCODE_DO_BIND)
341*5ffd83dbSDimitry Andric      << static_cast<uint8_t>(MachO::BIND_OPCODE_DONE);
342*5ffd83dbSDimitry Andric   return opstreamOffset;
343*5ffd83dbSDimitry Andric }
344*5ffd83dbSDimitry Andric 
345*5ffd83dbSDimitry Andric ExportSection::ExportSection()
346*5ffd83dbSDimitry Andric     : SyntheticSection(segment_names::linkEdit, section_names::export_) {}
347*5ffd83dbSDimitry Andric 
348*5ffd83dbSDimitry Andric void ExportSection::finalizeContents() {
349*5ffd83dbSDimitry Andric   // TODO: We should check symbol visibility.
350*5ffd83dbSDimitry Andric   for (const Symbol *sym : symtab->getSymbols())
351*5ffd83dbSDimitry Andric     if (auto *defined = dyn_cast<Defined>(sym))
352*5ffd83dbSDimitry Andric       trieBuilder.addSymbol(*defined);
353*5ffd83dbSDimitry Andric   size = trieBuilder.build();
354*5ffd83dbSDimitry Andric }
355*5ffd83dbSDimitry Andric 
356*5ffd83dbSDimitry Andric void ExportSection::writeTo(uint8_t *buf) const { trieBuilder.writeTo(buf); }
357*5ffd83dbSDimitry Andric 
358*5ffd83dbSDimitry Andric SymtabSection::SymtabSection(StringTableSection &stringTableSection)
359*5ffd83dbSDimitry Andric     : SyntheticSection(segment_names::linkEdit, section_names::symbolTable),
360*5ffd83dbSDimitry Andric       stringTableSection(stringTableSection) {
361*5ffd83dbSDimitry Andric   // TODO: When we introduce the SyntheticSections superclass, we should make
362*5ffd83dbSDimitry Andric   // all synthetic sections aligned to WordSize by default.
363*5ffd83dbSDimitry Andric   align = WordSize;
364*5ffd83dbSDimitry Andric }
365*5ffd83dbSDimitry Andric 
366*5ffd83dbSDimitry Andric uint64_t SymtabSection::getSize() const {
367*5ffd83dbSDimitry Andric   return symbols.size() * sizeof(structs::nlist_64);
368*5ffd83dbSDimitry Andric }
369*5ffd83dbSDimitry Andric 
370*5ffd83dbSDimitry Andric void SymtabSection::finalizeContents() {
371*5ffd83dbSDimitry Andric   // TODO support other symbol types
372*5ffd83dbSDimitry Andric   for (Symbol *sym : symtab->getSymbols())
373*5ffd83dbSDimitry Andric     if (isa<Defined>(sym))
374*5ffd83dbSDimitry Andric       symbols.push_back({sym, stringTableSection.addString(sym->getName())});
375*5ffd83dbSDimitry Andric }
376*5ffd83dbSDimitry Andric 
377*5ffd83dbSDimitry Andric void SymtabSection::writeTo(uint8_t *buf) const {
378*5ffd83dbSDimitry Andric   auto *nList = reinterpret_cast<structs::nlist_64 *>(buf);
379*5ffd83dbSDimitry Andric   for (const SymtabEntry &entry : symbols) {
380*5ffd83dbSDimitry Andric     nList->n_strx = entry.strx;
381*5ffd83dbSDimitry Andric     // TODO support other symbol types
382*5ffd83dbSDimitry Andric     // TODO populate n_desc
383*5ffd83dbSDimitry Andric     if (auto *defined = dyn_cast<Defined>(entry.sym)) {
384*5ffd83dbSDimitry Andric       nList->n_type = MachO::N_EXT | MachO::N_SECT;
385*5ffd83dbSDimitry Andric       nList->n_sect = defined->isec->parent->index;
386*5ffd83dbSDimitry Andric       // For the N_SECT symbol type, n_value is the address of the symbol
387*5ffd83dbSDimitry Andric       nList->n_value = defined->value + defined->isec->getVA();
388*5ffd83dbSDimitry Andric     }
389*5ffd83dbSDimitry Andric     ++nList;
390*5ffd83dbSDimitry Andric   }
391*5ffd83dbSDimitry Andric }
392*5ffd83dbSDimitry Andric 
393*5ffd83dbSDimitry Andric StringTableSection::StringTableSection()
394*5ffd83dbSDimitry Andric     : SyntheticSection(segment_names::linkEdit, section_names::stringTable) {}
395*5ffd83dbSDimitry Andric 
396*5ffd83dbSDimitry Andric uint32_t StringTableSection::addString(StringRef str) {
397*5ffd83dbSDimitry Andric   uint32_t strx = size;
398*5ffd83dbSDimitry Andric   strings.push_back(str);
399*5ffd83dbSDimitry Andric   size += str.size() + 1; // account for null terminator
400*5ffd83dbSDimitry Andric   return strx;
401*5ffd83dbSDimitry Andric }
402*5ffd83dbSDimitry Andric 
403*5ffd83dbSDimitry Andric void StringTableSection::writeTo(uint8_t *buf) const {
404*5ffd83dbSDimitry Andric   uint32_t off = 0;
405*5ffd83dbSDimitry Andric   for (StringRef str : strings) {
406*5ffd83dbSDimitry Andric     memcpy(buf + off, str.data(), str.size());
407*5ffd83dbSDimitry Andric     off += str.size() + 1; // account for null terminator
408*5ffd83dbSDimitry Andric   }
409*5ffd83dbSDimitry Andric }
410