blob: 4f46c83bfd8c61d5ea93eff3e1844b28e8afce97 [file] [log] [blame]
Nick Kledzike34182f2013-11-06 21:36:55 +00001//===- lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp ---------===//
2//
3// The LLVM Linker
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10///
11/// \file For mach-o object files, this implementation converts normalized
12/// mach-o in memory to mach-o binary on disk.
13///
14/// +---------------+
15/// | binary mach-o |
16/// +---------------+
17/// ^
18/// |
19/// |
20/// +------------+
21/// | normalized |
22/// +------------+
23
24#include "MachONormalizedFile.h"
25#include "MachONormalizedFileBinaryUtils.h"
26
27#include "lld/Core/Error.h"
28#include "lld/Core/LLVM.h"
29
30#include "llvm/ADT/SmallString.h"
31#include "llvm/ADT/SmallVector.h"
32#include "llvm/ADT/StringRef.h"
33#include "llvm/Support/Casting.h"
34#include "llvm/Support/Debug.h"
35#include "llvm/Support/ErrorHandling.h"
36#include "llvm/Support/FileOutputBuffer.h"
37#include "llvm/Support/Host.h"
38#include "llvm/Support/MachO.h"
39#include "llvm/Support/MemoryBuffer.h"
40#include "llvm/Support/raw_ostream.h"
41#include "llvm/Support/system_error.h"
42
43#include <functional>
44#include <map>
45
46using namespace llvm::MachO;
47
48namespace lld {
49namespace mach_o {
50namespace normalized {
51
52/// Utility class for writing a mach-o binary file given an in-memory
53/// normalized file.
54class MachOFileLayout {
55public:
56 /// All layout computation is done in the constructor.
57 MachOFileLayout(const NormalizedFile &file);
58
59 /// Returns the final file size as computed in the constructor.
60 size_t size() const;
61
62 /// Writes the normalized file as a binary mach-o file to the specified
63 /// path. This does not have a stream interface because the generated
64 /// file may need the 'x' bit set.
65 error_code writeBinary(StringRef path);
66
67private:
68 uint32_t loadCommandsSize(uint32_t &count);
69 void buildFileOffsets();
70 void writeMachHeader();
71 error_code writeLoadCommands();
72 void writeSectionContent();
73 void writeRelocations();
74 void writeSymbolTable();
75 void writeRebaseInfo();
76 void writeBindingInfo();
77 void writeLazyBindingInfo();
78 void writeLinkEditContent();
79 void buildLinkEditInfo();
80 void buildRebaseInfo();
81 void buildBindInfo();
82 void buildLazyBindInfo();
83 void computeSymbolTableSizes();
84 void buildSectionRelocations();
85 void appendSymbols(const std::vector<Symbol> &symbols,
86 uint32_t &symOffset, uint32_t &strOffset);
87 uint32_t indirectSymbolIndex(const Section &sect, uint32_t &index);
88 uint32_t indirectSymbolElementSize(const Section &sect);
89
Nick Kledzik29f749e2013-11-09 00:07:28 +000090 // For use as template parameter to load command methods.
91 struct MachO64Trait {
92 typedef llvm::MachO::segment_command_64 command;
93 typedef llvm::MachO::section_64 section;
94 enum { LC = llvm::MachO::LC_SEGMENT_64 };
95 };
96
97 // For use as template parameter to load command methods.
98 struct MachO32Trait {
99 typedef llvm::MachO::segment_command command;
100 typedef llvm::MachO::section section;
101 enum { LC = llvm::MachO::LC_SEGMENT };
102 };
Nick Kledzike34182f2013-11-06 21:36:55 +0000103
Nick Kledzik29f749e2013-11-09 00:07:28 +0000104 template <typename T>
105 error_code writeSingleSegmentLoadCommand(uint8_t *&lc);
106 template <typename T>
107 error_code writeSegmentLoadCommands(uint8_t *&lc);
108
Nick Kledzike34182f2013-11-06 21:36:55 +0000109 uint32_t pointerAlign(uint32_t value);
110 static StringRef dyldPath();
111
112 class ByteBuffer {
113 public:
114 ByteBuffer();
115 void append_byte(uint8_t);
116 void append_uleb128(uint64_t);
117 void append_sleb128(int64_t);
118 void append_string(StringRef);
119 void align(unsigned);
120 size_t size();
121 const uint8_t *bytes();
122 private:
123 std::vector<uint8_t> _bytes;
124 };
125
126 struct SegExtraInfo {
127 uint32_t fileOffset;
128 std::vector<const Section*> sections;
129 };
130 typedef std::map<const Segment*, SegExtraInfo> SegMap;
131 struct SectionExtraInfo {
132 uint32_t fileOffset;
133 };
134 typedef std::map<const Section*, SectionExtraInfo> SectionMap;
135
136 const NormalizedFile &_file;
137 error_code _ec;
138 uint8_t *_buffer;
139 const bool _is64;
140 const bool _swap;
141 const bool _bigEndianArch;
142 uint64_t _seg1addr;
143 uint32_t _startOfLoadCommands;
144 uint32_t _countOfLoadCommands;
145 uint32_t _endOfLoadCommands;
146 uint32_t _startOfRelocations;
147 uint32_t _startOfSymbols;
148 uint32_t _startOfIndirectSymbols;
149 uint32_t _startOfSymbolStrings;
150 uint32_t _endOfSymbolStrings;
151 uint32_t _symbolTableLocalsStartIndex;
152 uint32_t _symbolTableGlobalsStartIndex;
153 uint32_t _symbolTableUndefinesStartIndex;
154 uint32_t _symbolStringPoolSize;
155 uint32_t _symbolTableSize;
156 uint32_t _indirectSymbolTableCount;
157 // Used in object file creation only
158 uint32_t _startOfSectionsContent;
159 uint32_t _endOfSectionsContent;
160 // Used in final linked image only
161 uint32_t _startOfLinkEdit;
162 uint32_t _startOfRebaseInfo;
163 uint32_t _endOfRebaseInfo;
164 uint32_t _startOfBindingInfo;
165 uint32_t _endOfBindingInfo;
166 uint32_t _startOfLazyBindingInfo;
167 uint32_t _endOfLazyBindingInfo;
168 uint32_t _endOfLinkEdit;
169 uint64_t _addressOfLinkEdit;
170 SegMap _segInfo;
171 SectionMap _sectInfo;
172 ByteBuffer _rebaseInfo;
173 ByteBuffer _bindingInfo;
174 ByteBuffer _lazyBindingInfo;
175 ByteBuffer _weakBindingInfo;
176 ByteBuffer _exportInfo;
177};
178
179size_t headerAndLoadCommandsSize(const NormalizedFile &file) {
180 MachOFileLayout layout(file);
181 return layout.size();
182}
183
184StringRef MachOFileLayout::dyldPath() {
185 return "/usr/lib/dyld";
186}
187
188uint32_t MachOFileLayout::pointerAlign(uint32_t value) {
189 return llvm::RoundUpToAlignment(value, _is64 ? 8 : 4);
190}
191
192
193MachOFileLayout::ByteBuffer::ByteBuffer() {
194 _bytes.reserve(256);
195}
196
197void MachOFileLayout::ByteBuffer::append_byte(uint8_t b) {
198 _bytes.push_back(b);
199}
200
201
202void MachOFileLayout::ByteBuffer::append_uleb128(uint64_t value) {
203 uint8_t byte;
204 do {
205 byte = value & 0x7F;
206 value &= ~0x7F;
207 if ( value != 0 )
208 byte |= 0x80;
209 _bytes.push_back(byte);
210 value = value >> 7;
211 } while( byte >= 0x80 );
212}
213
214void MachOFileLayout::ByteBuffer::append_sleb128(int64_t value) {
215 bool isNeg = ( value < 0 );
216 uint8_t byte;
217 bool more;
218 do {
219 byte = value & 0x7F;
220 value = value >> 7;
221 if ( isNeg )
222 more = ( (value != -1) || ((byte & 0x40) == 0) );
223 else
224 more = ( (value != 0) || ((byte & 0x40) != 0) );
225 if ( more )
226 byte |= 0x80;
227 _bytes.push_back(byte);
228 }
229 while( more );
230}
231
232void MachOFileLayout::ByteBuffer::append_string(StringRef str) {
233 _bytes.insert(_bytes.end(), str.begin(), str.end());
234 _bytes.push_back('\0');
235}
236
237void MachOFileLayout::ByteBuffer::align(unsigned alignment) {
238 while ( (_bytes.size() % alignment) != 0 )
239 _bytes.push_back(0);
240}
241
242const uint8_t *MachOFileLayout::ByteBuffer::bytes() {
243 return &_bytes[0];
244}
245
246size_t MachOFileLayout::ByteBuffer::size() {
247 return _bytes.size();
248}
249
250
251
252
253MachOFileLayout::MachOFileLayout(const NormalizedFile &file)
254 : _file(file),
255 _is64(MachOLinkingContext::is64Bit(file.arch)),
256 _swap(!MachOLinkingContext::isHostEndian(file.arch)),
257 _bigEndianArch(MachOLinkingContext::isBigEndian(file.arch)),
258 _seg1addr(INT64_MAX) {
259 _startOfLoadCommands = _is64 ? sizeof(mach_header_64) : sizeof(mach_header);
260 const size_t segCommandBaseSize =
261 (_is64 ? sizeof(segment_command_64) : sizeof(segment_command));
262 const size_t sectsSize = (_is64 ? sizeof(section_64) : sizeof(section));
263 if (file.fileType == llvm::MachO::MH_OBJECT) {
264 // object files have just one segment load command containing all sections
265 _endOfLoadCommands = _startOfLoadCommands
266 + segCommandBaseSize
267 + file.sections.size() * sectsSize
268 + sizeof(symtab_command);
269 _countOfLoadCommands = 2;
270
271 // Accumulate size of each section.
272 _startOfSectionsContent = _endOfLoadCommands;
273 _endOfSectionsContent = _startOfSectionsContent;
274 unsigned relocCount = 0;
275 for (const Section &sect : file.sections) {
276 _sectInfo[&sect].fileOffset = _endOfSectionsContent;
277 _endOfSectionsContent += sect.content.size();
278 relocCount += sect.relocations.size();
279 }
280
281 computeSymbolTableSizes();
282
283 // Align start of relocations.
284 _startOfRelocations = pointerAlign(_endOfSectionsContent);
285 _startOfSymbols = _startOfRelocations + relocCount * 8;
286 // Add Indirect symbol table.
287 _startOfIndirectSymbols = _startOfSymbols + _symbolTableSize;
288 // Align start of symbol table and symbol strings.
289 _startOfSymbolStrings = _startOfIndirectSymbols
290 + pointerAlign(_indirectSymbolTableCount * sizeof(uint32_t));
291 _endOfSymbolStrings = _startOfSymbolStrings
292 + pointerAlign(_symbolStringPoolSize);
293 _endOfLinkEdit = _endOfSymbolStrings;
294 DEBUG_WITH_TYPE("MachOFileLayout",
295 llvm::dbgs() << "MachOFileLayout()\n"
296 << " startOfLoadCommands=" << _startOfLoadCommands << "\n"
297 << " countOfLoadCommands=" << _countOfLoadCommands << "\n"
298 << " endOfLoadCommands=" << _endOfLoadCommands << "\n"
299 << " startOfRelocations=" << _startOfRelocations << "\n"
300 << " startOfSymbols=" << _startOfSymbols << "\n"
301 << " startOfSymbolStrings=" << _startOfSymbolStrings << "\n"
302 << " endOfSymbolStrings=" << _endOfSymbolStrings << "\n"
303 << " startOfSectionsContent=" << _startOfSectionsContent << "\n"
304 << " endOfSectionsContent=" << _endOfSectionsContent << "\n");
305 } else {
306 // Final linked images have one load command per segment.
307 _endOfLoadCommands = _startOfLoadCommands
308 + loadCommandsSize(_countOfLoadCommands);
309
310 // Assign section file offsets.
311 buildFileOffsets();
312 buildLinkEditInfo();
313
314 // LINKEDIT of final linked images has in order:
315 // rebase info, binding info, lazy binding info, weak binding info,
316 // indirect symbol table, symbol table, symbol table strings.
317 _startOfRebaseInfo = _startOfLinkEdit;
318 _endOfRebaseInfo = _startOfRebaseInfo + _rebaseInfo.size();
319 _startOfBindingInfo = _endOfRebaseInfo;
320 _endOfBindingInfo = _startOfBindingInfo + _bindingInfo.size();
321 _startOfLazyBindingInfo = _endOfBindingInfo;
322 _endOfLazyBindingInfo = _startOfLazyBindingInfo + _lazyBindingInfo.size();
323
324 _startOfSymbols = _endOfLazyBindingInfo;
325 _startOfIndirectSymbols = _startOfSymbols + _symbolTableSize;
326 _startOfSymbolStrings = _startOfIndirectSymbols
327 + pointerAlign(_indirectSymbolTableCount * sizeof(uint32_t));
328 _endOfSymbolStrings = _startOfSymbolStrings
329 + pointerAlign(_symbolStringPoolSize);
330 _endOfLinkEdit = _endOfSymbolStrings;
331 DEBUG_WITH_TYPE("MachOFileLayout",
332 llvm::dbgs() << "MachOFileLayout()\n"
333 << " startOfLoadCommands=" << _startOfLoadCommands << "\n"
334 << " countOfLoadCommands=" << _countOfLoadCommands << "\n"
335 << " endOfLoadCommands=" << _endOfLoadCommands << "\n"
336 << " startOfLinkEdit=" << _startOfLinkEdit << "\n"
337 << " startOfRebaseInfo=" << _startOfRebaseInfo << "\n"
338 << " endOfRebaseInfo=" << _endOfRebaseInfo << "\n"
339 << " startOfBindingInfo=" << _startOfBindingInfo << "\n"
340 << " endOfBindingInfo=" << _endOfBindingInfo << "\n"
341 << " startOfLazyBindingInfo=" << _startOfLazyBindingInfo << "\n"
342 << " endOfLazyBindingInfo=" << _endOfLazyBindingInfo << "\n"
343 << " startOfSymbols=" << _startOfSymbols << "\n"
344 << " startOfSymbolStrings=" << _startOfSymbolStrings << "\n"
345 << " endOfSymbolStrings=" << _endOfSymbolStrings << "\n"
346 << " addressOfLinkEdit=" << _addressOfLinkEdit << "\n");
347 }
348}
349
350uint32_t MachOFileLayout::loadCommandsSize(uint32_t &count) {
351 uint32_t size = 0;
352 count = 0;
353
354 const size_t segCommandSize =
355 (_is64 ? sizeof(segment_command_64) : sizeof(segment_command));
356 const size_t sectionSize = (_is64 ? sizeof(section_64) : sizeof(section));
357
358 // Add LC_SEGMENT for each segment.
359 size += _file.segments.size() * segCommandSize;
360 count += _file.segments.size();
361 // Add section record for each section.
362 size += _file.sections.size() * sectionSize;
363 // Add one LC_SEGMENT for implicit __LINKEDIT segment
364 size += segCommandSize;
365 ++count;
366
367 // Add LC_DYLD_INFO
368 size += sizeof(dyld_info_command);
369 ++count;
370
371 // Add LC_SYMTAB
372 size += sizeof(symtab_command);
373 ++count;
374
375 // Add LC_DYSYMTAB
376 if (_file.fileType != llvm::MachO::MH_PRELOAD) {
377 size += sizeof(dysymtab_command);
378 ++count;
379 }
380
381 // If main executable add LC_LOAD_DYLINKER and LC_MAIN
382 if (_file.fileType == llvm::MachO::MH_EXECUTE) {
383 size += pointerAlign(sizeof(dylinker_command) + dyldPath().size()+1);
384 ++count;
385 size += sizeof(entry_point_command);
386 ++count;
387 }
388
389 // Add LC_LOAD_DYLIB for each dependent dylib.
390 for (const DependentDylib &dep : _file.dependentDylibs) {
391 size += sizeof(dylib_command) + pointerAlign(dep.path.size()+1);
392 ++count;
393 }
394
395 return size;
396}
397
398static bool overlaps(const Segment &s1, const Segment &s2) {
399 if (s2.address >= s1.address+s1.size)
400 return false;
401 if (s1.address >= s2.address+s2.size)
402 return false;
403 return true;
404}
405
406static bool overlaps(const Section &s1, const Section &s2) {
407 if (s2.address >= s1.address+s1.content.size())
408 return false;
409 if (s1.address >= s2.address+s2.content.size())
410 return false;
411 return true;
412}
413
414void MachOFileLayout::buildFileOffsets() {
415 // Verify no segments overlap
416 for (const Segment &sg1 : _file.segments) {
417 for (const Segment &sg2 : _file.segments) {
418 if (&sg1 == &sg2)
419 continue;
420 if (overlaps(sg1,sg2)) {
421 _ec = llvm::make_error_code(llvm::errc::executable_format_error);
422 return;
423 }
424 }
425 }
426
427 // Verify no sections overlap
428 for (const Section &s1 : _file.sections) {
429 for (const Section &s2 : _file.sections) {
430 if (&s1 == &s2)
431 continue;
432 if (overlaps(s1,s2)) {
433 _ec = llvm::make_error_code(llvm::errc::executable_format_error);
434 return;
435 }
436 }
437 }
438
439 // Build side table of extra info about segments and sections.
440 SegExtraInfo t;
441 t.fileOffset = 0;
442 for (const Segment &sg : _file.segments) {
443 _segInfo[&sg] = t;
444 }
445 SectionExtraInfo t2;
446 t2.fileOffset = 0;
447 // Assign sections to segments.
448 for (const Section &s : _file.sections) {
449 _sectInfo[&s] = t2;
450 for (const Segment &sg : _file.segments) {
451 if ((s.address >= sg.address)
452 && (s.address+s.content.size() <= sg.address+sg.size)) {
453 if (!sg.name.equals(s.segmentName)) {
454 _ec = llvm::make_error_code(llvm::errc::executable_format_error);
455 return;
456 }
457 _segInfo[&sg].sections.push_back(&s);
458 }
459 }
460 }
461
462 // Assign file offsets.
463 uint32_t fileOffset = 0;
464 DEBUG_WITH_TYPE("MachOFileLayout",
465 llvm::dbgs() << "buildFileOffsets()\n");
466 for (const Segment &sg : _file.segments) {
467 // FIXME: 4096 should be infered from segments in normalized file.
468 _segInfo[&sg].fileOffset = llvm::RoundUpToAlignment(fileOffset, 4096);
469 if ((_seg1addr == INT64_MAX) && sg.access)
470 _seg1addr = sg.address;
471 DEBUG_WITH_TYPE("MachOFileLayout",
472 llvm::dbgs() << " segment=" << sg.name
473 << ", fileOffset=" << _segInfo[&sg].fileOffset << "\n");
474 for (const Section *s : _segInfo[&sg].sections) {
475 fileOffset = s->address - sg.address + _segInfo[&sg].fileOffset;
476 _sectInfo[s].fileOffset = fileOffset;
477 DEBUG_WITH_TYPE("MachOFileLayout",
478 llvm::dbgs() << " section=" << s->sectionName
479 << ", fileOffset=" << fileOffset << "\n");
480 }
481 _addressOfLinkEdit = sg.address + sg.size;
482 }
483 _startOfLinkEdit = llvm::RoundUpToAlignment(fileOffset, 4096);
484}
485
486
487size_t MachOFileLayout::size() const {
488 return _endOfSymbolStrings;
489}
490
491void MachOFileLayout::writeMachHeader() {
492 mach_header *mh = reinterpret_cast<mach_header*>(_buffer);
493 mh->magic = _is64 ? llvm::MachO::MH_MAGIC_64 : llvm::MachO::MH_MAGIC;
494 mh->cputype = MachOLinkingContext::cpuTypeFromArch(_file.arch);
495 mh->cpusubtype = MachOLinkingContext::cpuSubtypeFromArch(_file.arch);
496 mh->filetype = _file.fileType;
497 mh->ncmds = _countOfLoadCommands;
498 mh->sizeofcmds = _endOfLoadCommands - _startOfLoadCommands;
499 mh->flags = _file.flags;
500 if (_swap)
501 swapStruct(*mh);
502}
503
504uint32_t MachOFileLayout::indirectSymbolIndex(const Section &sect,
505 uint32_t &index) {
506 if (sect.indirectSymbols.empty())
507 return 0;
508 uint32_t result = index;
509 index += sect.indirectSymbols.size();
510 return result;
511}
512
513uint32_t MachOFileLayout::indirectSymbolElementSize(const Section &sect) {
514 if (sect.indirectSymbols.empty())
515 return 0;
516 if (sect.type != S_SYMBOL_STUBS)
517 return 0;
518 return sect.content.size() / sect.indirectSymbols.size();
519}
520
Nick Kledzike34182f2013-11-06 21:36:55 +0000521
Nick Kledzik29f749e2013-11-09 00:07:28 +0000522
523template <typename T>
524error_code MachOFileLayout::writeSingleSegmentLoadCommand(uint8_t *&lc) {
525 typename T::command* seg = reinterpret_cast<typename T::command*>(lc);
526 seg->cmd = T::LC;
527 seg->cmdsize = sizeof(typename T::command)
528 + _file.sections.size() * sizeof(typename T::section);
Nick Kledzike34182f2013-11-06 21:36:55 +0000529 uint8_t *next = lc + seg->cmdsize;
530 memset(seg->segname, 0, 16);
531 seg->vmaddr = 0;
532 seg->vmsize = _endOfSectionsContent - _endOfLoadCommands;
533 seg->fileoff = _endOfLoadCommands;
534 seg->filesize = seg->vmsize;
535 seg->maxprot = VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE;
536 seg->initprot = VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE;
537 seg->nsects = _file.sections.size();
538 seg->flags = 0;
539 if (_swap)
540 swapStruct(*seg);
Nick Kledzik29f749e2013-11-09 00:07:28 +0000541 typename T::section *sout = reinterpret_cast<typename T::section*>
542 (lc+sizeof(typename T::command));
Nick Kledzike34182f2013-11-06 21:36:55 +0000543 uint32_t relOffset = _startOfRelocations;
544 uint32_t contentOffset = _startOfSectionsContent;
545 uint32_t indirectSymRunningIndex = 0;
546 for (const Section &sin : _file.sections) {
547 setString16(sin.sectionName, sout->sectname);
548 setString16(sin.segmentName, sout->segname);
549 sout->addr = sin.address;
550 sout->size = sin.content.size();
551 sout->offset = contentOffset;
552 sout->align = sin.alignment;
553 sout->reloff = sin.relocations.empty() ? 0 : relOffset;
554 sout->nreloc = sin.relocations.size();
555 sout->flags = sin.type | sin.attributes;
556 sout->reserved1 = indirectSymbolIndex(sin, indirectSymRunningIndex);
557 sout->reserved2 = indirectSymbolElementSize(sin);
558 relOffset += sin.relocations.size() * sizeof(any_relocation_info);
559 contentOffset += sin.content.size();
560 if (_swap)
561 swapStruct(*sout);
562 ++sout;
563 }
564 lc = next;
565 return error_code::success();
566}
567
568
Nick Kledzik29f749e2013-11-09 00:07:28 +0000569template <typename T>
570error_code MachOFileLayout::writeSegmentLoadCommands(uint8_t *&lc) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000571 uint32_t indirectSymRunningIndex = 0;
572 for (const Segment &seg : _file.segments) {
573 // Write segment command with trailing sections.
574 SegExtraInfo &segInfo = _segInfo[&seg];
Nick Kledzik29f749e2013-11-09 00:07:28 +0000575 typename T::command* cmd = reinterpret_cast<typename T::command*>(lc);
576 cmd->cmd = T::LC;
577 cmd->cmdsize = sizeof(typename T::command)
578 + segInfo.sections.size() * sizeof(typename T::section);
Nick Kledzike34182f2013-11-06 21:36:55 +0000579 uint8_t *next = lc + cmd->cmdsize;
580 setString16(seg.name, cmd->segname);
581 cmd->vmaddr = seg.address;
582 cmd->vmsize = seg.size;
583 cmd->fileoff = segInfo.fileOffset;
Nick Kledzik29f749e2013-11-09 00:07:28 +0000584 cmd->filesize = seg.access ? seg.size : Hex64(0);
Nick Kledzike34182f2013-11-06 21:36:55 +0000585 cmd->maxprot = seg.access;
586 cmd->initprot = seg.access;
587 cmd->nsects = segInfo.sections.size();
588 cmd->flags = 0;
589 if (_swap)
590 swapStruct(*cmd);
Nick Kledzik29f749e2013-11-09 00:07:28 +0000591 typename T::section *sect = reinterpret_cast<typename T::section*>
592 (lc+sizeof(typename T::command));
Nick Kledzike34182f2013-11-06 21:36:55 +0000593 for (const Section *section : segInfo.sections) {
594 setString16(section->sectionName, sect->sectname);
595 setString16(section->segmentName, sect->segname);
596 sect->addr = section->address;
597 sect->size = section->content.size();
598 sect->offset = section->address - seg.address + segInfo.fileOffset;
599 sect->align = section->alignment;
600 sect->reloff = 0;
601 sect->nreloc = 0;
602 sect->flags = section->type | section->attributes;
603 sect->reserved1 = indirectSymbolIndex(*section, indirectSymRunningIndex);
604 sect->reserved2 = indirectSymbolElementSize(*section);
605 if (_swap)
606 swapStruct(*sect);
607 ++sect;
608 }
609 lc = reinterpret_cast<uint8_t*>(next);
610 }
611 // Add implicit __LINKEDIT segment
Nick Kledzik29f749e2013-11-09 00:07:28 +0000612 typename T::command* cmd = reinterpret_cast<typename T::command*>(lc);
613 cmd->cmd = T::LC;
614 cmd->cmdsize = sizeof(typename T::command);
Nick Kledzike34182f2013-11-06 21:36:55 +0000615 uint8_t *next = lc + cmd->cmdsize;
616 setString16("__LINKEDIT", cmd->segname);
617 cmd->vmaddr = _addressOfLinkEdit;
618 cmd->vmsize = _endOfLinkEdit - _startOfLinkEdit;
619 cmd->fileoff = _startOfLinkEdit;
620 cmd->filesize = _endOfLinkEdit - _startOfLinkEdit;
621 cmd->maxprot = VM_PROT_READ;
622 cmd->initprot = VM_PROT_READ;
623 cmd->nsects = 0;
624 cmd->flags = 0;
625 if (_swap)
626 swapStruct(*cmd);
627 lc = next;
628 return error_code::success();
629}
630
Nick Kledzike34182f2013-11-06 21:36:55 +0000631
632error_code MachOFileLayout::writeLoadCommands() {
633 error_code ec;
634 uint8_t *lc = &_buffer[_startOfLoadCommands];
635 if (_file.fileType == llvm::MachO::MH_OBJECT) {
636 // Object files have one unnamed segment which holds all sections.
637 if (_is64)
Nick Kledzik29f749e2013-11-09 00:07:28 +0000638 ec = writeSingleSegmentLoadCommand<MachO64Trait>(lc);
Nick Kledzike34182f2013-11-06 21:36:55 +0000639 else
Nick Kledzik29f749e2013-11-09 00:07:28 +0000640 ec = writeSingleSegmentLoadCommand<MachO32Trait>(lc);
Nick Kledzike34182f2013-11-06 21:36:55 +0000641 // Add LC_SYMTAB with symbol table info
642 symtab_command* st = reinterpret_cast<symtab_command*>(lc);
643 st->cmd = LC_SYMTAB;
644 st->cmdsize = sizeof(symtab_command);
645 st->symoff = _startOfSymbols;
646 st->nsyms = _file.localSymbols.size() + _file.globalSymbols.size()
647 + _file.undefinedSymbols.size();
648 st->stroff = _startOfSymbolStrings;
649 st->strsize = _endOfSymbolStrings - _startOfSymbolStrings;
650 if (_swap)
651 swapStruct(*st);
652 } else {
653 // Final linked images have sections under segments.
654 if (_is64)
Nick Kledzik29f749e2013-11-09 00:07:28 +0000655 ec = writeSegmentLoadCommands<MachO64Trait>(lc);
Nick Kledzike34182f2013-11-06 21:36:55 +0000656 else
Nick Kledzik29f749e2013-11-09 00:07:28 +0000657 ec = writeSegmentLoadCommands<MachO32Trait>(lc);
Nick Kledzike34182f2013-11-06 21:36:55 +0000658
659 // Add LC_DYLD_INFO_ONLY.
660 dyld_info_command* di = reinterpret_cast<dyld_info_command*>(lc);
661 di->cmd = LC_DYLD_INFO_ONLY;
662 di->cmdsize = sizeof(dyld_info_command);
663 di->rebase_off = _rebaseInfo.size() ? _startOfRebaseInfo : 0;
664 di->rebase_size = _rebaseInfo.size();
665 di->bind_off = _bindingInfo.size() ? _startOfBindingInfo : 0;
666 di->bind_size = _bindingInfo.size();
667 di->weak_bind_off = 0;
668 di->weak_bind_size = 0;
669 di->lazy_bind_off = _lazyBindingInfo.size() ? _startOfLazyBindingInfo : 0;
670 di->lazy_bind_size = _lazyBindingInfo.size();
671 di->export_off = 0;
672 di->export_size = 0;
673 if (_swap)
674 swapStruct(*di);
675 lc += sizeof(dyld_info_command);
676
677 // Add LC_SYMTAB with symbol table info.
678 symtab_command* st = reinterpret_cast<symtab_command*>(lc);
679 st->cmd = LC_SYMTAB;
680 st->cmdsize = sizeof(symtab_command);
681 st->symoff = _startOfSymbols;
682 st->nsyms = _file.localSymbols.size() + _file.globalSymbols.size()
683 + _file.undefinedSymbols.size();
684 st->stroff = _startOfSymbolStrings;
685 st->strsize = _endOfSymbolStrings - _startOfSymbolStrings;
686 if (_swap)
687 swapStruct(*st);
688 lc += sizeof(symtab_command);
689
690 // Add LC_DYSYMTAB
691 if (_file.fileType != llvm::MachO::MH_PRELOAD) {
692 dysymtab_command* dst = reinterpret_cast<dysymtab_command*>(lc);
693 dst->cmd = LC_DYSYMTAB;
694 dst->cmdsize = sizeof(dysymtab_command);
695 dst->ilocalsym = _symbolTableLocalsStartIndex;
696 dst->nlocalsym = _file.localSymbols.size();
697 dst->iextdefsym = _symbolTableGlobalsStartIndex;
698 dst->nextdefsym = _file.globalSymbols.size();
699 dst->iundefsym = _symbolTableUndefinesStartIndex;
700 dst->nundefsym = _file.undefinedSymbols.size();
701 dst->tocoff = 0;
702 dst->ntoc = 0;
703 dst->modtaboff = 0;
704 dst->nmodtab = 0;
705 dst->extrefsymoff = 0;
706 dst->nextrefsyms = 0;
707 dst->indirectsymoff = _startOfIndirectSymbols;
708 dst->nindirectsyms = _indirectSymbolTableCount;
709 dst->extreloff = 0;
710 dst->nextrel = 0;
711 dst->locreloff = 0;
712 dst->nlocrel = 0;
713 if (_swap)
714 swapStruct(*dst);
715 lc += sizeof(dysymtab_command);
716 }
717
718 // If main executable, add LC_LOAD_DYLINKER and LC_MAIN.
719 if (_file.fileType == llvm::MachO::MH_EXECUTE) {
720 // Build LC_LOAD_DYLINKER load command.
721 uint32_t size=pointerAlign(sizeof(dylinker_command)+dyldPath().size()+1);
722 dylinker_command* dl = reinterpret_cast<dylinker_command*>(lc);
723 dl->cmd = LC_LOAD_DYLINKER;
724 dl->cmdsize = size;
725 dl->name = sizeof(dylinker_command); // offset
726 if (_swap)
727 swapStruct(*dl);
728 memcpy(lc+sizeof(dylinker_command), dyldPath().data(), dyldPath().size());
729 lc[sizeof(dylinker_command)+dyldPath().size()] = '\0';
730 lc += size;
731 // Build LC_MAIN load command.
732 entry_point_command* ep = reinterpret_cast<entry_point_command*>(lc);
733 ep->cmd = LC_MAIN;
734 ep->cmdsize = sizeof(entry_point_command);
735 ep->entryoff = _file.entryAddress - _seg1addr;
736 ep->stacksize = 0;
737 if (_swap)
738 swapStruct(*ep);
739 lc += sizeof(entry_point_command);
740 }
741
742 // Add LC_LOAD_DYLIB commands
743 for (const DependentDylib &dep : _file.dependentDylibs) {
744 dylib_command* dc = reinterpret_cast<dylib_command*>(lc);
745 uint32_t size = sizeof(dylib_command) + pointerAlign(dep.path.size()+1);
746 dc->cmd = LC_LOAD_DYLIB;
747 dc->cmdsize = size;
748 dc->dylib.name = sizeof(dylib_command); // offset
749 dc->dylib.timestamp = 0; // FIXME
750 dc->dylib.current_version = 0; // FIXME
751 dc->dylib.compatibility_version = 0; // FIXME
752 if (_swap)
753 swapStruct(*dc);
754 memcpy(lc+sizeof(dylib_command), dep.path.begin(), dep.path.size());
755 lc[sizeof(dylib_command)+dep.path.size()] = '\0';
756 lc += size;
757 }
758
759 }
760 return ec;
761}
762
763
764void MachOFileLayout::writeSectionContent() {
765 for (const Section &s : _file.sections) {
766 // Copy all section content to output buffer.
767 uint32_t offset = _sectInfo[&s].fileOffset;
768 uint8_t *p = &_buffer[offset];
769 memcpy(p, &s.content[0], s.content.size());
770 p += s.content.size();
771 }
772}
773
774void MachOFileLayout::writeRelocations() {
775 uint32_t relOffset = _startOfRelocations;
776 for (Section sect : _file.sections) {
777 for (Relocation r : sect.relocations) {
778 any_relocation_info* rb = reinterpret_cast<any_relocation_info*>(
779 &_buffer[relOffset]);
780 *rb = packRelocation(r, _swap, _bigEndianArch);
781 relOffset += sizeof(any_relocation_info);
782 }
783 }
784}
785
786
787void MachOFileLayout::appendSymbols(const std::vector<Symbol> &symbols,
788 uint32_t &symOffset, uint32_t &strOffset) {
789 for (const Symbol &sym : symbols) {
790 if (_is64) {
791 nlist_64* nb = reinterpret_cast<nlist_64*>(&_buffer[symOffset]);
792 nb->n_strx = strOffset - _startOfSymbolStrings;
793 nb->n_type = sym.type | sym.scope;
794 nb->n_sect = sym.sect;
795 nb->n_desc = sym.desc;
796 nb->n_value = sym.value;
797 if (_swap)
798 swapStruct(*nb);
799 symOffset += sizeof(nlist_64);
800 } else {
801 nlist* nb = reinterpret_cast<nlist*>(&_buffer[symOffset]);
802 nb->n_strx = strOffset - _startOfSymbolStrings;
803 nb->n_type = sym.type | sym.scope;
804 nb->n_sect = sym.sect;
805 nb->n_desc = sym.desc;
806 nb->n_value = sym.value;
807 if (_swap)
808 swapStruct(*nb);
809 symOffset += sizeof(nlist);
810 }
811 memcpy(&_buffer[strOffset], sym.name.begin(), sym.name.size());
812 strOffset += sym.name.size();
813 _buffer[strOffset++] ='\0'; // Strings in table have nul terminator.
814 }
815}
816
817void MachOFileLayout::writeSymbolTable() {
818 // Write symbol table and symbol strings in parallel.
819 uint32_t symOffset = _startOfSymbols;
820 uint32_t strOffset = _startOfSymbolStrings;
821 _buffer[strOffset++] = '\0'; // Reserve n_strx offset of zero to mean no name.
822 appendSymbols(_file.localSymbols, symOffset, strOffset);
823 appendSymbols(_file.globalSymbols, symOffset, strOffset);
824 appendSymbols(_file.undefinedSymbols, symOffset, strOffset);
825 // Write indirect symbol table array.
826 uint32_t *indirects = reinterpret_cast<uint32_t*>
827 (&_buffer[_startOfIndirectSymbols]);
828 if (_file.fileType == llvm::MachO::MH_OBJECT) {
829 // Object files have sections in same order as input normalized file.
830 for (const Section &section : _file.sections) {
831 for (uint32_t index : section.indirectSymbols) {
832 if (_swap)
833 *indirects++ = SwapByteOrder(index);
834 else
835 *indirects++ = index;
836 }
837 }
838 } else {
839 // Final linked images must sort sections from normalized file.
840 for (const Segment &seg : _file.segments) {
841 SegExtraInfo &segInfo = _segInfo[&seg];
842 for (const Section *section : segInfo.sections) {
843 for (uint32_t index : section->indirectSymbols) {
844 if (_swap)
845 *indirects++ = SwapByteOrder(index);
846 else
847 *indirects++ = index;
848 }
849 }
850 }
851 }
852}
853
854void MachOFileLayout::writeRebaseInfo() {
855 memcpy(&_buffer[_startOfRebaseInfo], _rebaseInfo.bytes(), _rebaseInfo.size());
856}
857
858void MachOFileLayout::writeBindingInfo() {
859 memcpy(&_buffer[_startOfBindingInfo],
860 _bindingInfo.bytes(), _bindingInfo.size());
861}
862
863void MachOFileLayout::writeLazyBindingInfo() {
864 memcpy(&_buffer[_startOfLazyBindingInfo],
865 _lazyBindingInfo.bytes(), _lazyBindingInfo.size());
866}
867
868void MachOFileLayout::buildLinkEditInfo() {
869 buildRebaseInfo();
870 buildBindInfo();
871 buildLazyBindInfo();
872 computeSymbolTableSizes();
873}
874
875void MachOFileLayout::buildSectionRelocations() {
876
877}
878
879void MachOFileLayout::buildRebaseInfo() {
880 // TODO: compress rebasing info.
881 for (const RebaseLocation& entry : _file.rebasingInfo) {
882 _rebaseInfo.append_byte(REBASE_OPCODE_SET_TYPE_IMM | entry.kind);
883 _rebaseInfo.append_byte(REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
884 | entry.segIndex);
885 _rebaseInfo.append_uleb128(entry.segOffset);
886 _rebaseInfo.append_uleb128(REBASE_OPCODE_DO_REBASE_IMM_TIMES | 1);
887 }
888 _rebaseInfo.append_byte(REBASE_OPCODE_DONE);
889 _rebaseInfo.align(_is64 ? 8 : 4);
890}
891
892void MachOFileLayout::buildBindInfo() {
893 // TODO: compress bind info.
894 for (const BindLocation& entry : _file.bindingInfo) {
895 _bindingInfo.append_byte(BIND_OPCODE_SET_TYPE_IMM | entry.kind);
896 _bindingInfo.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
897 | entry.segIndex);
898 _bindingInfo.append_uleb128(entry.segOffset);
899 _bindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM | entry.ordinal);
900 _bindingInfo.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM);
901 _bindingInfo.append_string(entry.symbolName);
902 if (entry.addend != 0) {
903 _bindingInfo.append_byte(BIND_OPCODE_SET_ADDEND_SLEB);
904 _bindingInfo.append_sleb128(entry.addend);
905 }
906 _bindingInfo.append_byte(BIND_OPCODE_DO_BIND);
907 }
908 _bindingInfo.append_byte(BIND_OPCODE_DONE);
909 _bindingInfo.align(_is64 ? 8 : 4);
910}
911
912void MachOFileLayout::buildLazyBindInfo() {
913 for (const BindLocation& entry : _file.lazyBindingInfo) {
914 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_TYPE_IMM | entry.kind);
915 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
916 | entry.segIndex);
917 _lazyBindingInfo.append_uleb128(entry.segOffset);
918 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM | entry.ordinal);
919 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM);
920 _lazyBindingInfo.append_string(entry.symbolName);
921 _lazyBindingInfo.append_byte(BIND_OPCODE_DO_BIND);
922 }
923 _lazyBindingInfo.append_byte(BIND_OPCODE_DONE);
924 _lazyBindingInfo.align(_is64 ? 8 : 4);
925}
926
927void MachOFileLayout::computeSymbolTableSizes() {
928 // MachO symbol tables have three ranges: locals, globals, and undefines
929 const size_t nlistSize = (_is64 ? sizeof(nlist_64) : sizeof(nlist));
930 _symbolTableSize = nlistSize * (_file.localSymbols.size()
931 + _file.globalSymbols.size()
932 + _file.undefinedSymbols.size());
933 _symbolStringPoolSize = 0;
934 for (const Symbol &sym : _file.localSymbols) {
935 _symbolStringPoolSize += (sym.name.size()+1);
936 }
937 for (const Symbol &sym : _file.globalSymbols) {
938 _symbolStringPoolSize += (sym.name.size()+1);
939 }
940 for (const Symbol &sym : _file.undefinedSymbols) {
941 _symbolStringPoolSize += (sym.name.size()+1);
942 }
943 _symbolTableLocalsStartIndex = 0;
944 _symbolTableGlobalsStartIndex = _file.localSymbols.size();
945 _symbolTableUndefinesStartIndex = _symbolTableGlobalsStartIndex
946 + _file.globalSymbols.size();
947
948 _indirectSymbolTableCount = 0;
949 for (const Section &sect : _file.sections) {
950 _indirectSymbolTableCount += sect.indirectSymbols.size();
951 }
952}
953
954
955void MachOFileLayout::writeLinkEditContent() {
956 if (_file.fileType == llvm::MachO::MH_OBJECT) {
957 writeRelocations();
958 writeSymbolTable();
959 } else {
960 writeRebaseInfo();
961 writeBindingInfo();
962 writeLazyBindingInfo();
963 // TODO: add weak binding info
964 writeSymbolTable();
965 }
966}
967
968
969error_code MachOFileLayout::writeBinary(StringRef path) {
970 // Check for pending error from constructor.
971 if (_ec)
972 return _ec;
973 // Create FileOutputBuffer with calculated size.
974 OwningPtr<llvm::FileOutputBuffer> fob;
975 unsigned flags = 0;
976 if (_file.fileType != llvm::MachO::MH_OBJECT)
977 flags = llvm::FileOutputBuffer::F_executable;
978 error_code ec;
979 ec = llvm::FileOutputBuffer::create(path, size(), fob, flags);
980 if (ec)
981 return ec;
982
983 // Write content.
984 _buffer = fob->getBufferStart();
985 writeMachHeader();
986 ec = writeLoadCommands();
987 if (ec)
988 return ec;
989 writeSectionContent();
990 writeLinkEditContent();
991 fob->commit();
992
993 return error_code::success();
994}
995
996
997
998/// Takes in-memory normalized view and writes a mach-o object file.
999error_code
1000writeBinary(const NormalizedFile &file, StringRef path) {
1001 MachOFileLayout layout(file);
1002 return layout.writeBinary(path);
1003}
1004
1005
1006} // namespace normalized
1007} // namespace mach_o
1008} // namespace lld
1009