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