blob: 1ffb4294c926ad4327c3dd76c8480b4bfceb5ef6 [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///
Shankar Easwaran3d8de472014-01-27 03:09:26 +000011/// \file For mach-o object files, this implementation converts normalized
Nick Kledzike34182f2013-11-06 21:36:55 +000012/// mach-o in memory to mach-o binary on disk.
13///
Shankar Easwaran3d8de472014-01-27 03:09:26 +000014/// +---------------+
15/// | binary mach-o |
16/// +---------------+
Nick Kledzike34182f2013-11-06 21:36:55 +000017/// ^
18/// |
19/// |
Shankar Easwaran3d8de472014-01-27 03:09:26 +000020/// +------------+
21/// | normalized |
22/// +------------+
Nick Kledzike34182f2013-11-06 21:36:55 +000023
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"
Nick Kledzik00a15d92013-11-09 01:00:51 +000038#include "llvm/Support/LEB128.h"
Nick Kledzike34182f2013-11-06 21:36:55 +000039#include "llvm/Support/MachO.h"
40#include "llvm/Support/MemoryBuffer.h"
41#include "llvm/Support/raw_ostream.h"
42#include "llvm/Support/system_error.h"
43
44#include <functional>
45#include <map>
46
47using namespace llvm::MachO;
48
49namespace lld {
50namespace mach_o {
51namespace normalized {
52
53/// Utility class for writing a mach-o binary file given an in-memory
Shankar Easwaran3d8de472014-01-27 03:09:26 +000054/// normalized file.
Nick Kledzike34182f2013-11-06 21:36:55 +000055class MachOFileLayout {
56public:
Joey Goulyb275d7f2013-12-23 23:29:50 +000057 /// All layout computation is done in the constructor.
58 MachOFileLayout(const NormalizedFile &file);
59
Nick Kledzike34182f2013-11-06 21:36:55 +000060 /// Returns the final file size as computed in the constructor.
61 size_t size() const;
62
Shankar Easwaran3d8de472014-01-27 03:09:26 +000063 /// Writes the normalized file as a binary mach-o file to the specified
Nick Kledzike34182f2013-11-06 21:36:55 +000064 /// path. This does not have a stream interface because the generated
65 /// file may need the 'x' bit set.
66 error_code writeBinary(StringRef path);
Shankar Easwaran3d8de472014-01-27 03:09:26 +000067
Nick Kledzike34182f2013-11-06 21:36:55 +000068private:
69 uint32_t loadCommandsSize(uint32_t &count);
70 void buildFileOffsets();
71 void writeMachHeader();
72 error_code writeLoadCommands();
73 void writeSectionContent();
74 void writeRelocations();
75 void writeSymbolTable();
76 void writeRebaseInfo();
77 void writeBindingInfo();
78 void writeLazyBindingInfo();
79 void writeLinkEditContent();
80 void buildLinkEditInfo();
81 void buildRebaseInfo();
82 void buildBindInfo();
83 void buildLazyBindInfo();
84 void computeSymbolTableSizes();
85 void buildSectionRelocations();
86 void appendSymbols(const std::vector<Symbol> &symbols,
87 uint32_t &symOffset, uint32_t &strOffset);
88 uint32_t indirectSymbolIndex(const Section &sect, uint32_t &index);
89 uint32_t indirectSymbolElementSize(const Section &sect);
90
Nick Kledzik29f749e2013-11-09 00:07:28 +000091 // For use as template parameter to load command methods.
92 struct MachO64Trait {
93 typedef llvm::MachO::segment_command_64 command;
94 typedef llvm::MachO::section_64 section;
95 enum { LC = llvm::MachO::LC_SEGMENT_64 };
96 };
97
98 // For use as template parameter to load command methods.
99 struct MachO32Trait {
100 typedef llvm::MachO::segment_command command;
101 typedef llvm::MachO::section section;
102 enum { LC = llvm::MachO::LC_SEGMENT };
103 };
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000104
Nick Kledzik29f749e2013-11-09 00:07:28 +0000105 template <typename T>
106 error_code writeSingleSegmentLoadCommand(uint8_t *&lc);
107 template <typename T>
108 error_code writeSegmentLoadCommands(uint8_t *&lc);
109
Nick Kledzike34182f2013-11-06 21:36:55 +0000110 uint32_t pointerAlign(uint32_t value);
111 static StringRef dyldPath();
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000112
Nick Kledzike34182f2013-11-06 21:36:55 +0000113 class ByteBuffer {
114 public:
Nick Kledzik00a15d92013-11-09 01:00:51 +0000115 ByteBuffer() : _ostream(_bytes) { }
116 void append_byte(uint8_t b) {
117 _ostream << b;
118 }
119 void append_uleb128(uint64_t value) {
120 llvm::encodeULEB128(value, _ostream);
121 }
122 void append_sleb128(int64_t value) {
123 llvm::encodeSLEB128(value, _ostream);
124 }
125 void append_string(StringRef str) {
126 _ostream << str;
127 append_byte(0);
128 }
129 void align(unsigned alignment) {
130 while ( (_ostream.tell() % alignment) != 0 )
131 append_byte(0);
132 }
133 size_t size() {
134 return _ostream.tell();
135 }
136 const uint8_t *bytes() {
137 return reinterpret_cast<const uint8_t*>(_ostream.str().data());
138 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000139 private:
Nick Kledzik00a15d92013-11-09 01:00:51 +0000140 SmallVector<char, 128> _bytes;
141 // Stream ivar must be after SmallVector ivar to construct properly.
142 llvm::raw_svector_ostream _ostream;
Nick Kledzike34182f2013-11-06 21:36:55 +0000143 };
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000144
Nick Kledzik00a15d92013-11-09 01:00:51 +0000145
Nick Kledzike34182f2013-11-06 21:36:55 +0000146 struct SegExtraInfo {
147 uint32_t fileOffset;
148 std::vector<const Section*> sections;
149 };
150 typedef std::map<const Segment*, SegExtraInfo> SegMap;
151 struct SectionExtraInfo {
152 uint32_t fileOffset;
153 };
154 typedef std::map<const Section*, SectionExtraInfo> SectionMap;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000155
Nick Kledzike34182f2013-11-06 21:36:55 +0000156 const NormalizedFile &_file;
157 error_code _ec;
158 uint8_t *_buffer;
159 const bool _is64;
160 const bool _swap;
161 const bool _bigEndianArch;
162 uint64_t _seg1addr;
163 uint32_t _startOfLoadCommands;
164 uint32_t _countOfLoadCommands;
165 uint32_t _endOfLoadCommands;
166 uint32_t _startOfRelocations;
167 uint32_t _startOfSymbols;
168 uint32_t _startOfIndirectSymbols;
169 uint32_t _startOfSymbolStrings;
170 uint32_t _endOfSymbolStrings;
171 uint32_t _symbolTableLocalsStartIndex;
172 uint32_t _symbolTableGlobalsStartIndex;
173 uint32_t _symbolTableUndefinesStartIndex;
174 uint32_t _symbolStringPoolSize;
175 uint32_t _symbolTableSize;
176 uint32_t _indirectSymbolTableCount;
177 // Used in object file creation only
178 uint32_t _startOfSectionsContent;
179 uint32_t _endOfSectionsContent;
180 // Used in final linked image only
181 uint32_t _startOfLinkEdit;
182 uint32_t _startOfRebaseInfo;
183 uint32_t _endOfRebaseInfo;
184 uint32_t _startOfBindingInfo;
185 uint32_t _endOfBindingInfo;
186 uint32_t _startOfLazyBindingInfo;
187 uint32_t _endOfLazyBindingInfo;
188 uint32_t _endOfLinkEdit;
189 uint64_t _addressOfLinkEdit;
190 SegMap _segInfo;
191 SectionMap _sectInfo;
192 ByteBuffer _rebaseInfo;
193 ByteBuffer _bindingInfo;
194 ByteBuffer _lazyBindingInfo;
195 ByteBuffer _weakBindingInfo;
196 ByteBuffer _exportInfo;
197};
198
199size_t headerAndLoadCommandsSize(const NormalizedFile &file) {
200 MachOFileLayout layout(file);
201 return layout.size();
202}
203
204StringRef MachOFileLayout::dyldPath() {
205 return "/usr/lib/dyld";
206}
207
208uint32_t MachOFileLayout::pointerAlign(uint32_t value) {
209 return llvm::RoundUpToAlignment(value, _is64 ? 8 : 4);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000210}
Nick Kledzike34182f2013-11-06 21:36:55 +0000211
212
Nick Kledzike34182f2013-11-06 21:36:55 +0000213
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000214
215MachOFileLayout::MachOFileLayout(const NormalizedFile &file)
Nick Kledzike34182f2013-11-06 21:36:55 +0000216 : _file(file),
217 _is64(MachOLinkingContext::is64Bit(file.arch)),
218 _swap(!MachOLinkingContext::isHostEndian(file.arch)),
219 _bigEndianArch(MachOLinkingContext::isBigEndian(file.arch)),
220 _seg1addr(INT64_MAX) {
221 _startOfLoadCommands = _is64 ? sizeof(mach_header_64) : sizeof(mach_header);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000222 const size_t segCommandBaseSize =
Nick Kledzike34182f2013-11-06 21:36:55 +0000223 (_is64 ? sizeof(segment_command_64) : sizeof(segment_command));
224 const size_t sectsSize = (_is64 ? sizeof(section_64) : sizeof(section));
225 if (file.fileType == llvm::MachO::MH_OBJECT) {
226 // object files have just one segment load command containing all sections
227 _endOfLoadCommands = _startOfLoadCommands
228 + segCommandBaseSize
229 + file.sections.size() * sectsSize
230 + sizeof(symtab_command);
231 _countOfLoadCommands = 2;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000232
Nick Kledzike34182f2013-11-06 21:36:55 +0000233 // Accumulate size of each section.
234 _startOfSectionsContent = _endOfLoadCommands;
235 _endOfSectionsContent = _startOfSectionsContent;
236 unsigned relocCount = 0;
237 for (const Section &sect : file.sections) {
238 _sectInfo[&sect].fileOffset = _endOfSectionsContent;
239 _endOfSectionsContent += sect.content.size();
240 relocCount += sect.relocations.size();
241 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000242
Nick Kledzike34182f2013-11-06 21:36:55 +0000243 computeSymbolTableSizes();
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000244
Nick Kledzike34182f2013-11-06 21:36:55 +0000245 // Align start of relocations.
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000246 _startOfRelocations = pointerAlign(_endOfSectionsContent);
Nick Kledzike34182f2013-11-06 21:36:55 +0000247 _startOfSymbols = _startOfRelocations + relocCount * 8;
248 // Add Indirect symbol table.
249 _startOfIndirectSymbols = _startOfSymbols + _symbolTableSize;
250 // Align start of symbol table and symbol strings.
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000251 _startOfSymbolStrings = _startOfIndirectSymbols
Nick Kledzike34182f2013-11-06 21:36:55 +0000252 + pointerAlign(_indirectSymbolTableCount * sizeof(uint32_t));
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000253 _endOfSymbolStrings = _startOfSymbolStrings
Nick Kledzike34182f2013-11-06 21:36:55 +0000254 + pointerAlign(_symbolStringPoolSize);
255 _endOfLinkEdit = _endOfSymbolStrings;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000256 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000257 llvm::dbgs() << "MachOFileLayout()\n"
258 << " startOfLoadCommands=" << _startOfLoadCommands << "\n"
259 << " countOfLoadCommands=" << _countOfLoadCommands << "\n"
260 << " endOfLoadCommands=" << _endOfLoadCommands << "\n"
261 << " startOfRelocations=" << _startOfRelocations << "\n"
262 << " startOfSymbols=" << _startOfSymbols << "\n"
263 << " startOfSymbolStrings=" << _startOfSymbolStrings << "\n"
264 << " endOfSymbolStrings=" << _endOfSymbolStrings << "\n"
265 << " startOfSectionsContent=" << _startOfSectionsContent << "\n"
266 << " endOfSectionsContent=" << _endOfSectionsContent << "\n");
267 } else {
268 // Final linked images have one load command per segment.
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000269 _endOfLoadCommands = _startOfLoadCommands
Nick Kledzike34182f2013-11-06 21:36:55 +0000270 + loadCommandsSize(_countOfLoadCommands);
271
272 // Assign section file offsets.
273 buildFileOffsets();
274 buildLinkEditInfo();
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000275
Nick Kledzike34182f2013-11-06 21:36:55 +0000276 // LINKEDIT of final linked images has in order:
277 // rebase info, binding info, lazy binding info, weak binding info,
278 // indirect symbol table, symbol table, symbol table strings.
279 _startOfRebaseInfo = _startOfLinkEdit;
280 _endOfRebaseInfo = _startOfRebaseInfo + _rebaseInfo.size();
281 _startOfBindingInfo = _endOfRebaseInfo;
282 _endOfBindingInfo = _startOfBindingInfo + _bindingInfo.size();
283 _startOfLazyBindingInfo = _endOfBindingInfo;
284 _endOfLazyBindingInfo = _startOfLazyBindingInfo + _lazyBindingInfo.size();
285
286 _startOfSymbols = _endOfLazyBindingInfo;
287 _startOfIndirectSymbols = _startOfSymbols + _symbolTableSize;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000288 _startOfSymbolStrings = _startOfIndirectSymbols
Nick Kledzike34182f2013-11-06 21:36:55 +0000289 + pointerAlign(_indirectSymbolTableCount * sizeof(uint32_t));
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000290 _endOfSymbolStrings = _startOfSymbolStrings
Nick Kledzike34182f2013-11-06 21:36:55 +0000291 + pointerAlign(_symbolStringPoolSize);
292 _endOfLinkEdit = _endOfSymbolStrings;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000293 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000294 llvm::dbgs() << "MachOFileLayout()\n"
295 << " startOfLoadCommands=" << _startOfLoadCommands << "\n"
296 << " countOfLoadCommands=" << _countOfLoadCommands << "\n"
297 << " endOfLoadCommands=" << _endOfLoadCommands << "\n"
298 << " startOfLinkEdit=" << _startOfLinkEdit << "\n"
299 << " startOfRebaseInfo=" << _startOfRebaseInfo << "\n"
300 << " endOfRebaseInfo=" << _endOfRebaseInfo << "\n"
301 << " startOfBindingInfo=" << _startOfBindingInfo << "\n"
302 << " endOfBindingInfo=" << _endOfBindingInfo << "\n"
303 << " startOfLazyBindingInfo=" << _startOfLazyBindingInfo << "\n"
304 << " endOfLazyBindingInfo=" << _endOfLazyBindingInfo << "\n"
305 << " startOfSymbols=" << _startOfSymbols << "\n"
306 << " startOfSymbolStrings=" << _startOfSymbolStrings << "\n"
307 << " endOfSymbolStrings=" << _endOfSymbolStrings << "\n"
308 << " addressOfLinkEdit=" << _addressOfLinkEdit << "\n");
309 }
310}
311
312uint32_t MachOFileLayout::loadCommandsSize(uint32_t &count) {
313 uint32_t size = 0;
314 count = 0;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000315
316 const size_t segCommandSize =
Nick Kledzike34182f2013-11-06 21:36:55 +0000317 (_is64 ? sizeof(segment_command_64) : sizeof(segment_command));
318 const size_t sectionSize = (_is64 ? sizeof(section_64) : sizeof(section));
319
320 // Add LC_SEGMENT for each segment.
321 size += _file.segments.size() * segCommandSize;
322 count += _file.segments.size();
323 // Add section record for each section.
324 size += _file.sections.size() * sectionSize;
325 // Add one LC_SEGMENT for implicit __LINKEDIT segment
326 size += segCommandSize;
327 ++count;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000328
Nick Kledzike34182f2013-11-06 21:36:55 +0000329 // Add LC_DYLD_INFO
330 size += sizeof(dyld_info_command);
331 ++count;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000332
Nick Kledzike34182f2013-11-06 21:36:55 +0000333 // Add LC_SYMTAB
334 size += sizeof(symtab_command);
335 ++count;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000336
Nick Kledzike34182f2013-11-06 21:36:55 +0000337 // Add LC_DYSYMTAB
338 if (_file.fileType != llvm::MachO::MH_PRELOAD) {
339 size += sizeof(dysymtab_command);
340 ++count;
341 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000342
Nick Kledzike34182f2013-11-06 21:36:55 +0000343 // If main executable add LC_LOAD_DYLINKER and LC_MAIN
344 if (_file.fileType == llvm::MachO::MH_EXECUTE) {
345 size += pointerAlign(sizeof(dylinker_command) + dyldPath().size()+1);
346 ++count;
347 size += sizeof(entry_point_command);
348 ++count;
349 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000350
Nick Kledzike34182f2013-11-06 21:36:55 +0000351 // Add LC_LOAD_DYLIB for each dependent dylib.
352 for (const DependentDylib &dep : _file.dependentDylibs) {
353 size += sizeof(dylib_command) + pointerAlign(dep.path.size()+1);
354 ++count;
355 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000356
Nick Kledzike34182f2013-11-06 21:36:55 +0000357 return size;
358}
359
360static bool overlaps(const Segment &s1, const Segment &s2) {
361 if (s2.address >= s1.address+s1.size)
362 return false;
363 if (s1.address >= s2.address+s2.size)
364 return false;
365 return true;
366}
367
368static bool overlaps(const Section &s1, const Section &s2) {
369 if (s2.address >= s1.address+s1.content.size())
370 return false;
371 if (s1.address >= s2.address+s2.content.size())
372 return false;
373 return true;
374}
375
376void MachOFileLayout::buildFileOffsets() {
377 // Verify no segments overlap
378 for (const Segment &sg1 : _file.segments) {
379 for (const Segment &sg2 : _file.segments) {
380 if (&sg1 == &sg2)
381 continue;
382 if (overlaps(sg1,sg2)) {
383 _ec = llvm::make_error_code(llvm::errc::executable_format_error);
384 return;
385 }
386 }
387 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000388
389 // Verify no sections overlap
Nick Kledzike34182f2013-11-06 21:36:55 +0000390 for (const Section &s1 : _file.sections) {
391 for (const Section &s2 : _file.sections) {
392 if (&s1 == &s2)
393 continue;
394 if (overlaps(s1,s2)) {
395 _ec = llvm::make_error_code(llvm::errc::executable_format_error);
396 return;
397 }
398 }
399 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000400
Nick Kledzike34182f2013-11-06 21:36:55 +0000401 // Build side table of extra info about segments and sections.
402 SegExtraInfo t;
403 t.fileOffset = 0;
404 for (const Segment &sg : _file.segments) {
405 _segInfo[&sg] = t;
406 }
407 SectionExtraInfo t2;
408 t2.fileOffset = 0;
409 // Assign sections to segments.
410 for (const Section &s : _file.sections) {
411 _sectInfo[&s] = t2;
412 for (const Segment &sg : _file.segments) {
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000413 if ((s.address >= sg.address)
Nick Kledzike34182f2013-11-06 21:36:55 +0000414 && (s.address+s.content.size() <= sg.address+sg.size)) {
415 if (!sg.name.equals(s.segmentName)) {
416 _ec = llvm::make_error_code(llvm::errc::executable_format_error);
417 return;
418 }
419 _segInfo[&sg].sections.push_back(&s);
420 }
421 }
422 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000423
Nick Kledzike34182f2013-11-06 21:36:55 +0000424 // Assign file offsets.
425 uint32_t fileOffset = 0;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000426 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000427 llvm::dbgs() << "buildFileOffsets()\n");
428 for (const Segment &sg : _file.segments) {
Alp Toker32e8bef2013-12-01 23:51:36 +0000429 // FIXME: 4096 should be inferred from segments in normalized file.
Nick Kledzike34182f2013-11-06 21:36:55 +0000430 _segInfo[&sg].fileOffset = llvm::RoundUpToAlignment(fileOffset, 4096);
431 if ((_seg1addr == INT64_MAX) && sg.access)
432 _seg1addr = sg.address;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000433 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000434 llvm::dbgs() << " segment=" << sg.name
435 << ", fileOffset=" << _segInfo[&sg].fileOffset << "\n");
436 for (const Section *s : _segInfo[&sg].sections) {
437 fileOffset = s->address - sg.address + _segInfo[&sg].fileOffset;
438 _sectInfo[s].fileOffset = fileOffset;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000439 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000440 llvm::dbgs() << " section=" << s->sectionName
441 << ", fileOffset=" << fileOffset << "\n");
442 }
443 _addressOfLinkEdit = sg.address + sg.size;
444 }
445 _startOfLinkEdit = llvm::RoundUpToAlignment(fileOffset, 4096);
446}
447
448
449size_t MachOFileLayout::size() const {
450 return _endOfSymbolStrings;
451}
452
453void MachOFileLayout::writeMachHeader() {
454 mach_header *mh = reinterpret_cast<mach_header*>(_buffer);
455 mh->magic = _is64 ? llvm::MachO::MH_MAGIC_64 : llvm::MachO::MH_MAGIC;
456 mh->cputype = MachOLinkingContext::cpuTypeFromArch(_file.arch);
457 mh->cpusubtype = MachOLinkingContext::cpuSubtypeFromArch(_file.arch);
458 mh->filetype = _file.fileType;
459 mh->ncmds = _countOfLoadCommands;
460 mh->sizeofcmds = _endOfLoadCommands - _startOfLoadCommands;
461 mh->flags = _file.flags;
462 if (_swap)
463 swapStruct(*mh);
464}
465
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000466uint32_t MachOFileLayout::indirectSymbolIndex(const Section &sect,
Nick Kledzike34182f2013-11-06 21:36:55 +0000467 uint32_t &index) {
468 if (sect.indirectSymbols.empty())
469 return 0;
470 uint32_t result = index;
471 index += sect.indirectSymbols.size();
472 return result;
473}
474
475uint32_t MachOFileLayout::indirectSymbolElementSize(const Section &sect) {
476 if (sect.indirectSymbols.empty())
477 return 0;
478 if (sect.type != S_SYMBOL_STUBS)
479 return 0;
480 return sect.content.size() / sect.indirectSymbols.size();
481}
482
Nick Kledzike34182f2013-11-06 21:36:55 +0000483
Nick Kledzik29f749e2013-11-09 00:07:28 +0000484
485template <typename T>
486error_code MachOFileLayout::writeSingleSegmentLoadCommand(uint8_t *&lc) {
487 typename T::command* seg = reinterpret_cast<typename T::command*>(lc);
488 seg->cmd = T::LC;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000489 seg->cmdsize = sizeof(typename T::command)
Nick Kledzik29f749e2013-11-09 00:07:28 +0000490 + _file.sections.size() * sizeof(typename T::section);
Nick Kledzike34182f2013-11-06 21:36:55 +0000491 uint8_t *next = lc + seg->cmdsize;
492 memset(seg->segname, 0, 16);
493 seg->vmaddr = 0;
494 seg->vmsize = _endOfSectionsContent - _endOfLoadCommands;
495 seg->fileoff = _endOfLoadCommands;
496 seg->filesize = seg->vmsize;
497 seg->maxprot = VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE;
498 seg->initprot = VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE;
499 seg->nsects = _file.sections.size();
500 seg->flags = 0;
501 if (_swap)
502 swapStruct(*seg);
Nick Kledzik29f749e2013-11-09 00:07:28 +0000503 typename T::section *sout = reinterpret_cast<typename T::section*>
504 (lc+sizeof(typename T::command));
Nick Kledzike34182f2013-11-06 21:36:55 +0000505 uint32_t relOffset = _startOfRelocations;
506 uint32_t contentOffset = _startOfSectionsContent;
507 uint32_t indirectSymRunningIndex = 0;
508 for (const Section &sin : _file.sections) {
509 setString16(sin.sectionName, sout->sectname);
510 setString16(sin.segmentName, sout->segname);
511 sout->addr = sin.address;
512 sout->size = sin.content.size();
513 sout->offset = contentOffset;
514 sout->align = sin.alignment;
515 sout->reloff = sin.relocations.empty() ? 0 : relOffset;
516 sout->nreloc = sin.relocations.size();
517 sout->flags = sin.type | sin.attributes;
518 sout->reserved1 = indirectSymbolIndex(sin, indirectSymRunningIndex);
519 sout->reserved2 = indirectSymbolElementSize(sin);
520 relOffset += sin.relocations.size() * sizeof(any_relocation_info);
521 contentOffset += sin.content.size();
522 if (_swap)
523 swapStruct(*sout);
524 ++sout;
525 }
526 lc = next;
527 return error_code::success();
528}
529
530
Nick Kledzik29f749e2013-11-09 00:07:28 +0000531template <typename T>
532error_code MachOFileLayout::writeSegmentLoadCommands(uint8_t *&lc) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000533 uint32_t indirectSymRunningIndex = 0;
534 for (const Segment &seg : _file.segments) {
535 // Write segment command with trailing sections.
536 SegExtraInfo &segInfo = _segInfo[&seg];
Nick Kledzik29f749e2013-11-09 00:07:28 +0000537 typename T::command* cmd = reinterpret_cast<typename T::command*>(lc);
538 cmd->cmd = T::LC;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000539 cmd->cmdsize = sizeof(typename T::command)
Nick Kledzik29f749e2013-11-09 00:07:28 +0000540 + segInfo.sections.size() * sizeof(typename T::section);
Nick Kledzike34182f2013-11-06 21:36:55 +0000541 uint8_t *next = lc + cmd->cmdsize;
542 setString16(seg.name, cmd->segname);
543 cmd->vmaddr = seg.address;
544 cmd->vmsize = seg.size;
545 cmd->fileoff = segInfo.fileOffset;
Nick Kledzik29f749e2013-11-09 00:07:28 +0000546 cmd->filesize = seg.access ? seg.size : Hex64(0);
Nick Kledzike34182f2013-11-06 21:36:55 +0000547 cmd->maxprot = seg.access;
548 cmd->initprot = seg.access;
549 cmd->nsects = segInfo.sections.size();
550 cmd->flags = 0;
551 if (_swap)
552 swapStruct(*cmd);
Nick Kledzik29f749e2013-11-09 00:07:28 +0000553 typename T::section *sect = reinterpret_cast<typename T::section*>
554 (lc+sizeof(typename T::command));
Nick Kledzike34182f2013-11-06 21:36:55 +0000555 for (const Section *section : segInfo.sections) {
556 setString16(section->sectionName, sect->sectname);
557 setString16(section->segmentName, sect->segname);
558 sect->addr = section->address;
559 sect->size = section->content.size();
560 sect->offset = section->address - seg.address + segInfo.fileOffset;
561 sect->align = section->alignment;
562 sect->reloff = 0;
563 sect->nreloc = 0;
564 sect->flags = section->type | section->attributes;
565 sect->reserved1 = indirectSymbolIndex(*section, indirectSymRunningIndex);
566 sect->reserved2 = indirectSymbolElementSize(*section);
567 if (_swap)
568 swapStruct(*sect);
569 ++sect;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000570 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000571 lc = reinterpret_cast<uint8_t*>(next);
572 }
573 // Add implicit __LINKEDIT segment
Nick Kledzik29f749e2013-11-09 00:07:28 +0000574 typename T::command* cmd = reinterpret_cast<typename T::command*>(lc);
575 cmd->cmd = T::LC;
576 cmd->cmdsize = sizeof(typename T::command);
Nick Kledzike34182f2013-11-06 21:36:55 +0000577 uint8_t *next = lc + cmd->cmdsize;
578 setString16("__LINKEDIT", cmd->segname);
579 cmd->vmaddr = _addressOfLinkEdit;
580 cmd->vmsize = _endOfLinkEdit - _startOfLinkEdit;
581 cmd->fileoff = _startOfLinkEdit;
582 cmd->filesize = _endOfLinkEdit - _startOfLinkEdit;
583 cmd->maxprot = VM_PROT_READ;
584 cmd->initprot = VM_PROT_READ;
585 cmd->nsects = 0;
586 cmd->flags = 0;
587 if (_swap)
588 swapStruct(*cmd);
589 lc = next;
590 return error_code::success();
591}
592
Nick Kledzike34182f2013-11-06 21:36:55 +0000593
594error_code MachOFileLayout::writeLoadCommands() {
595 error_code ec;
596 uint8_t *lc = &_buffer[_startOfLoadCommands];
597 if (_file.fileType == llvm::MachO::MH_OBJECT) {
598 // Object files have one unnamed segment which holds all sections.
599 if (_is64)
Nick Kledzik29f749e2013-11-09 00:07:28 +0000600 ec = writeSingleSegmentLoadCommand<MachO64Trait>(lc);
Nick Kledzike34182f2013-11-06 21:36:55 +0000601 else
Nick Kledzik29f749e2013-11-09 00:07:28 +0000602 ec = writeSingleSegmentLoadCommand<MachO32Trait>(lc);
Nick Kledzike34182f2013-11-06 21:36:55 +0000603 // Add LC_SYMTAB with symbol table info
604 symtab_command* st = reinterpret_cast<symtab_command*>(lc);
605 st->cmd = LC_SYMTAB;
606 st->cmdsize = sizeof(symtab_command);
607 st->symoff = _startOfSymbols;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000608 st->nsyms = _file.localSymbols.size() + _file.globalSymbols.size()
Nick Kledzike34182f2013-11-06 21:36:55 +0000609 + _file.undefinedSymbols.size();
610 st->stroff = _startOfSymbolStrings;
611 st->strsize = _endOfSymbolStrings - _startOfSymbolStrings;
612 if (_swap)
613 swapStruct(*st);
614 } else {
615 // Final linked images have sections under segments.
616 if (_is64)
Nick Kledzik29f749e2013-11-09 00:07:28 +0000617 ec = writeSegmentLoadCommands<MachO64Trait>(lc);
Nick Kledzike34182f2013-11-06 21:36:55 +0000618 else
Nick Kledzik29f749e2013-11-09 00:07:28 +0000619 ec = writeSegmentLoadCommands<MachO32Trait>(lc);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000620
Nick Kledzike34182f2013-11-06 21:36:55 +0000621 // Add LC_DYLD_INFO_ONLY.
622 dyld_info_command* di = reinterpret_cast<dyld_info_command*>(lc);
623 di->cmd = LC_DYLD_INFO_ONLY;
624 di->cmdsize = sizeof(dyld_info_command);
625 di->rebase_off = _rebaseInfo.size() ? _startOfRebaseInfo : 0;
626 di->rebase_size = _rebaseInfo.size();
627 di->bind_off = _bindingInfo.size() ? _startOfBindingInfo : 0;
628 di->bind_size = _bindingInfo.size();
629 di->weak_bind_off = 0;
630 di->weak_bind_size = 0;
631 di->lazy_bind_off = _lazyBindingInfo.size() ? _startOfLazyBindingInfo : 0;
632 di->lazy_bind_size = _lazyBindingInfo.size();
633 di->export_off = 0;
634 di->export_size = 0;
635 if (_swap)
636 swapStruct(*di);
637 lc += sizeof(dyld_info_command);
638
639 // Add LC_SYMTAB with symbol table info.
640 symtab_command* st = reinterpret_cast<symtab_command*>(lc);
641 st->cmd = LC_SYMTAB;
642 st->cmdsize = sizeof(symtab_command);
643 st->symoff = _startOfSymbols;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000644 st->nsyms = _file.localSymbols.size() + _file.globalSymbols.size()
Nick Kledzike34182f2013-11-06 21:36:55 +0000645 + _file.undefinedSymbols.size();
646 st->stroff = _startOfSymbolStrings;
647 st->strsize = _endOfSymbolStrings - _startOfSymbolStrings;
648 if (_swap)
649 swapStruct(*st);
650 lc += sizeof(symtab_command);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000651
Nick Kledzike34182f2013-11-06 21:36:55 +0000652 // Add LC_DYSYMTAB
653 if (_file.fileType != llvm::MachO::MH_PRELOAD) {
654 dysymtab_command* dst = reinterpret_cast<dysymtab_command*>(lc);
655 dst->cmd = LC_DYSYMTAB;
656 dst->cmdsize = sizeof(dysymtab_command);
657 dst->ilocalsym = _symbolTableLocalsStartIndex;
658 dst->nlocalsym = _file.localSymbols.size();
659 dst->iextdefsym = _symbolTableGlobalsStartIndex;
660 dst->nextdefsym = _file.globalSymbols.size();
661 dst->iundefsym = _symbolTableUndefinesStartIndex;
662 dst->nundefsym = _file.undefinedSymbols.size();
663 dst->tocoff = 0;
664 dst->ntoc = 0;
665 dst->modtaboff = 0;
666 dst->nmodtab = 0;
667 dst->extrefsymoff = 0;
668 dst->nextrefsyms = 0;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000669 dst->indirectsymoff = _startOfIndirectSymbols;
Nick Kledzike34182f2013-11-06 21:36:55 +0000670 dst->nindirectsyms = _indirectSymbolTableCount;
671 dst->extreloff = 0;
672 dst->nextrel = 0;
673 dst->locreloff = 0;
674 dst->nlocrel = 0;
675 if (_swap)
676 swapStruct(*dst);
677 lc += sizeof(dysymtab_command);
678 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000679
Nick Kledzike34182f2013-11-06 21:36:55 +0000680 // If main executable, add LC_LOAD_DYLINKER and LC_MAIN.
681 if (_file.fileType == llvm::MachO::MH_EXECUTE) {
682 // Build LC_LOAD_DYLINKER load command.
683 uint32_t size=pointerAlign(sizeof(dylinker_command)+dyldPath().size()+1);
684 dylinker_command* dl = reinterpret_cast<dylinker_command*>(lc);
685 dl->cmd = LC_LOAD_DYLINKER;
686 dl->cmdsize = size;
687 dl->name = sizeof(dylinker_command); // offset
688 if (_swap)
689 swapStruct(*dl);
690 memcpy(lc+sizeof(dylinker_command), dyldPath().data(), dyldPath().size());
691 lc[sizeof(dylinker_command)+dyldPath().size()] = '\0';
692 lc += size;
693 // Build LC_MAIN load command.
694 entry_point_command* ep = reinterpret_cast<entry_point_command*>(lc);
695 ep->cmd = LC_MAIN;
696 ep->cmdsize = sizeof(entry_point_command);
697 ep->entryoff = _file.entryAddress - _seg1addr;
698 ep->stacksize = 0;
699 if (_swap)
700 swapStruct(*ep);
701 lc += sizeof(entry_point_command);
702 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000703
Nick Kledzike34182f2013-11-06 21:36:55 +0000704 // Add LC_LOAD_DYLIB commands
705 for (const DependentDylib &dep : _file.dependentDylibs) {
706 dylib_command* dc = reinterpret_cast<dylib_command*>(lc);
707 uint32_t size = sizeof(dylib_command) + pointerAlign(dep.path.size()+1);
708 dc->cmd = LC_LOAD_DYLIB;
709 dc->cmdsize = size;
710 dc->dylib.name = sizeof(dylib_command); // offset
711 dc->dylib.timestamp = 0; // FIXME
712 dc->dylib.current_version = 0; // FIXME
713 dc->dylib.compatibility_version = 0; // FIXME
714 if (_swap)
715 swapStruct(*dc);
716 memcpy(lc+sizeof(dylib_command), dep.path.begin(), dep.path.size());
717 lc[sizeof(dylib_command)+dep.path.size()] = '\0';
718 lc += size;
719 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000720
Nick Kledzike34182f2013-11-06 21:36:55 +0000721 }
722 return ec;
723}
724
725
726void MachOFileLayout::writeSectionContent() {
727 for (const Section &s : _file.sections) {
728 // Copy all section content to output buffer.
729 uint32_t offset = _sectInfo[&s].fileOffset;
730 uint8_t *p = &_buffer[offset];
731 memcpy(p, &s.content[0], s.content.size());
732 p += s.content.size();
733 }
734}
735
736void MachOFileLayout::writeRelocations() {
737 uint32_t relOffset = _startOfRelocations;
738 for (Section sect : _file.sections) {
739 for (Relocation r : sect.relocations) {
740 any_relocation_info* rb = reinterpret_cast<any_relocation_info*>(
741 &_buffer[relOffset]);
742 *rb = packRelocation(r, _swap, _bigEndianArch);
743 relOffset += sizeof(any_relocation_info);
744 }
745 }
746}
747
748
749void MachOFileLayout::appendSymbols(const std::vector<Symbol> &symbols,
750 uint32_t &symOffset, uint32_t &strOffset) {
751 for (const Symbol &sym : symbols) {
752 if (_is64) {
753 nlist_64* nb = reinterpret_cast<nlist_64*>(&_buffer[symOffset]);
754 nb->n_strx = strOffset - _startOfSymbolStrings;
755 nb->n_type = sym.type | sym.scope;
756 nb->n_sect = sym.sect;
757 nb->n_desc = sym.desc;
758 nb->n_value = sym.value;
759 if (_swap)
760 swapStruct(*nb);
761 symOffset += sizeof(nlist_64);
762 } else {
763 nlist* nb = reinterpret_cast<nlist*>(&_buffer[symOffset]);
764 nb->n_strx = strOffset - _startOfSymbolStrings;
765 nb->n_type = sym.type | sym.scope;
766 nb->n_sect = sym.sect;
767 nb->n_desc = sym.desc;
768 nb->n_value = sym.value;
769 if (_swap)
770 swapStruct(*nb);
771 symOffset += sizeof(nlist);
772 }
773 memcpy(&_buffer[strOffset], sym.name.begin(), sym.name.size());
774 strOffset += sym.name.size();
775 _buffer[strOffset++] ='\0'; // Strings in table have nul terminator.
776 }
777}
778
779void MachOFileLayout::writeSymbolTable() {
780 // Write symbol table and symbol strings in parallel.
781 uint32_t symOffset = _startOfSymbols;
782 uint32_t strOffset = _startOfSymbolStrings;
783 _buffer[strOffset++] = '\0'; // Reserve n_strx offset of zero to mean no name.
784 appendSymbols(_file.localSymbols, symOffset, strOffset);
785 appendSymbols(_file.globalSymbols, symOffset, strOffset);
786 appendSymbols(_file.undefinedSymbols, symOffset, strOffset);
787 // Write indirect symbol table array.
788 uint32_t *indirects = reinterpret_cast<uint32_t*>
789 (&_buffer[_startOfIndirectSymbols]);
790 if (_file.fileType == llvm::MachO::MH_OBJECT) {
791 // Object files have sections in same order as input normalized file.
792 for (const Section &section : _file.sections) {
793 for (uint32_t index : section.indirectSymbols) {
794 if (_swap)
795 *indirects++ = SwapByteOrder(index);
796 else
797 *indirects++ = index;
798 }
799 }
800 } else {
801 // Final linked images must sort sections from normalized file.
802 for (const Segment &seg : _file.segments) {
803 SegExtraInfo &segInfo = _segInfo[&seg];
804 for (const Section *section : segInfo.sections) {
805 for (uint32_t index : section->indirectSymbols) {
806 if (_swap)
807 *indirects++ = SwapByteOrder(index);
808 else
809 *indirects++ = index;
810 }
811 }
812 }
813 }
814}
815
816void MachOFileLayout::writeRebaseInfo() {
817 memcpy(&_buffer[_startOfRebaseInfo], _rebaseInfo.bytes(), _rebaseInfo.size());
818}
819
820void MachOFileLayout::writeBindingInfo() {
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000821 memcpy(&_buffer[_startOfBindingInfo],
Nick Kledzike34182f2013-11-06 21:36:55 +0000822 _bindingInfo.bytes(), _bindingInfo.size());
823}
824
825void MachOFileLayout::writeLazyBindingInfo() {
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000826 memcpy(&_buffer[_startOfLazyBindingInfo],
Nick Kledzike34182f2013-11-06 21:36:55 +0000827 _lazyBindingInfo.bytes(), _lazyBindingInfo.size());
828}
829
830void MachOFileLayout::buildLinkEditInfo() {
831 buildRebaseInfo();
832 buildBindInfo();
833 buildLazyBindInfo();
834 computeSymbolTableSizes();
835}
836
837void MachOFileLayout::buildSectionRelocations() {
838
839}
840
841void MachOFileLayout::buildRebaseInfo() {
842 // TODO: compress rebasing info.
843 for (const RebaseLocation& entry : _file.rebasingInfo) {
844 _rebaseInfo.append_byte(REBASE_OPCODE_SET_TYPE_IMM | entry.kind);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000845 _rebaseInfo.append_byte(REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
Nick Kledzike34182f2013-11-06 21:36:55 +0000846 | entry.segIndex);
847 _rebaseInfo.append_uleb128(entry.segOffset);
848 _rebaseInfo.append_uleb128(REBASE_OPCODE_DO_REBASE_IMM_TIMES | 1);
849 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000850 _rebaseInfo.append_byte(REBASE_OPCODE_DONE);
Nick Kledzike34182f2013-11-06 21:36:55 +0000851 _rebaseInfo.align(_is64 ? 8 : 4);
852}
853
854void MachOFileLayout::buildBindInfo() {
855 // TODO: compress bind info.
856 for (const BindLocation& entry : _file.bindingInfo) {
857 _bindingInfo.append_byte(BIND_OPCODE_SET_TYPE_IMM | entry.kind);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000858 _bindingInfo.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
Nick Kledzike34182f2013-11-06 21:36:55 +0000859 | entry.segIndex);
860 _bindingInfo.append_uleb128(entry.segOffset);
861 _bindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM | entry.ordinal);
862 _bindingInfo.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM);
863 _bindingInfo.append_string(entry.symbolName);
864 if (entry.addend != 0) {
865 _bindingInfo.append_byte(BIND_OPCODE_SET_ADDEND_SLEB);
866 _bindingInfo.append_sleb128(entry.addend);
867 }
868 _bindingInfo.append_byte(BIND_OPCODE_DO_BIND);
869 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000870 _bindingInfo.append_byte(BIND_OPCODE_DONE);
Nick Kledzike34182f2013-11-06 21:36:55 +0000871 _bindingInfo.align(_is64 ? 8 : 4);
872}
873
874void MachOFileLayout::buildLazyBindInfo() {
875 for (const BindLocation& entry : _file.lazyBindingInfo) {
876 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_TYPE_IMM | entry.kind);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000877 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
Nick Kledzike34182f2013-11-06 21:36:55 +0000878 | entry.segIndex);
879 _lazyBindingInfo.append_uleb128(entry.segOffset);
880 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM | entry.ordinal);
881 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM);
882 _lazyBindingInfo.append_string(entry.symbolName);
883 _lazyBindingInfo.append_byte(BIND_OPCODE_DO_BIND);
884 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000885 _lazyBindingInfo.append_byte(BIND_OPCODE_DONE);
Nick Kledzike34182f2013-11-06 21:36:55 +0000886 _lazyBindingInfo.align(_is64 ? 8 : 4);
887}
888
889void MachOFileLayout::computeSymbolTableSizes() {
890 // MachO symbol tables have three ranges: locals, globals, and undefines
891 const size_t nlistSize = (_is64 ? sizeof(nlist_64) : sizeof(nlist));
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000892 _symbolTableSize = nlistSize * (_file.localSymbols.size()
Nick Kledzike34182f2013-11-06 21:36:55 +0000893 + _file.globalSymbols.size()
894 + _file.undefinedSymbols.size());
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000895 _symbolStringPoolSize = 0;
Nick Kledzike34182f2013-11-06 21:36:55 +0000896 for (const Symbol &sym : _file.localSymbols) {
897 _symbolStringPoolSize += (sym.name.size()+1);
898 }
899 for (const Symbol &sym : _file.globalSymbols) {
900 _symbolStringPoolSize += (sym.name.size()+1);
901 }
902 for (const Symbol &sym : _file.undefinedSymbols) {
903 _symbolStringPoolSize += (sym.name.size()+1);
904 }
905 _symbolTableLocalsStartIndex = 0;
906 _symbolTableGlobalsStartIndex = _file.localSymbols.size();
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000907 _symbolTableUndefinesStartIndex = _symbolTableGlobalsStartIndex
Nick Kledzike34182f2013-11-06 21:36:55 +0000908 + _file.globalSymbols.size();
909
910 _indirectSymbolTableCount = 0;
911 for (const Section &sect : _file.sections) {
912 _indirectSymbolTableCount += sect.indirectSymbols.size();
913 }
914}
915
916
917void MachOFileLayout::writeLinkEditContent() {
918 if (_file.fileType == llvm::MachO::MH_OBJECT) {
919 writeRelocations();
920 writeSymbolTable();
921 } else {
922 writeRebaseInfo();
923 writeBindingInfo();
924 writeLazyBindingInfo();
925 // TODO: add weak binding info
926 writeSymbolTable();
927 }
928}
929
930
931error_code MachOFileLayout::writeBinary(StringRef path) {
932 // Check for pending error from constructor.
933 if (_ec)
934 return _ec;
935 // Create FileOutputBuffer with calculated size.
Ahmed Charles13c70b62014-03-13 16:20:38 +0000936 std::unique_ptr<llvm::FileOutputBuffer> fob;
Nick Kledzike34182f2013-11-06 21:36:55 +0000937 unsigned flags = 0;
938 if (_file.fileType != llvm::MachO::MH_OBJECT)
939 flags = llvm::FileOutputBuffer::F_executable;
940 error_code ec;
941 ec = llvm::FileOutputBuffer::create(path, size(), fob, flags);
942 if (ec)
943 return ec;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000944
Nick Kledzike34182f2013-11-06 21:36:55 +0000945 // Write content.
946 _buffer = fob->getBufferStart();
947 writeMachHeader();
948 ec = writeLoadCommands();
949 if (ec)
950 return ec;
951 writeSectionContent();
952 writeLinkEditContent();
953 fob->commit();
954
955 return error_code::success();
956}
957
958
959
960/// Takes in-memory normalized view and writes a mach-o object file.
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000961error_code
Nick Kledzike34182f2013-11-06 21:36:55 +0000962writeBinary(const NormalizedFile &file, StringRef path) {
963 MachOFileLayout layout(file);
964 return layout.writeBinary(path);
965}
966
967
968} // namespace normalized
969} // namespace mach_o
970} // namespace lld
971