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 "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 24 using namespace llvm; 25 using namespace llvm::MachO; 26 using namespace llvm::support; 27 using namespace lld; 28 using namespace lld::macho; 29 30 namespace { 31 class LCLinkEdit; 32 class LCDyldInfo; 33 class LCSymtab; 34 35 class LoadCommand { 36 public: 37 virtual ~LoadCommand() = default; 38 virtual uint32_t getSize() const = 0; 39 virtual void writeTo(uint8_t *buf) const = 0; 40 }; 41 42 class Writer { 43 public: 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 64 class LCPagezero : public LoadCommand { 65 public: 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 77 class LCLinkEdit : public LoadCommand { 78 public: 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 98 class LCDyldInfo : public LoadCommand { 99 public: 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 114 class LCDysymtab : public LoadCommand { 115 public: 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 125 class LCSegment : public LoadCommand { 126 public: 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 *> §ions = 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 179 private: 180 StringRef name; 181 OutputSegment *seg; 182 }; 183 184 class 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 196 class LCSymtab : public LoadCommand { 197 public: 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 207 class LCLoadDylib : public LoadCommand { 208 public: 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 227 private: 228 StringRef path; 229 }; 230 231 class LCLoadDylinker : public LoadCommand { 232 public: 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 249 private: 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 256 void 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 277 void 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 302 void 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 314 void 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 331 void Writer::writeSections() { 332 uint8_t *buf = buffer->getBufferStart(); 333 334 for (OutputSegment *seg : outputSegments) 335 for (auto § : 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 343 void 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 359 void macho::writeResult() { Writer().run(); } 360