blob: ce0c30d5300b92c6ebb944c9c715abc60937cf8d [file] [log] [blame]
Fangrui Song6acd3002020-04-02 11:54:05 -07001//===- 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 "Target.h"
17
18#include "lld/Common/ErrorHandler.h"
19#include "lld/Common/Memory.h"
20#include "llvm/BinaryFormat/MachO.h"
21#include "llvm/Support/LEB128.h"
22#include "llvm/Support/MathExtras.h"
23
24using namespace llvm;
25using namespace llvm::MachO;
26using namespace llvm::support;
27using namespace lld;
28using namespace lld::macho;
29
30namespace {
31class LCLinkEdit;
32class LCDyldInfo;
33class LCSymtab;
34
35class LoadCommand {
36public:
37 virtual ~LoadCommand() = default;
38 virtual uint32_t getSize() const = 0;
39 virtual void writeTo(uint8_t *buf) const = 0;
40};
41
42class Writer {
43public:
44 Writer() : buffer(errorHandler().outputBuffer) {}
45
46 void createLoadCommands();
47 void assignAddresses();
48
49 void openFile();
50 void writeHeader();
51 void writeSections();
52
53 void run();
54
55 std::vector<LoadCommand *> loadCommands;
56 std::unique_ptr<FileOutputBuffer> &buffer;
57 uint64_t fileSize = 0;
58 uint64_t sizeofCmds = 0;
59 LCLinkEdit *linkEditSeg = nullptr;
60 LCDyldInfo *dyldInfoSeg = nullptr;
61 LCSymtab *symtabSeg = nullptr;
62};
63
64class LCPagezero : public LoadCommand {
65public:
66 uint32_t getSize() const override { return sizeof(segment_command_64); }
67
68 void writeTo(uint8_t *buf) const override {
69 auto *c = reinterpret_cast<segment_command_64 *>(buf);
70 c->cmd = LC_SEGMENT_64;
71 c->cmdsize = getSize();
72 strcpy(c->segname, "__PAGEZERO");
73 c->vmsize = PageSize;
74 }
75};
76
77class LCLinkEdit : public LoadCommand {
78public:
79 uint32_t getSize() const override { return sizeof(segment_command_64); }
80
81 void writeTo(uint8_t *buf) const override {
82 auto *c = reinterpret_cast<segment_command_64 *>(buf);
83 c->cmd = LC_SEGMENT_64;
84 c->cmdsize = getSize();
85 strcpy(c->segname, "__LINKEDIT");
86 c->fileoff = fileOff;
87 c->filesize = contents.size();
88 c->maxprot = VM_PROT_READ | VM_PROT_WRITE;
89 c->initprot = VM_PROT_READ;
90 }
91
92 uint64_t getOffset() const { return fileOff + contents.size(); }
93
94 uint64_t fileOff = 0;
95 SmallVector<char, 128> contents;
96};
97
98class LCDyldInfo : public LoadCommand {
99public:
100 uint32_t getSize() const override { return sizeof(dyld_info_command); }
101
102 void writeTo(uint8_t *buf) const override {
103 auto *c = reinterpret_cast<dyld_info_command *>(buf);
104 c->cmd = LC_DYLD_INFO_ONLY;
105 c->cmdsize = getSize();
106 c->export_off = exportOff;
107 c->export_size = exportSize;
108 }
109
110 uint64_t exportOff = 0;
111 uint64_t exportSize = 0;
112};
113
114class LCDysymtab : public LoadCommand {
115public:
116 uint32_t getSize() const override { return sizeof(dysymtab_command); }
117
118 void writeTo(uint8_t *buf) const override {
119 auto *c = reinterpret_cast<dysymtab_command *>(buf);
120 c->cmd = LC_DYSYMTAB;
121 c->cmdsize = getSize();
122 }
123};
124
125class LCSegment : public LoadCommand {
126public:
127 LCSegment(StringRef name, OutputSegment *seg) : name(name), seg(seg) {}
128
129 uint32_t getSize() const override {
130 return sizeof(segment_command_64) +
131 seg->sections.size() * sizeof(section_64);
132 }
133
134 void writeTo(uint8_t *buf) const override {
135 auto *c = reinterpret_cast<segment_command_64 *>(buf);
136 buf += sizeof(segment_command_64);
137
138 c->cmd = LC_SEGMENT_64;
139 c->cmdsize = getSize();
140 memcpy(c->segname, name.data(), name.size());
141
142 InputSection *firstSec = seg->sections.front().second[0];
143 InputSection *lastSec = seg->sections.back().second.back();
144
145 // dyld3's MachOLoaded::getSlide() assumes that the __TEXT segment starts
146 // from the beginning of the file (i.e. the header).
147 // TODO: replace this logic by creating a synthetic __TEXT,__mach_header
148 // section instead.
149 c->fileoff = name == "__TEXT" ? 0 : firstSec->addr - ImageBase;
150 c->vmaddr = c->fileoff + ImageBase;
151 c->vmsize = c->filesize = lastSec->addr + lastSec->data.size() - c->vmaddr;
152 c->maxprot = VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE;
153 c->initprot = seg->perms;
154 c->nsects = seg->sections.size();
155
156 for (auto &p : seg->sections) {
157 StringRef s = p.first;
158 std::vector<InputSection *> &sections = p.second;
159
160 auto *sectHdr = reinterpret_cast<section_64 *>(buf);
161 buf += sizeof(section_64);
162
163 memcpy(sectHdr->sectname, s.data(), s.size());
164 memcpy(sectHdr->segname, name.data(), name.size());
165
166 sectHdr->addr = sections[0]->addr;
167 sectHdr->offset = sections[0]->addr - ImageBase;
168 sectHdr->align = sections[0]->align;
169 uint32_t maxAlign = 0;
170 for (const InputSection *section : sections)
171 maxAlign = std::max(maxAlign, section->align);
172 sectHdr->align = Log2_32(maxAlign);
173 sectHdr->flags = sections[0]->flags;
174 sectHdr->size = sections.back()->addr + sections.back()->data.size() -
175 sections[0]->addr;
176 }
177 }
178
179private:
180 StringRef name;
181 OutputSegment *seg;
182};
183
184class LCMain : public LoadCommand {
185 uint32_t getSize() const override { return sizeof(entry_point_command); }
186
187 void writeTo(uint8_t *buf) const override {
188 auto *c = reinterpret_cast<entry_point_command *>(buf);
189 c->cmd = LC_MAIN;
190 c->cmdsize = getSize();
191 c->entryoff = config->entry->getVA();
192 c->stacksize = 0;
193 }
194};
195
196class LCSymtab : public LoadCommand {
197public:
198 uint32_t getSize() const override { return sizeof(symtab_command); }
199
200 void writeTo(uint8_t *buf) const override {
201 auto *c = reinterpret_cast<symtab_command *>(buf);
202 c->cmd = LC_SYMTAB;
203 c->cmdsize = getSize();
204 }
205};
206
207class LCLoadDylib : public LoadCommand {
208public:
209 LCLoadDylib(StringRef path) : path(path) {}
210
211 uint32_t getSize() const override {
212 return alignTo(sizeof(dylib_command) + path.size() + 1, 8);
213 }
214
215 void writeTo(uint8_t *buf) const override {
216 auto *c = reinterpret_cast<dylib_command *>(buf);
217 buf += sizeof(dylib_command);
218
219 c->cmd = LC_LOAD_DYLIB;
220 c->cmdsize = getSize();
221 c->dylib.name = sizeof(dylib_command);
222
223 memcpy(buf, path.data(), path.size());
224 buf[path.size()] = '\0';
225 }
226
227private:
228 StringRef path;
229};
230
231class LCLoadDylinker : public LoadCommand {
232public:
233 uint32_t getSize() const override {
234 return alignTo(sizeof(dylinker_command) + path.size() + 1, 8);
235 }
236
237 void writeTo(uint8_t *buf) const override {
238 auto *c = reinterpret_cast<dylinker_command *>(buf);
239 buf += sizeof(dylinker_command);
240
241 c->cmd = LC_LOAD_DYLINKER;
242 c->cmdsize = getSize();
243 c->name = sizeof(dylinker_command);
244
245 memcpy(buf, path.data(), path.size());
246 buf[path.size()] = '\0';
247 }
248
249private:
250 // Recent versions of Darwin won't run any binary that has dyld at a
251 // different location.
252 const StringRef path = "/usr/lib/dyld";
253};
254} // namespace
255
256void Writer::createLoadCommands() {
257 linkEditSeg = make<LCLinkEdit>();
258 dyldInfoSeg = make<LCDyldInfo>();
259 symtabSeg = make<LCSymtab>();
260
261 loadCommands.push_back(linkEditSeg);
262 loadCommands.push_back(dyldInfoSeg);
263 loadCommands.push_back(symtabSeg);
264 loadCommands.push_back(make<LCPagezero>());
265 loadCommands.push_back(make<LCLoadDylinker>());
266 loadCommands.push_back(make<LCDysymtab>());
267 loadCommands.push_back(make<LCMain>());
268 // TODO: dyld requires libSystem to be loaded. libSystem is a universal
269 // binary and we don't have support for that yet, so mock it out here.
270 loadCommands.push_back(make<LCLoadDylib>("/usr/lib/libSystem.B.dylib"));
271
272 for (OutputSegment *seg : outputSegments)
273 if (!seg->sections.empty())
274 loadCommands.push_back(make<LCSegment>(seg->name, seg));
275}
276
277void Writer::assignAddresses() {
278 uint64_t addr = ImageBase + sizeof(mach_header_64);
279
280 uint64_t size = 0;
281 for (LoadCommand *lc : loadCommands)
282 size += lc->getSize();
283 sizeofCmds = size;
284 addr += size;
285
286 for (OutputSegment *seg : outputSegments) {
287 addr = alignTo(addr, PageSize);
288
289 for (auto &p : seg->sections) {
290 ArrayRef<InputSection *> sections = p.second;
291 for (InputSection *isec : sections) {
292 addr = alignTo(addr, isec->align);
293 isec->addr = addr;
294 addr += isec->data.size();
295 }
296 }
297 }
298
299 linkEditSeg->fileOff = addr - ImageBase;
300}
301
302void Writer::openFile() {
303 Expected<std::unique_ptr<FileOutputBuffer>> bufferOrErr =
304 FileOutputBuffer::create(config->outputFile, fileSize,
305 FileOutputBuffer::F_executable);
306
307 if (!bufferOrErr)
308 error("failed to open " + config->outputFile + ": " +
309 llvm::toString(bufferOrErr.takeError()));
310 else
311 buffer = std::move(*bufferOrErr);
312}
313
314void Writer::writeHeader() {
315 auto *hdr = reinterpret_cast<mach_header_64 *>(buffer->getBufferStart());
316 hdr->magic = MH_MAGIC_64;
317 hdr->cputype = CPU_TYPE_X86_64;
318 hdr->cpusubtype = CPU_SUBTYPE_X86_64_ALL | CPU_SUBTYPE_LIB64;
319 hdr->filetype = MH_EXECUTE;
320 hdr->ncmds = loadCommands.size();
321 hdr->sizeofcmds = sizeofCmds;
322 hdr->flags = MH_NOUNDEFS | MH_DYLDLINK | MH_TWOLEVEL;
323
324 uint8_t *p = reinterpret_cast<uint8_t *>(hdr + 1);
325 for (LoadCommand *lc : loadCommands) {
326 lc->writeTo(p);
327 p += lc->getSize();
328 }
329}
330
331void Writer::writeSections() {
332 uint8_t *buf = buffer->getBufferStart();
333
334 for (OutputSegment *seg : outputSegments)
335 for (auto &sect : seg->sections)
336 for (InputSection *isec : sect.second)
337 isec->writeTo(buf + isec->addr - ImageBase);
338
339 memcpy(buf + linkEditSeg->fileOff, linkEditSeg->contents.data(),
340 linkEditSeg->contents.size());
341}
342
343void Writer::run() {
344 createLoadCommands();
345 assignAddresses();
346 fileSize = linkEditSeg->fileOff + linkEditSeg->contents.size();
347
348 openFile();
349 if (errorCount())
350 return;
351
352 writeHeader();
353 writeSections();
354
355 if (auto e = buffer->commit())
356 error("failed to write to the output file: " + toString(std::move(e)));
357}
358
359void macho::writeResult() { Writer().run(); }