xref: /llvm-project-15.0.7/lld/MachO/Writer.cpp (revision cfb4f8c5)
1 //===- Writer.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 //===----------------------------------------------------------------------===//
8 
9 #include "Writer.h"
10 #include "Config.h"
11 #include "InputFiles.h"
12 #include "InputSection.h"
13 #include "OutputSegment.h"
14 #include "SymbolTable.h"
15 #include "Symbols.h"
16 #include "SyntheticSections.h"
17 #include "Target.h"
18 
19 #include "lld/Common/ErrorHandler.h"
20 #include "lld/Common/Memory.h"
21 #include "llvm/BinaryFormat/MachO.h"
22 #include "llvm/Support/EndianStream.h"
23 #include "llvm/Support/LEB128.h"
24 #include "llvm/Support/MathExtras.h"
25 
26 using namespace llvm;
27 using namespace llvm::MachO;
28 using namespace llvm::support;
29 using namespace lld;
30 using namespace lld::macho;
31 
32 namespace {
33 class LCLinkEdit;
34 class LCDyldInfo;
35 class LCSymtab;
36 
37 class LoadCommand {
38 public:
39   virtual ~LoadCommand() = default;
40   virtual uint32_t getSize() const = 0;
41   virtual void writeTo(uint8_t *buf) const = 0;
42 };
43 
44 class Writer {
45 public:
46   Writer() : buffer(errorHandler().outputBuffer) {}
47 
48   void createLoadCommands();
49   void scanRelocations();
50   void assignAddresses();
51 
52   void createDyldInfoContents();
53 
54   void openFile();
55   void writeHeader();
56   void writeSections();
57 
58   void run();
59 
60   std::vector<LoadCommand *> loadCommands;
61   std::unique_ptr<FileOutputBuffer> &buffer;
62   uint64_t fileSize = 0;
63   uint64_t sizeofCmds = 0;
64   LCLinkEdit *linkEditSeg = nullptr;
65   LCDyldInfo *dyldInfoSeg = nullptr;
66   LCSymtab *symtabSeg = nullptr;
67 };
68 
69 class LCPagezero : public LoadCommand {
70 public:
71   uint32_t getSize() const override { return sizeof(segment_command_64); }
72 
73   void writeTo(uint8_t *buf) const override {
74     auto *c = reinterpret_cast<segment_command_64 *>(buf);
75     c->cmd = LC_SEGMENT_64;
76     c->cmdsize = getSize();
77     strcpy(c->segname, "__PAGEZERO");
78     c->vmsize = PageSize;
79   }
80 };
81 
82 class LCLinkEdit : public LoadCommand {
83 public:
84   uint32_t getSize() const override { return sizeof(segment_command_64); }
85 
86   void writeTo(uint8_t *buf) const override {
87     auto *c = reinterpret_cast<segment_command_64 *>(buf);
88     c->cmd = LC_SEGMENT_64;
89     c->cmdsize = getSize();
90     strcpy(c->segname, "__LINKEDIT");
91     c->vmaddr = addr;
92     c->fileoff = fileOff;
93     c->filesize = c->vmsize = contents.size();
94     c->maxprot = VM_PROT_READ | VM_PROT_WRITE;
95     c->initprot = VM_PROT_READ;
96   }
97 
98   uint64_t getOffset() const { return fileOff + contents.size(); }
99 
100   uint64_t fileOff = 0;
101   uint64_t addr = 0;
102   SmallVector<char, 128> contents;
103 };
104 
105 class LCDyldInfo : public LoadCommand {
106 public:
107   uint32_t getSize() const override { return sizeof(dyld_info_command); }
108 
109   void writeTo(uint8_t *buf) const override {
110     auto *c = reinterpret_cast<dyld_info_command *>(buf);
111     c->cmd = LC_DYLD_INFO_ONLY;
112     c->cmdsize = getSize();
113     c->bind_off = bindOff;
114     c->bind_size = bindSize;
115     c->export_off = exportOff;
116     c->export_size = exportSize;
117   }
118 
119   uint64_t bindOff = 0;
120   uint64_t bindSize = 0;
121   uint64_t exportOff = 0;
122   uint64_t exportSize = 0;
123 };
124 
125 class LCDysymtab : public LoadCommand {
126 public:
127   uint32_t getSize() const override { return sizeof(dysymtab_command); }
128 
129   void writeTo(uint8_t *buf) const override {
130     auto *c = reinterpret_cast<dysymtab_command *>(buf);
131     c->cmd = LC_DYSYMTAB;
132     c->cmdsize = getSize();
133   }
134 };
135 
136 class LCSegment : public LoadCommand {
137 public:
138   LCSegment(StringRef name, OutputSegment *seg) : name(name), seg(seg) {}
139 
140   uint32_t getSize() const override {
141     return sizeof(segment_command_64) +
142            seg->sections.size() * sizeof(section_64);
143   }
144 
145   void writeTo(uint8_t *buf) const override {
146     auto *c = reinterpret_cast<segment_command_64 *>(buf);
147     buf += sizeof(segment_command_64);
148 
149     c->cmd = LC_SEGMENT_64;
150     c->cmdsize = getSize();
151     memcpy(c->segname, name.data(), name.size());
152 
153     // dyld3's MachOLoaded::getSlide() assumes that the __TEXT segment starts
154     // from the beginning of the file (i.e. the header).
155     // TODO: replace this logic by creating a synthetic __TEXT,__mach_header
156     // section instead.
157     c->fileoff = name == "__TEXT" ? 0 : seg->firstSection()->addr - ImageBase;
158     c->vmaddr = c->fileoff + ImageBase;
159     c->vmsize = c->filesize =
160         seg->lastSection()->addr + seg->lastSection()->getSize() - c->vmaddr;
161     c->maxprot = VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE;
162     c->initprot = seg->perms;
163     c->nsects = seg->sections.size();
164 
165     for (auto &p : seg->sections) {
166       StringRef s = p.first;
167       std::vector<InputSection *> &sections = p.second;
168 
169       auto *sectHdr = reinterpret_cast<section_64 *>(buf);
170       buf += sizeof(section_64);
171 
172       memcpy(sectHdr->sectname, s.data(), s.size());
173       memcpy(sectHdr->segname, name.data(), name.size());
174 
175       sectHdr->addr = sections[0]->addr;
176       sectHdr->offset = sections[0]->addr - ImageBase;
177       sectHdr->align = sections[0]->align;
178       uint32_t maxAlign = 0;
179       for (const InputSection *section : sections)
180         maxAlign = std::max(maxAlign, section->align);
181       sectHdr->align = Log2_32(maxAlign);
182       sectHdr->flags = sections[0]->flags;
183       sectHdr->size = sections.back()->addr + sections.back()->getSize() -
184                       sections[0]->addr;
185     }
186   }
187 
188 private:
189   StringRef name;
190   OutputSegment *seg;
191 };
192 
193 class LCMain : public LoadCommand {
194   uint32_t getSize() const override { return sizeof(entry_point_command); }
195 
196   void writeTo(uint8_t *buf) const override {
197     auto *c = reinterpret_cast<entry_point_command *>(buf);
198     c->cmd = LC_MAIN;
199     c->cmdsize = getSize();
200     c->entryoff = config->entry->getVA();
201     c->stacksize = 0;
202   }
203 };
204 
205 class LCSymtab : public LoadCommand {
206 public:
207   uint32_t getSize() const override { return sizeof(symtab_command); }
208 
209   void writeTo(uint8_t *buf) const override {
210     auto *c = reinterpret_cast<symtab_command *>(buf);
211     c->cmd = LC_SYMTAB;
212     c->cmdsize = getSize();
213   }
214 };
215 
216 class LCLoadDylib : public LoadCommand {
217 public:
218   LCLoadDylib(StringRef path) : path(path) {}
219 
220   uint32_t getSize() const override {
221     return alignTo(sizeof(dylib_command) + path.size() + 1, 8);
222   }
223 
224   void writeTo(uint8_t *buf) const override {
225     auto *c = reinterpret_cast<dylib_command *>(buf);
226     buf += sizeof(dylib_command);
227 
228     c->cmd = LC_LOAD_DYLIB;
229     c->cmdsize = getSize();
230     c->dylib.name = sizeof(dylib_command);
231 
232     memcpy(buf, path.data(), path.size());
233     buf[path.size()] = '\0';
234   }
235 
236 private:
237   StringRef path;
238 };
239 
240 class LCLoadDylinker : public LoadCommand {
241 public:
242   uint32_t getSize() const override {
243     return alignTo(sizeof(dylinker_command) + path.size() + 1, 8);
244   }
245 
246   void writeTo(uint8_t *buf) const override {
247     auto *c = reinterpret_cast<dylinker_command *>(buf);
248     buf += sizeof(dylinker_command);
249 
250     c->cmd = LC_LOAD_DYLINKER;
251     c->cmdsize = getSize();
252     c->name = sizeof(dylinker_command);
253 
254     memcpy(buf, path.data(), path.size());
255     buf[path.size()] = '\0';
256   }
257 
258 private:
259   // Recent versions of Darwin won't run any binary that has dyld at a
260   // different location.
261   const StringRef path = "/usr/lib/dyld";
262 };
263 } // namespace
264 
265 void Writer::createLoadCommands() {
266   linkEditSeg = make<LCLinkEdit>();
267   dyldInfoSeg = make<LCDyldInfo>();
268   symtabSeg = make<LCSymtab>();
269 
270   loadCommands.push_back(linkEditSeg);
271   loadCommands.push_back(dyldInfoSeg);
272   loadCommands.push_back(symtabSeg);
273   loadCommands.push_back(make<LCPagezero>());
274   loadCommands.push_back(make<LCLoadDylinker>());
275   loadCommands.push_back(make<LCDysymtab>());
276   loadCommands.push_back(make<LCMain>());
277 
278   uint8_t segIndex = 1; // LCPagezero is a segment load command
279   for (OutputSegment *seg : outputSegments) {
280     if (!seg->sections.empty()) {
281       loadCommands.push_back(make<LCSegment>(seg->name, seg));
282       seg->index = segIndex++;
283     }
284   }
285 
286   uint64_t dylibOrdinal = 1;
287   for (InputFile *file : inputFiles) {
288     if (auto *dylibFile = dyn_cast<DylibFile>(file)) {
289       loadCommands.push_back(make<LCLoadDylib>(dylibFile->dylibName));
290       dylibFile->ordinal = dylibOrdinal++;
291     }
292   }
293 
294   // TODO: dyld requires libSystem to be loaded. libSystem is a universal
295   // binary and we don't have support for that yet, so mock it out here.
296   loadCommands.push_back(make<LCLoadDylib>("/usr/lib/libSystem.B.dylib"));
297 }
298 
299 void Writer::scanRelocations() {
300   for (InputSection *sect : inputSections)
301     for (Reloc &r : sect->relocs)
302       if (auto *s = r.target.dyn_cast<Symbol *>())
303         if (auto *dylibSymbol = dyn_cast<DylibSymbol>(s))
304           in.got->addEntry(*dylibSymbol);
305 }
306 
307 void Writer::assignAddresses() {
308   uint64_t addr = ImageBase + sizeof(mach_header_64);
309 
310   uint64_t size = 0;
311   for (LoadCommand *lc : loadCommands)
312     size += lc->getSize();
313   sizeofCmds = size;
314   addr += size;
315 
316   for (OutputSegment *seg : outputSegments) {
317     addr = alignTo(addr, PageSize);
318 
319     for (auto &p : seg->sections) {
320       ArrayRef<InputSection *> sections = p.second;
321       for (InputSection *isec : sections) {
322         addr = alignTo(addr, isec->align);
323         isec->addr = addr;
324         addr += isec->getSize();
325       }
326     }
327   }
328 
329   addr = alignTo(addr, PageSize);
330   linkEditSeg->addr = addr;
331   linkEditSeg->fileOff = addr - ImageBase;
332 }
333 
334 // LC_DYLD_INFO_ONLY contains symbol import/export information. Imported
335 // symbols are described by a sequence of bind opcodes, which allow for a
336 // compact encoding. Exported symbols are described using a trie.
337 void Writer::createDyldInfoContents() {
338   uint64_t sectionStart = linkEditSeg->getOffset();
339   raw_svector_ostream os{linkEditSeg->contents};
340 
341   if (in.got->getSize() != 0) {
342     // Emit bind opcodes, which tell dyld which dylib symbols to load.
343 
344     // Tell dyld to write to the section containing the GOT.
345     os << static_cast<uint8_t>(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB |
346                                in.got->parent->index);
347     encodeULEB128(in.got->addr - in.got->parent->firstSection()->addr, os);
348     for (const DylibSymbol *sym : in.got->getEntries()) {
349       // TODO: Implement compact encoding -- we only need to encode the
350       // differences between consecutive symbol entries.
351       if (sym->file->ordinal <= BIND_IMMEDIATE_MASK) {
352         os << static_cast<uint8_t>(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM |
353                                    sym->file->ordinal);
354       } else {
355         error("TODO: Support larger dylib symbol ordinals");
356         continue;
357       }
358       os << static_cast<uint8_t>(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM)
359          << sym->getName() << '\0'
360          << static_cast<uint8_t>(BIND_OPCODE_SET_TYPE_IMM | BIND_TYPE_POINTER)
361          << static_cast<uint8_t>(BIND_OPCODE_DO_BIND);
362     }
363 
364     os << static_cast<uint8_t>(BIND_OPCODE_DONE);
365 
366     dyldInfoSeg->bindOff = sectionStart;
367     dyldInfoSeg->bindSize = linkEditSeg->getOffset() - sectionStart;
368   }
369 
370   // TODO: emit bind opcodes for lazy symbols.
371   // TODO: Implement symbol export trie.
372 }
373 
374 void Writer::openFile() {
375   Expected<std::unique_ptr<FileOutputBuffer>> bufferOrErr =
376       FileOutputBuffer::create(config->outputFile, fileSize,
377                                FileOutputBuffer::F_executable);
378 
379   if (!bufferOrErr)
380     error("failed to open " + config->outputFile + ": " +
381           llvm::toString(bufferOrErr.takeError()));
382   else
383     buffer = std::move(*bufferOrErr);
384 }
385 
386 void Writer::writeHeader() {
387   auto *hdr = reinterpret_cast<mach_header_64 *>(buffer->getBufferStart());
388   hdr->magic = MH_MAGIC_64;
389   hdr->cputype = CPU_TYPE_X86_64;
390   hdr->cpusubtype = CPU_SUBTYPE_X86_64_ALL | CPU_SUBTYPE_LIB64;
391   hdr->filetype = MH_EXECUTE;
392   hdr->ncmds = loadCommands.size();
393   hdr->sizeofcmds = sizeofCmds;
394   hdr->flags = MH_NOUNDEFS | MH_DYLDLINK | MH_TWOLEVEL;
395 
396   uint8_t *p = reinterpret_cast<uint8_t *>(hdr + 1);
397   for (LoadCommand *lc : loadCommands) {
398     lc->writeTo(p);
399     p += lc->getSize();
400   }
401 }
402 
403 void Writer::writeSections() {
404   uint8_t *buf = buffer->getBufferStart();
405 
406   for (OutputSegment *seg : outputSegments)
407     for (auto &sect : seg->sections)
408       for (InputSection *isec : sect.second)
409         isec->writeTo(buf + isec->addr - ImageBase);
410 
411   memcpy(buf + linkEditSeg->fileOff, linkEditSeg->contents.data(),
412          linkEditSeg->contents.size());
413 }
414 
415 void Writer::run() {
416   createLoadCommands();
417   scanRelocations();
418   assignAddresses();
419 
420   // Fill __LINKEDIT contents
421   createDyldInfoContents();
422   fileSize = linkEditSeg->fileOff + linkEditSeg->contents.size();
423 
424   openFile();
425   if (errorCount())
426     return;
427 
428   writeHeader();
429   writeSections();
430 
431   if (auto e = buffer->commit())
432     error("failed to write to the output file: " + toString(std::move(e)));
433 }
434 
435 void macho::writeResult() { Writer().run(); }
436 
437 void macho::createSyntheticSections() {
438   in.got = make<GotSection>();
439   inputSections.push_back(in.got);
440 }
441