[Dexter][NFC] Add Missing Commands to Commands.md Contents
[llvm-project.git] / lld / MachO / SyntheticSections.cpp
blob5d603d6f90d38dc0f05c086e894493ed59266fd5
1 //===- SyntheticSections.cpp ---------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "SyntheticSections.h"
10 #include "Config.h"
11 #include "ExportTrie.h"
12 #include "InputFiles.h"
13 #include "MachOStructs.h"
14 #include "MergedOutputSection.h"
15 #include "OutputSegment.h"
16 #include "SymbolTable.h"
17 #include "Symbols.h"
18 #include "Writer.h"
20 #include "lld/Common/ErrorHandler.h"
21 #include "lld/Common/Memory.h"
22 #include "llvm/Support/EndianStream.h"
23 #include "llvm/Support/LEB128.h"
25 using namespace llvm;
26 using namespace llvm::support;
27 using namespace llvm::support::endian;
28 using namespace lld;
29 using namespace lld::macho;
31 InStruct macho::in;
32 std::vector<SyntheticSection *> macho::syntheticSections;
34 SyntheticSection::SyntheticSection(const char *segname, const char *name)
35 : OutputSection(SyntheticKind, name), segname(segname) {
36 syntheticSections.push_back(this);
39 // dyld3's MachOLoaded::getSlide() assumes that the __TEXT segment starts
40 // from the beginning of the file (i.e. the header).
41 MachHeaderSection::MachHeaderSection()
42 : SyntheticSection(segment_names::text, section_names::header) {}
44 void MachHeaderSection::addLoadCommand(LoadCommand *lc) {
45 loadCommands.push_back(lc);
46 sizeOfCmds += lc->getSize();
49 uint64_t MachHeaderSection::getSize() const {
50 return sizeof(MachO::mach_header_64) + sizeOfCmds + config->headerPad;
53 void MachHeaderSection::writeTo(uint8_t *buf) const {
54 auto *hdr = reinterpret_cast<MachO::mach_header_64 *>(buf);
55 hdr->magic = MachO::MH_MAGIC_64;
56 hdr->cputype = MachO::CPU_TYPE_X86_64;
57 hdr->cpusubtype = MachO::CPU_SUBTYPE_X86_64_ALL | MachO::CPU_SUBTYPE_LIB64;
58 hdr->filetype = config->outputType;
59 hdr->ncmds = loadCommands.size();
60 hdr->sizeofcmds = sizeOfCmds;
61 hdr->flags = MachO::MH_NOUNDEFS | MachO::MH_DYLDLINK | MachO::MH_TWOLEVEL;
63 if (config->outputType == MachO::MH_DYLIB && !config->hasReexports)
64 hdr->flags |= MachO::MH_NO_REEXPORTED_DYLIBS;
66 if (config->outputType == MachO::MH_EXECUTE && config->isPic)
67 hdr->flags |= MachO::MH_PIE;
69 if (in.exports->hasWeakSymbol || in.weakBinding->hasNonWeakDefinition())
70 hdr->flags |= MachO::MH_WEAK_DEFINES;
72 if (in.exports->hasWeakSymbol || in.weakBinding->hasEntry())
73 hdr->flags |= MachO::MH_BINDS_TO_WEAK;
75 for (OutputSegment *seg : outputSegments) {
76 for (OutputSection *osec : seg->getSections()) {
77 if (isThreadLocalVariables(osec->flags)) {
78 hdr->flags |= MachO::MH_HAS_TLV_DESCRIPTORS;
79 break;
84 uint8_t *p = reinterpret_cast<uint8_t *>(hdr + 1);
85 for (LoadCommand *lc : loadCommands) {
86 lc->writeTo(p);
87 p += lc->getSize();
91 PageZeroSection::PageZeroSection()
92 : SyntheticSection(segment_names::pageZero, section_names::pageZero) {}
94 uint64_t Location::getVA() const {
95 if (const auto *isec = section.dyn_cast<const InputSection *>())
96 return isec->getVA() + offset;
97 return section.get<const OutputSection *>()->addr + offset;
100 RebaseSection::RebaseSection()
101 : LinkEditSection(segment_names::linkEdit, section_names::rebase) {}
103 namespace {
104 struct Rebase {
105 OutputSegment *segment = nullptr;
106 uint64_t offset = 0;
107 uint64_t consecutiveCount = 0;
109 } // namespace
111 // Rebase opcodes allow us to describe a contiguous sequence of rebase location
112 // using a single DO_REBASE opcode. To take advantage of it, we delay emitting
113 // `DO_REBASE` until we have reached the end of a contiguous sequence.
114 static void encodeDoRebase(Rebase &rebase, raw_svector_ostream &os) {
115 using namespace llvm::MachO;
116 assert(rebase.consecutiveCount != 0);
117 if (rebase.consecutiveCount <= REBASE_IMMEDIATE_MASK) {
118 os << static_cast<uint8_t>(REBASE_OPCODE_DO_REBASE_IMM_TIMES |
119 rebase.consecutiveCount);
120 } else {
121 os << static_cast<uint8_t>(REBASE_OPCODE_DO_REBASE_ULEB_TIMES);
122 encodeULEB128(rebase.consecutiveCount, os);
124 rebase.consecutiveCount = 0;
127 static void encodeRebase(const OutputSection *osec, uint64_t outSecOff,
128 Rebase &lastRebase, raw_svector_ostream &os) {
129 using namespace llvm::MachO;
130 OutputSegment *seg = osec->parent;
131 uint64_t offset = osec->getSegmentOffset() + outSecOff;
132 if (lastRebase.segment != seg || lastRebase.offset != offset) {
133 if (lastRebase.consecutiveCount != 0)
134 encodeDoRebase(lastRebase, os);
136 if (lastRebase.segment != seg) {
137 os << static_cast<uint8_t>(REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB |
138 seg->index);
139 encodeULEB128(offset, os);
140 lastRebase.segment = seg;
141 lastRebase.offset = offset;
142 } else {
143 assert(lastRebase.offset != offset);
144 os << static_cast<uint8_t>(REBASE_OPCODE_ADD_ADDR_ULEB);
145 encodeULEB128(offset - lastRebase.offset, os);
146 lastRebase.offset = offset;
149 ++lastRebase.consecutiveCount;
150 // DO_REBASE causes dyld to both perform the binding and increment the offset
151 lastRebase.offset += WordSize;
154 void RebaseSection::finalizeContents() {
155 using namespace llvm::MachO;
156 if (locations.empty())
157 return;
159 raw_svector_ostream os{contents};
160 Rebase lastRebase;
162 os << static_cast<uint8_t>(REBASE_OPCODE_SET_TYPE_IMM | REBASE_TYPE_POINTER);
164 llvm::sort(locations, [](const Location &a, const Location &b) {
165 return a.getVA() < b.getVA();
167 for (const Location &loc : locations) {
168 if (const auto *isec = loc.section.dyn_cast<const InputSection *>()) {
169 encodeRebase(isec->parent, isec->outSecOff + loc.offset, lastRebase, os);
170 } else {
171 const auto *osec = loc.section.get<const OutputSection *>();
172 encodeRebase(osec, loc.offset, lastRebase, os);
175 if (lastRebase.consecutiveCount != 0)
176 encodeDoRebase(lastRebase, os);
178 os << static_cast<uint8_t>(REBASE_OPCODE_DONE);
181 void RebaseSection::writeTo(uint8_t *buf) const {
182 memcpy(buf, contents.data(), contents.size());
185 NonLazyPointerSectionBase::NonLazyPointerSectionBase(const char *segname,
186 const char *name)
187 : SyntheticSection(segname, name) {
188 align = 8;
189 flags = MachO::S_NON_LAZY_SYMBOL_POINTERS;
192 void NonLazyPointerSectionBase::addEntry(Symbol *sym) {
193 if (entries.insert(sym)) {
194 assert(!sym->isInGot());
195 sym->gotIndex = entries.size() - 1;
197 addNonLazyBindingEntries(sym, this, sym->gotIndex * WordSize);
201 void NonLazyPointerSectionBase::writeTo(uint8_t *buf) const {
202 for (size_t i = 0, n = entries.size(); i < n; ++i)
203 if (auto *defined = dyn_cast<Defined>(entries[i]))
204 write64le(&buf[i * WordSize], defined->getVA());
207 BindingSection::BindingSection()
208 : LinkEditSection(segment_names::linkEdit, section_names::binding) {}
210 namespace {
211 struct Binding {
212 OutputSegment *segment = nullptr;
213 uint64_t offset = 0;
214 int64_t addend = 0;
215 uint8_t ordinal = 0;
217 } // namespace
219 // Encode a sequence of opcodes that tell dyld to write the address of symbol +
220 // addend at osec->addr + outSecOff.
222 // The bind opcode "interpreter" remembers the values of each binding field, so
223 // we only need to encode the differences between bindings. Hence the use of
224 // lastBinding.
225 static void encodeBinding(const Symbol *sym, const OutputSection *osec,
226 uint64_t outSecOff, int64_t addend,
227 Binding &lastBinding, raw_svector_ostream &os) {
228 using namespace llvm::MachO;
229 OutputSegment *seg = osec->parent;
230 uint64_t offset = osec->getSegmentOffset() + outSecOff;
231 if (lastBinding.segment != seg) {
232 os << static_cast<uint8_t>(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB |
233 seg->index);
234 encodeULEB128(offset, os);
235 lastBinding.segment = seg;
236 lastBinding.offset = offset;
237 } else if (lastBinding.offset != offset) {
238 os << static_cast<uint8_t>(BIND_OPCODE_ADD_ADDR_ULEB);
239 encodeULEB128(offset - lastBinding.offset, os);
240 lastBinding.offset = offset;
243 if (lastBinding.addend != addend) {
244 os << static_cast<uint8_t>(BIND_OPCODE_SET_ADDEND_SLEB);
245 encodeSLEB128(addend, os);
246 lastBinding.addend = addend;
249 os << static_cast<uint8_t>(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM)
250 << sym->getName() << '\0'
251 << static_cast<uint8_t>(BIND_OPCODE_SET_TYPE_IMM | BIND_TYPE_POINTER)
252 << static_cast<uint8_t>(BIND_OPCODE_DO_BIND);
253 // DO_BIND causes dyld to both perform the binding and increment the offset
254 lastBinding.offset += WordSize;
257 // Non-weak bindings need to have their dylib ordinal encoded as well.
258 static void encodeDylibOrdinal(const DylibSymbol *dysym, Binding &lastBinding,
259 raw_svector_ostream &os) {
260 using namespace llvm::MachO;
261 if (lastBinding.ordinal != dysym->file->ordinal) {
262 if (dysym->file->ordinal <= BIND_IMMEDIATE_MASK) {
263 os << static_cast<uint8_t>(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM |
264 dysym->file->ordinal);
265 } else {
266 os << static_cast<uint8_t>(BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB);
267 encodeULEB128(dysym->file->ordinal, os);
269 lastBinding.ordinal = dysym->file->ordinal;
273 static void encodeWeakOverride(const Defined *defined,
274 raw_svector_ostream &os) {
275 using namespace llvm::MachO;
276 os << static_cast<uint8_t>(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM |
277 BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
278 << defined->getName() << '\0';
281 // Emit bind opcodes, which are a stream of byte-sized opcodes that dyld
282 // interprets to update a record with the following fields:
283 // * segment index (of the segment to write the symbol addresses to, typically
284 // the __DATA_CONST segment which contains the GOT)
285 // * offset within the segment, indicating the next location to write a binding
286 // * symbol type
287 // * symbol library ordinal (the index of its library's LC_LOAD_DYLIB command)
288 // * symbol name
289 // * addend
290 // When dyld sees BIND_OPCODE_DO_BIND, it uses the current record state to bind
291 // a symbol in the GOT, and increments the segment offset to point to the next
292 // entry. It does *not* clear the record state after doing the bind, so
293 // subsequent opcodes only need to encode the differences between bindings.
294 void BindingSection::finalizeContents() {
295 raw_svector_ostream os{contents};
296 Binding lastBinding;
298 // Since bindings are delta-encoded, sorting them allows for a more compact
299 // result. Note that sorting by address alone ensures that bindings for the
300 // same segment / section are located together.
301 llvm::sort(bindings, [](const BindingEntry &a, const BindingEntry &b) {
302 return a.target.getVA() < b.target.getVA();
304 for (const BindingEntry &b : bindings) {
305 encodeDylibOrdinal(b.dysym, lastBinding, os);
306 if (auto *isec = b.target.section.dyn_cast<const InputSection *>()) {
307 encodeBinding(b.dysym, isec->parent, isec->outSecOff + b.target.offset,
308 b.addend, lastBinding, os);
309 } else {
310 auto *osec = b.target.section.get<const OutputSection *>();
311 encodeBinding(b.dysym, osec, b.target.offset, b.addend, lastBinding, os);
314 if (!bindings.empty())
315 os << static_cast<uint8_t>(MachO::BIND_OPCODE_DONE);
318 void BindingSection::writeTo(uint8_t *buf) const {
319 memcpy(buf, contents.data(), contents.size());
322 WeakBindingSection::WeakBindingSection()
323 : LinkEditSection(segment_names::linkEdit, section_names::weakBinding) {}
325 void WeakBindingSection::finalizeContents() {
326 raw_svector_ostream os{contents};
327 Binding lastBinding;
329 for (const Defined *defined : definitions)
330 encodeWeakOverride(defined, os);
332 // Since bindings are delta-encoded, sorting them allows for a more compact
333 // result.
334 llvm::sort(bindings,
335 [](const WeakBindingEntry &a, const WeakBindingEntry &b) {
336 return a.target.getVA() < b.target.getVA();
338 for (const WeakBindingEntry &b : bindings) {
339 if (auto *isec = b.target.section.dyn_cast<const InputSection *>()) {
340 encodeBinding(b.symbol, isec->parent, isec->outSecOff + b.target.offset,
341 b.addend, lastBinding, os);
342 } else {
343 auto *osec = b.target.section.get<const OutputSection *>();
344 encodeBinding(b.symbol, osec, b.target.offset, b.addend, lastBinding, os);
347 if (!bindings.empty() || !definitions.empty())
348 os << static_cast<uint8_t>(MachO::BIND_OPCODE_DONE);
351 void WeakBindingSection::writeTo(uint8_t *buf) const {
352 memcpy(buf, contents.data(), contents.size());
355 bool macho::needsBinding(const Symbol *sym) {
356 if (isa<DylibSymbol>(sym)) {
357 return true;
358 } else if (const auto *defined = dyn_cast<Defined>(sym)) {
359 if (defined->isWeakDef() && defined->isExternal())
360 return true;
362 return false;
365 void macho::addNonLazyBindingEntries(const Symbol *sym,
366 SectionPointerUnion section,
367 uint64_t offset, int64_t addend) {
368 if (auto *dysym = dyn_cast<DylibSymbol>(sym)) {
369 in.binding->addEntry(dysym, section, offset, addend);
370 if (dysym->isWeakDef())
371 in.weakBinding->addEntry(sym, section, offset, addend);
372 } else if (auto *defined = dyn_cast<Defined>(sym)) {
373 in.rebase->addEntry(section, offset);
374 if (defined->isWeakDef() && defined->isExternal())
375 in.weakBinding->addEntry(sym, section, offset, addend);
376 } else if (isa<DSOHandle>(sym)) {
377 error("cannot bind to " + DSOHandle::name);
378 } else {
379 // Undefined symbols are filtered out in scanRelocations(); we should never
380 // get here
381 llvm_unreachable("cannot bind to an undefined symbol");
385 StubsSection::StubsSection()
386 : SyntheticSection(segment_names::text, "__stubs") {
387 flags = MachO::S_SYMBOL_STUBS;
388 reserved2 = target->stubSize;
391 uint64_t StubsSection::getSize() const {
392 return entries.size() * target->stubSize;
395 void StubsSection::writeTo(uint8_t *buf) const {
396 size_t off = 0;
397 for (const Symbol *sym : entries) {
398 target->writeStub(buf + off, *sym);
399 off += target->stubSize;
403 bool StubsSection::addEntry(Symbol *sym) {
404 bool inserted = entries.insert(sym);
405 if (inserted)
406 sym->stubsIndex = entries.size() - 1;
407 return inserted;
410 StubHelperSection::StubHelperSection()
411 : SyntheticSection(segment_names::text, "__stub_helper") {}
413 uint64_t StubHelperSection::getSize() const {
414 return target->stubHelperHeaderSize +
415 in.lazyBinding->getEntries().size() * target->stubHelperEntrySize;
418 bool StubHelperSection::isNeeded() const { return in.lazyBinding->isNeeded(); }
420 void StubHelperSection::writeTo(uint8_t *buf) const {
421 target->writeStubHelperHeader(buf);
422 size_t off = target->stubHelperHeaderSize;
423 for (const DylibSymbol *sym : in.lazyBinding->getEntries()) {
424 target->writeStubHelperEntry(buf + off, *sym, addr + off);
425 off += target->stubHelperEntrySize;
429 void StubHelperSection::setup() {
430 stubBinder = dyn_cast_or_null<DylibSymbol>(symtab->find("dyld_stub_binder"));
431 if (stubBinder == nullptr) {
432 error("symbol dyld_stub_binder not found (normally in libSystem.dylib). "
433 "Needed to perform lazy binding.");
434 return;
436 in.got->addEntry(stubBinder);
438 inputSections.push_back(in.imageLoaderCache);
439 symtab->addDefined("__dyld_private", in.imageLoaderCache, 0,
440 /*isWeakDef=*/false);
443 ImageLoaderCacheSection::ImageLoaderCacheSection() {
444 segname = segment_names::data;
445 name = "__data";
446 uint8_t *arr = bAlloc.Allocate<uint8_t>(WordSize);
447 memset(arr, 0, WordSize);
448 data = {arr, WordSize};
451 LazyPointerSection::LazyPointerSection()
452 : SyntheticSection(segment_names::data, "__la_symbol_ptr") {
453 align = 8;
454 flags = MachO::S_LAZY_SYMBOL_POINTERS;
457 uint64_t LazyPointerSection::getSize() const {
458 return in.stubs->getEntries().size() * WordSize;
461 bool LazyPointerSection::isNeeded() const {
462 return !in.stubs->getEntries().empty();
465 void LazyPointerSection::writeTo(uint8_t *buf) const {
466 size_t off = 0;
467 for (const Symbol *sym : in.stubs->getEntries()) {
468 if (const auto *dysym = dyn_cast<DylibSymbol>(sym)) {
469 if (dysym->hasStubsHelper()) {
470 uint64_t stubHelperOffset =
471 target->stubHelperHeaderSize +
472 dysym->stubsHelperIndex * target->stubHelperEntrySize;
473 write64le(buf + off, in.stubHelper->addr + stubHelperOffset);
475 } else {
476 write64le(buf + off, sym->getVA());
478 off += WordSize;
482 LazyBindingSection::LazyBindingSection()
483 : LinkEditSection(segment_names::linkEdit, section_names::lazyBinding) {}
485 void LazyBindingSection::finalizeContents() {
486 // TODO: Just precompute output size here instead of writing to a temporary
487 // buffer
488 for (DylibSymbol *sym : entries)
489 sym->lazyBindOffset = encode(*sym);
492 void LazyBindingSection::writeTo(uint8_t *buf) const {
493 memcpy(buf, contents.data(), contents.size());
496 void LazyBindingSection::addEntry(DylibSymbol *dysym) {
497 if (entries.insert(dysym)) {
498 dysym->stubsHelperIndex = entries.size() - 1;
499 in.rebase->addEntry(in.lazyPointers, dysym->stubsIndex * WordSize);
503 // Unlike the non-lazy binding section, the bind opcodes in this section aren't
504 // interpreted all at once. Rather, dyld will start interpreting opcodes at a
505 // given offset, typically only binding a single symbol before it finds a
506 // BIND_OPCODE_DONE terminator. As such, unlike in the non-lazy-binding case,
507 // we cannot encode just the differences between symbols; we have to emit the
508 // complete bind information for each symbol.
509 uint32_t LazyBindingSection::encode(const DylibSymbol &sym) {
510 uint32_t opstreamOffset = contents.size();
511 OutputSegment *dataSeg = in.lazyPointers->parent;
512 os << static_cast<uint8_t>(MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB |
513 dataSeg->index);
514 uint64_t offset = in.lazyPointers->addr - dataSeg->firstSection()->addr +
515 sym.stubsIndex * WordSize;
516 encodeULEB128(offset, os);
517 if (sym.file->ordinal <= MachO::BIND_IMMEDIATE_MASK) {
518 os << static_cast<uint8_t>(MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM |
519 sym.file->ordinal);
520 } else {
521 os << static_cast<uint8_t>(MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB);
522 encodeULEB128(sym.file->ordinal, os);
525 os << static_cast<uint8_t>(MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM)
526 << sym.getName() << '\0'
527 << static_cast<uint8_t>(MachO::BIND_OPCODE_DO_BIND)
528 << static_cast<uint8_t>(MachO::BIND_OPCODE_DONE);
529 return opstreamOffset;
532 void macho::prepareBranchTarget(Symbol *sym) {
533 if (auto *dysym = dyn_cast<DylibSymbol>(sym)) {
534 if (in.stubs->addEntry(dysym)) {
535 if (sym->isWeakDef()) {
536 in.binding->addEntry(dysym, in.lazyPointers,
537 sym->stubsIndex * WordSize);
538 in.weakBinding->addEntry(sym, in.lazyPointers,
539 sym->stubsIndex * WordSize);
540 } else {
541 in.lazyBinding->addEntry(dysym);
544 } else if (auto *defined = dyn_cast<Defined>(sym)) {
545 if (defined->isWeakDef() && defined->isExternal()) {
546 if (in.stubs->addEntry(sym)) {
547 in.rebase->addEntry(in.lazyPointers, sym->stubsIndex * WordSize);
548 in.weakBinding->addEntry(sym, in.lazyPointers,
549 sym->stubsIndex * WordSize);
555 ExportSection::ExportSection()
556 : LinkEditSection(segment_names::linkEdit, section_names::export_) {}
558 void ExportSection::finalizeContents() {
559 trieBuilder.setImageBase(in.header->addr);
560 // TODO: We should check symbol visibility.
561 for (const Symbol *sym : symtab->getSymbols()) {
562 if (const auto *defined = dyn_cast<Defined>(sym)) {
563 trieBuilder.addSymbol(*defined);
564 hasWeakSymbol = hasWeakSymbol || sym->isWeakDef();
567 size = trieBuilder.build();
570 void ExportSection::writeTo(uint8_t *buf) const { trieBuilder.writeTo(buf); }
572 SymtabSection::SymtabSection(StringTableSection &stringTableSection)
573 : LinkEditSection(segment_names::linkEdit, section_names::symbolTable),
574 stringTableSection(stringTableSection) {}
576 uint64_t SymtabSection::getRawSize() const {
577 return symbols.size() * sizeof(structs::nlist_64);
580 void SymtabSection::finalizeContents() {
581 // TODO support other symbol types
582 for (Symbol *sym : symtab->getSymbols()) {
583 if (isa<Defined>(sym) || sym->isInGot() || sym->isInStubs()) {
584 sym->symtabIndex = symbols.size();
585 symbols.push_back({sym, stringTableSection.addString(sym->getName())});
590 void SymtabSection::writeTo(uint8_t *buf) const {
591 auto *nList = reinterpret_cast<structs::nlist_64 *>(buf);
592 for (const SymtabEntry &entry : symbols) {
593 nList->n_strx = entry.strx;
594 // TODO support other symbol types
595 // TODO populate n_desc with more flags
596 if (auto *defined = dyn_cast<Defined>(entry.sym)) {
597 if (defined->isAbsolute()) {
598 nList->n_type = MachO::N_EXT | MachO::N_ABS;
599 nList->n_sect = MachO::NO_SECT;
600 nList->n_value = defined->value;
601 } else {
602 nList->n_type = MachO::N_EXT | MachO::N_SECT;
603 nList->n_sect = defined->isec->parent->index;
604 // For the N_SECT symbol type, n_value is the address of the symbol
605 nList->n_value = defined->value + defined->isec->getVA();
607 nList->n_desc |= defined->isWeakDef() ? MachO::N_WEAK_DEF : 0;
609 ++nList;
613 IndirectSymtabSection::IndirectSymtabSection()
614 : LinkEditSection(segment_names::linkEdit,
615 section_names::indirectSymbolTable) {}
617 uint32_t IndirectSymtabSection::getNumSymbols() const {
618 return in.got->getEntries().size() + in.tlvPointers->getEntries().size() +
619 in.stubs->getEntries().size();
622 bool IndirectSymtabSection::isNeeded() const {
623 return in.got->isNeeded() || in.tlvPointers->isNeeded() ||
624 in.stubs->isNeeded();
627 void IndirectSymtabSection::finalizeContents() {
628 uint32_t off = 0;
629 in.got->reserved1 = off;
630 off += in.got->getEntries().size();
631 in.tlvPointers->reserved1 = off;
632 off += in.tlvPointers->getEntries().size();
633 // There is a 1:1 correspondence between stubs and LazyPointerSection
634 // entries, so they can share the same sub-array in the table.
635 in.stubs->reserved1 = in.lazyPointers->reserved1 = off;
638 void IndirectSymtabSection::writeTo(uint8_t *buf) const {
639 uint32_t off = 0;
640 for (const Symbol *sym : in.got->getEntries()) {
641 write32le(buf + off * sizeof(uint32_t), sym->symtabIndex);
642 ++off;
644 for (const Symbol *sym : in.tlvPointers->getEntries()) {
645 write32le(buf + off * sizeof(uint32_t), sym->symtabIndex);
646 ++off;
648 for (const Symbol *sym : in.stubs->getEntries()) {
649 write32le(buf + off * sizeof(uint32_t), sym->symtabIndex);
650 ++off;
654 StringTableSection::StringTableSection()
655 : LinkEditSection(segment_names::linkEdit, section_names::stringTable) {}
657 uint32_t StringTableSection::addString(StringRef str) {
658 uint32_t strx = size;
659 strings.push_back(str);
660 size += str.size() + 1; // account for null terminator
661 return strx;
664 void StringTableSection::writeTo(uint8_t *buf) const {
665 uint32_t off = 0;
666 for (StringRef str : strings) {
667 memcpy(buf + off, str.data(), str.size());
668 off += str.size() + 1; // account for null terminator