blob: 5d9f46dd582a9512b1a8f79d287c35daa83e3a9a [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"
Nick Kledzike34182f2013-11-06 21:36:55 +000026#include "lld/Core/Error.h"
27#include "lld/Core/LLVM.h"
Nick Kledzike34182f2013-11-06 21:36:55 +000028#include "llvm/ADT/SmallString.h"
29#include "llvm/ADT/SmallVector.h"
30#include "llvm/ADT/StringRef.h"
31#include "llvm/Support/Casting.h"
Rafael Espindola372bc702014-06-13 17:20:48 +000032#include "llvm/Support/Errc.h"
Nick Kledzike34182f2013-11-06 21:36:55 +000033#include "llvm/Support/Debug.h"
34#include "llvm/Support/ErrorHandling.h"
35#include "llvm/Support/FileOutputBuffer.h"
36#include "llvm/Support/Host.h"
Nick Kledzik00a15d92013-11-09 01:00:51 +000037#include "llvm/Support/LEB128.h"
Nick Kledzike34182f2013-11-06 21:36:55 +000038#include "llvm/Support/MachO.h"
39#include "llvm/Support/MemoryBuffer.h"
40#include "llvm/Support/raw_ostream.h"
Nick Kledzike34182f2013-11-06 21:36:55 +000041#include <functional>
42#include <map>
Rafael Espindola54427cc2014-06-12 17:15:58 +000043#include <system_error>
Nick Kledzike34182f2013-11-06 21:36:55 +000044
45using namespace llvm::MachO;
46
47namespace lld {
48namespace mach_o {
49namespace normalized {
50
51/// Utility class for writing a mach-o binary file given an in-memory
Shankar Easwaran3d8de472014-01-27 03:09:26 +000052/// normalized file.
Nick Kledzike34182f2013-11-06 21:36:55 +000053class MachOFileLayout {
54public:
Joey Goulyb275d7f2013-12-23 23:29:50 +000055 /// All layout computation is done in the constructor.
56 MachOFileLayout(const NormalizedFile &file);
57
Nick Kledzike34182f2013-11-06 21:36:55 +000058 /// Returns the final file size as computed in the constructor.
59 size_t size() const;
60
Nick Kledzik2fcbe822014-07-30 00:58:06 +000061 // Returns size of the mach_header and load commands.
62 size_t headerAndLoadCommandsSize() const;
63
Shankar Easwaran3d8de472014-01-27 03:09:26 +000064 /// Writes the normalized file as a binary mach-o file to the specified
Nick Kledzike34182f2013-11-06 21:36:55 +000065 /// path. This does not have a stream interface because the generated
66 /// file may need the 'x' bit set.
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +000067 std::error_code writeBinary(StringRef path);
Shankar Easwaran3d8de472014-01-27 03:09:26 +000068
Nick Kledzike34182f2013-11-06 21:36:55 +000069private:
70 uint32_t loadCommandsSize(uint32_t &count);
71 void buildFileOffsets();
72 void writeMachHeader();
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +000073 std::error_code writeLoadCommands();
Nick Kledzike34182f2013-11-06 21:36:55 +000074 void writeSectionContent();
75 void writeRelocations();
76 void writeSymbolTable();
77 void writeRebaseInfo();
78 void writeBindingInfo();
79 void writeLazyBindingInfo();
Nick Kledzik21921372014-07-24 23:06:56 +000080 void writeDataInCodeInfo();
Nick Kledzike34182f2013-11-06 21:36:55 +000081 void writeLinkEditContent();
82 void buildLinkEditInfo();
83 void buildRebaseInfo();
84 void buildBindInfo();
85 void buildLazyBindInfo();
Nick Kledzik21921372014-07-24 23:06:56 +000086 void computeDataInCodeSize();
Nick Kledzike34182f2013-11-06 21:36:55 +000087 void computeSymbolTableSizes();
88 void buildSectionRelocations();
89 void appendSymbols(const std::vector<Symbol> &symbols,
90 uint32_t &symOffset, uint32_t &strOffset);
91 uint32_t indirectSymbolIndex(const Section &sect, uint32_t &index);
92 uint32_t indirectSymbolElementSize(const Section &sect);
93
Nick Kledzik29f749e2013-11-09 00:07:28 +000094 // For use as template parameter to load command methods.
95 struct MachO64Trait {
96 typedef llvm::MachO::segment_command_64 command;
97 typedef llvm::MachO::section_64 section;
98 enum { LC = llvm::MachO::LC_SEGMENT_64 };
99 };
100
101 // For use as template parameter to load command methods.
102 struct MachO32Trait {
103 typedef llvm::MachO::segment_command command;
104 typedef llvm::MachO::section section;
105 enum { LC = llvm::MachO::LC_SEGMENT };
106 };
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000107
Nick Kledzik29f749e2013-11-09 00:07:28 +0000108 template <typename T>
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000109 std::error_code writeSingleSegmentLoadCommand(uint8_t *&lc);
110 template <typename T> std::error_code writeSegmentLoadCommands(uint8_t *&lc);
Nick Kledzik29f749e2013-11-09 00:07:28 +0000111
Nick Kledzike34182f2013-11-06 21:36:55 +0000112 uint32_t pointerAlign(uint32_t value);
113 static StringRef dyldPath();
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000114
Nick Kledzike34182f2013-11-06 21:36:55 +0000115 class ByteBuffer {
116 public:
Nick Kledzik00a15d92013-11-09 01:00:51 +0000117 ByteBuffer() : _ostream(_bytes) { }
118 void append_byte(uint8_t b) {
119 _ostream << b;
120 }
121 void append_uleb128(uint64_t value) {
122 llvm::encodeULEB128(value, _ostream);
123 }
124 void append_sleb128(int64_t value) {
125 llvm::encodeSLEB128(value, _ostream);
126 }
127 void append_string(StringRef str) {
128 _ostream << str;
129 append_byte(0);
130 }
131 void align(unsigned alignment) {
132 while ( (_ostream.tell() % alignment) != 0 )
133 append_byte(0);
134 }
135 size_t size() {
136 return _ostream.tell();
137 }
138 const uint8_t *bytes() {
139 return reinterpret_cast<const uint8_t*>(_ostream.str().data());
140 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000141 private:
Nick Kledzik00a15d92013-11-09 01:00:51 +0000142 SmallVector<char, 128> _bytes;
143 // Stream ivar must be after SmallVector ivar to construct properly.
144 llvm::raw_svector_ostream _ostream;
Nick Kledzike34182f2013-11-06 21:36:55 +0000145 };
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000146
Nick Kledzik00a15d92013-11-09 01:00:51 +0000147
Nick Kledzike34182f2013-11-06 21:36:55 +0000148 struct SegExtraInfo {
149 uint32_t fileOffset;
Tim Northover08d6a7b2014-06-30 09:49:30 +0000150 uint32_t fileSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000151 std::vector<const Section*> sections;
152 };
153 typedef std::map<const Segment*, SegExtraInfo> SegMap;
154 struct SectionExtraInfo {
155 uint32_t fileOffset;
156 };
157 typedef std::map<const Section*, SectionExtraInfo> SectionMap;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000158
Nick Kledzike34182f2013-11-06 21:36:55 +0000159 const NormalizedFile &_file;
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000160 std::error_code _ec;
Nick Kledzike34182f2013-11-06 21:36:55 +0000161 uint8_t *_buffer;
162 const bool _is64;
163 const bool _swap;
164 const bool _bigEndianArch;
165 uint64_t _seg1addr;
166 uint32_t _startOfLoadCommands;
167 uint32_t _countOfLoadCommands;
168 uint32_t _endOfLoadCommands;
169 uint32_t _startOfRelocations;
Nick Kledzik21921372014-07-24 23:06:56 +0000170 uint32_t _startOfDataInCode;
Nick Kledzike34182f2013-11-06 21:36:55 +0000171 uint32_t _startOfSymbols;
172 uint32_t _startOfIndirectSymbols;
173 uint32_t _startOfSymbolStrings;
174 uint32_t _endOfSymbolStrings;
175 uint32_t _symbolTableLocalsStartIndex;
176 uint32_t _symbolTableGlobalsStartIndex;
177 uint32_t _symbolTableUndefinesStartIndex;
178 uint32_t _symbolStringPoolSize;
179 uint32_t _symbolTableSize;
Nick Kledzik21921372014-07-24 23:06:56 +0000180 uint32_t _dataInCodeSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000181 uint32_t _indirectSymbolTableCount;
182 // Used in object file creation only
183 uint32_t _startOfSectionsContent;
184 uint32_t _endOfSectionsContent;
185 // Used in final linked image only
186 uint32_t _startOfLinkEdit;
187 uint32_t _startOfRebaseInfo;
188 uint32_t _endOfRebaseInfo;
189 uint32_t _startOfBindingInfo;
190 uint32_t _endOfBindingInfo;
191 uint32_t _startOfLazyBindingInfo;
192 uint32_t _endOfLazyBindingInfo;
193 uint32_t _endOfLinkEdit;
194 uint64_t _addressOfLinkEdit;
195 SegMap _segInfo;
196 SectionMap _sectInfo;
197 ByteBuffer _rebaseInfo;
198 ByteBuffer _bindingInfo;
199 ByteBuffer _lazyBindingInfo;
200 ByteBuffer _weakBindingInfo;
201 ByteBuffer _exportInfo;
202};
203
204size_t headerAndLoadCommandsSize(const NormalizedFile &file) {
205 MachOFileLayout layout(file);
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000206 return layout.headerAndLoadCommandsSize();
Nick Kledzike34182f2013-11-06 21:36:55 +0000207}
208
209StringRef MachOFileLayout::dyldPath() {
210 return "/usr/lib/dyld";
211}
212
213uint32_t MachOFileLayout::pointerAlign(uint32_t value) {
214 return llvm::RoundUpToAlignment(value, _is64 ? 8 : 4);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000215}
Nick Kledzike34182f2013-11-06 21:36:55 +0000216
217
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000218size_t MachOFileLayout::headerAndLoadCommandsSize() const {
219 return _endOfLoadCommands;
220}
Nick Kledzike34182f2013-11-06 21:36:55 +0000221
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000222
223MachOFileLayout::MachOFileLayout(const NormalizedFile &file)
Nick Kledzike34182f2013-11-06 21:36:55 +0000224 : _file(file),
225 _is64(MachOLinkingContext::is64Bit(file.arch)),
226 _swap(!MachOLinkingContext::isHostEndian(file.arch)),
227 _bigEndianArch(MachOLinkingContext::isBigEndian(file.arch)),
228 _seg1addr(INT64_MAX) {
229 _startOfLoadCommands = _is64 ? sizeof(mach_header_64) : sizeof(mach_header);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000230 const size_t segCommandBaseSize =
Nick Kledzike34182f2013-11-06 21:36:55 +0000231 (_is64 ? sizeof(segment_command_64) : sizeof(segment_command));
232 const size_t sectsSize = (_is64 ? sizeof(section_64) : sizeof(section));
233 if (file.fileType == llvm::MachO::MH_OBJECT) {
234 // object files have just one segment load command containing all sections
235 _endOfLoadCommands = _startOfLoadCommands
236 + segCommandBaseSize
237 + file.sections.size() * sectsSize
238 + sizeof(symtab_command);
239 _countOfLoadCommands = 2;
Nick Kledzik21921372014-07-24 23:06:56 +0000240 if (!_file.dataInCode.empty()) {
241 _endOfLoadCommands += sizeof(linkedit_data_command);
242 _countOfLoadCommands++;
243 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000244 // Accumulate size of each section.
245 _startOfSectionsContent = _endOfLoadCommands;
246 _endOfSectionsContent = _startOfSectionsContent;
247 unsigned relocCount = 0;
248 for (const Section &sect : file.sections) {
249 _sectInfo[&sect].fileOffset = _endOfSectionsContent;
250 _endOfSectionsContent += sect.content.size();
251 relocCount += sect.relocations.size();
252 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000253
Nick Kledzike34182f2013-11-06 21:36:55 +0000254 computeSymbolTableSizes();
Nick Kledzik21921372014-07-24 23:06:56 +0000255 computeDataInCodeSize();
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000256
Nick Kledzike34182f2013-11-06 21:36:55 +0000257 // Align start of relocations.
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000258 _startOfRelocations = pointerAlign(_endOfSectionsContent);
Nick Kledzik21921372014-07-24 23:06:56 +0000259 _startOfDataInCode = _startOfRelocations + relocCount * 8;
260 _startOfSymbols = _startOfDataInCode + _dataInCodeSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000261 // Add Indirect symbol table.
262 _startOfIndirectSymbols = _startOfSymbols + _symbolTableSize;
263 // Align start of symbol table and symbol strings.
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000264 _startOfSymbolStrings = _startOfIndirectSymbols
Nick Kledzike34182f2013-11-06 21:36:55 +0000265 + pointerAlign(_indirectSymbolTableCount * sizeof(uint32_t));
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000266 _endOfSymbolStrings = _startOfSymbolStrings
Nick Kledzike34182f2013-11-06 21:36:55 +0000267 + pointerAlign(_symbolStringPoolSize);
268 _endOfLinkEdit = _endOfSymbolStrings;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000269 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000270 llvm::dbgs() << "MachOFileLayout()\n"
271 << " startOfLoadCommands=" << _startOfLoadCommands << "\n"
272 << " countOfLoadCommands=" << _countOfLoadCommands << "\n"
273 << " endOfLoadCommands=" << _endOfLoadCommands << "\n"
274 << " startOfRelocations=" << _startOfRelocations << "\n"
275 << " startOfSymbols=" << _startOfSymbols << "\n"
276 << " startOfSymbolStrings=" << _startOfSymbolStrings << "\n"
277 << " endOfSymbolStrings=" << _endOfSymbolStrings << "\n"
278 << " startOfSectionsContent=" << _startOfSectionsContent << "\n"
279 << " endOfSectionsContent=" << _endOfSectionsContent << "\n");
280 } else {
281 // Final linked images have one load command per segment.
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000282 _endOfLoadCommands = _startOfLoadCommands
Nick Kledzike34182f2013-11-06 21:36:55 +0000283 + loadCommandsSize(_countOfLoadCommands);
284
285 // Assign section file offsets.
286 buildFileOffsets();
287 buildLinkEditInfo();
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000288
Nick Kledzike34182f2013-11-06 21:36:55 +0000289 // LINKEDIT of final linked images has in order:
290 // rebase info, binding info, lazy binding info, weak binding info,
Nick Kledzik21921372014-07-24 23:06:56 +0000291 // data-in-code, symbol table, indirect symbol table, symbol table strings.
Nick Kledzike34182f2013-11-06 21:36:55 +0000292 _startOfRebaseInfo = _startOfLinkEdit;
293 _endOfRebaseInfo = _startOfRebaseInfo + _rebaseInfo.size();
294 _startOfBindingInfo = _endOfRebaseInfo;
295 _endOfBindingInfo = _startOfBindingInfo + _bindingInfo.size();
296 _startOfLazyBindingInfo = _endOfBindingInfo;
297 _endOfLazyBindingInfo = _startOfLazyBindingInfo + _lazyBindingInfo.size();
Nick Kledzik21921372014-07-24 23:06:56 +0000298 _startOfDataInCode = _endOfLazyBindingInfo;
299 _startOfSymbols = _startOfDataInCode + _dataInCodeSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000300 _startOfIndirectSymbols = _startOfSymbols + _symbolTableSize;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000301 _startOfSymbolStrings = _startOfIndirectSymbols
Nick Kledzike34182f2013-11-06 21:36:55 +0000302 + pointerAlign(_indirectSymbolTableCount * sizeof(uint32_t));
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000303 _endOfSymbolStrings = _startOfSymbolStrings
Nick Kledzike34182f2013-11-06 21:36:55 +0000304 + pointerAlign(_symbolStringPoolSize);
305 _endOfLinkEdit = _endOfSymbolStrings;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000306 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000307 llvm::dbgs() << "MachOFileLayout()\n"
308 << " startOfLoadCommands=" << _startOfLoadCommands << "\n"
309 << " countOfLoadCommands=" << _countOfLoadCommands << "\n"
310 << " endOfLoadCommands=" << _endOfLoadCommands << "\n"
311 << " startOfLinkEdit=" << _startOfLinkEdit << "\n"
312 << " startOfRebaseInfo=" << _startOfRebaseInfo << "\n"
313 << " endOfRebaseInfo=" << _endOfRebaseInfo << "\n"
314 << " startOfBindingInfo=" << _startOfBindingInfo << "\n"
315 << " endOfBindingInfo=" << _endOfBindingInfo << "\n"
316 << " startOfLazyBindingInfo=" << _startOfLazyBindingInfo << "\n"
317 << " endOfLazyBindingInfo=" << _endOfLazyBindingInfo << "\n"
Nick Kledzik21921372014-07-24 23:06:56 +0000318 << " startOfDataInCode=" << _startOfDataInCode << "\n"
Nick Kledzike34182f2013-11-06 21:36:55 +0000319 << " startOfSymbols=" << _startOfSymbols << "\n"
320 << " startOfSymbolStrings=" << _startOfSymbolStrings << "\n"
321 << " endOfSymbolStrings=" << _endOfSymbolStrings << "\n"
322 << " addressOfLinkEdit=" << _addressOfLinkEdit << "\n");
323 }
324}
325
326uint32_t MachOFileLayout::loadCommandsSize(uint32_t &count) {
327 uint32_t size = 0;
328 count = 0;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000329
330 const size_t segCommandSize =
Nick Kledzike34182f2013-11-06 21:36:55 +0000331 (_is64 ? sizeof(segment_command_64) : sizeof(segment_command));
332 const size_t sectionSize = (_is64 ? sizeof(section_64) : sizeof(section));
333
334 // Add LC_SEGMENT for each segment.
335 size += _file.segments.size() * segCommandSize;
336 count += _file.segments.size();
337 // Add section record for each section.
338 size += _file.sections.size() * sectionSize;
339 // Add one LC_SEGMENT for implicit __LINKEDIT segment
340 size += segCommandSize;
341 ++count;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000342
Tim Northover301c4e62014-07-01 08:15:41 +0000343 // If creating a dylib, add LC_ID_DYLIB.
344 if (_file.fileType == llvm::MachO::MH_DYLIB) {
345 size += sizeof(dylib_command) + pointerAlign(_file.installName.size() + 1);
346 ++count;
347 }
348
Nick Kledzike34182f2013-11-06 21:36:55 +0000349 // Add LC_DYLD_INFO
350 size += sizeof(dyld_info_command);
351 ++count;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000352
Nick Kledzike34182f2013-11-06 21:36:55 +0000353 // Add LC_SYMTAB
354 size += sizeof(symtab_command);
355 ++count;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000356
Nick Kledzike34182f2013-11-06 21:36:55 +0000357 // Add LC_DYSYMTAB
358 if (_file.fileType != llvm::MachO::MH_PRELOAD) {
359 size += sizeof(dysymtab_command);
360 ++count;
361 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000362
Nick Kledzike34182f2013-11-06 21:36:55 +0000363 // If main executable add LC_LOAD_DYLINKER and LC_MAIN
364 if (_file.fileType == llvm::MachO::MH_EXECUTE) {
365 size += pointerAlign(sizeof(dylinker_command) + dyldPath().size()+1);
366 ++count;
367 size += sizeof(entry_point_command);
368 ++count;
369 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000370
Nick Kledzike34182f2013-11-06 21:36:55 +0000371 // Add LC_LOAD_DYLIB for each dependent dylib.
372 for (const DependentDylib &dep : _file.dependentDylibs) {
373 size += sizeof(dylib_command) + pointerAlign(dep.path.size()+1);
374 ++count;
375 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000376
Nick Kledzike34182f2013-11-06 21:36:55 +0000377 return size;
378}
379
380static bool overlaps(const Segment &s1, const Segment &s2) {
381 if (s2.address >= s1.address+s1.size)
382 return false;
383 if (s1.address >= s2.address+s2.size)
384 return false;
385 return true;
386}
387
388static bool overlaps(const Section &s1, const Section &s2) {
389 if (s2.address >= s1.address+s1.content.size())
390 return false;
391 if (s1.address >= s2.address+s2.content.size())
392 return false;
393 return true;
394}
395
396void MachOFileLayout::buildFileOffsets() {
397 // Verify no segments overlap
398 for (const Segment &sg1 : _file.segments) {
399 for (const Segment &sg2 : _file.segments) {
400 if (&sg1 == &sg2)
401 continue;
402 if (overlaps(sg1,sg2)) {
Rafael Espindola372bc702014-06-13 17:20:48 +0000403 _ec = make_error_code(llvm::errc::executable_format_error);
Nick Kledzike34182f2013-11-06 21:36:55 +0000404 return;
405 }
406 }
407 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000408
409 // Verify no sections overlap
Nick Kledzike34182f2013-11-06 21:36:55 +0000410 for (const Section &s1 : _file.sections) {
411 for (const Section &s2 : _file.sections) {
412 if (&s1 == &s2)
413 continue;
414 if (overlaps(s1,s2)) {
Rafael Espindola372bc702014-06-13 17:20:48 +0000415 _ec = make_error_code(llvm::errc::executable_format_error);
Nick Kledzike34182f2013-11-06 21:36:55 +0000416 return;
417 }
418 }
419 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000420
Nick Kledzike34182f2013-11-06 21:36:55 +0000421 // Build side table of extra info about segments and sections.
422 SegExtraInfo t;
423 t.fileOffset = 0;
424 for (const Segment &sg : _file.segments) {
425 _segInfo[&sg] = t;
426 }
427 SectionExtraInfo t2;
428 t2.fileOffset = 0;
429 // Assign sections to segments.
430 for (const Section &s : _file.sections) {
431 _sectInfo[&s] = t2;
432 for (const Segment &sg : _file.segments) {
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000433 if ((s.address >= sg.address)
Nick Kledzike34182f2013-11-06 21:36:55 +0000434 && (s.address+s.content.size() <= sg.address+sg.size)) {
435 if (!sg.name.equals(s.segmentName)) {
Rafael Espindola372bc702014-06-13 17:20:48 +0000436 _ec = make_error_code(llvm::errc::executable_format_error);
Nick Kledzike34182f2013-11-06 21:36:55 +0000437 return;
438 }
439 _segInfo[&sg].sections.push_back(&s);
440 }
441 }
442 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000443
Nick Kledzike34182f2013-11-06 21:36:55 +0000444 // Assign file offsets.
445 uint32_t fileOffset = 0;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000446 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000447 llvm::dbgs() << "buildFileOffsets()\n");
448 for (const Segment &sg : _file.segments) {
Tim Northover08d6a7b2014-06-30 09:49:30 +0000449 _segInfo[&sg].fileOffset = fileOffset;
Nick Kledzike34182f2013-11-06 21:36:55 +0000450 if ((_seg1addr == INT64_MAX) && sg.access)
451 _seg1addr = sg.address;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000452 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000453 llvm::dbgs() << " segment=" << sg.name
454 << ", fileOffset=" << _segInfo[&sg].fileOffset << "\n");
Tim Northover08d6a7b2014-06-30 09:49:30 +0000455
456 uint32_t segFileSize = 0;
Nick Kledzike34182f2013-11-06 21:36:55 +0000457 for (const Section *s : _segInfo[&sg].sections) {
Tim Northover08d6a7b2014-06-30 09:49:30 +0000458 uint32_t sectOffset = s->address - sg.address;
459 uint32_t sectFileSize =
460 s->type == llvm::MachO::S_ZEROFILL ? 0 : s->content.size();
461 segFileSize = std::max(segFileSize, sectOffset + sectFileSize);
462
463 _sectInfo[s].fileOffset = _segInfo[&sg].fileOffset + sectOffset;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000464 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000465 llvm::dbgs() << " section=" << s->sectionName
466 << ", fileOffset=" << fileOffset << "\n");
467 }
Tim Northover08d6a7b2014-06-30 09:49:30 +0000468
469 // FIXME: 4096 should be inferred from segments in normalized file.
470 _segInfo[&sg].fileSize = llvm::RoundUpToAlignment(segFileSize, 4096);
471 fileOffset = llvm::RoundUpToAlignment(fileOffset + segFileSize, 4096);
Nick Kledzike34182f2013-11-06 21:36:55 +0000472 _addressOfLinkEdit = sg.address + sg.size;
473 }
Tim Northover08d6a7b2014-06-30 09:49:30 +0000474 _startOfLinkEdit = fileOffset;
Nick Kledzike34182f2013-11-06 21:36:55 +0000475}
476
477
478size_t MachOFileLayout::size() const {
479 return _endOfSymbolStrings;
480}
481
482void MachOFileLayout::writeMachHeader() {
483 mach_header *mh = reinterpret_cast<mach_header*>(_buffer);
484 mh->magic = _is64 ? llvm::MachO::MH_MAGIC_64 : llvm::MachO::MH_MAGIC;
485 mh->cputype = MachOLinkingContext::cpuTypeFromArch(_file.arch);
486 mh->cpusubtype = MachOLinkingContext::cpuSubtypeFromArch(_file.arch);
487 mh->filetype = _file.fileType;
488 mh->ncmds = _countOfLoadCommands;
489 mh->sizeofcmds = _endOfLoadCommands - _startOfLoadCommands;
490 mh->flags = _file.flags;
491 if (_swap)
492 swapStruct(*mh);
493}
494
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000495uint32_t MachOFileLayout::indirectSymbolIndex(const Section &sect,
Nick Kledzike34182f2013-11-06 21:36:55 +0000496 uint32_t &index) {
497 if (sect.indirectSymbols.empty())
498 return 0;
499 uint32_t result = index;
500 index += sect.indirectSymbols.size();
501 return result;
502}
503
504uint32_t MachOFileLayout::indirectSymbolElementSize(const Section &sect) {
505 if (sect.indirectSymbols.empty())
506 return 0;
507 if (sect.type != S_SYMBOL_STUBS)
508 return 0;
509 return sect.content.size() / sect.indirectSymbols.size();
510}
511
Nick Kledzik29f749e2013-11-09 00:07:28 +0000512template <typename T>
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000513std::error_code MachOFileLayout::writeSingleSegmentLoadCommand(uint8_t *&lc) {
Nick Kledzik29f749e2013-11-09 00:07:28 +0000514 typename T::command* seg = reinterpret_cast<typename T::command*>(lc);
515 seg->cmd = T::LC;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000516 seg->cmdsize = sizeof(typename T::command)
Nick Kledzik29f749e2013-11-09 00:07:28 +0000517 + _file.sections.size() * sizeof(typename T::section);
Nick Kledzike34182f2013-11-06 21:36:55 +0000518 uint8_t *next = lc + seg->cmdsize;
519 memset(seg->segname, 0, 16);
520 seg->vmaddr = 0;
521 seg->vmsize = _endOfSectionsContent - _endOfLoadCommands;
522 seg->fileoff = _endOfLoadCommands;
523 seg->filesize = seg->vmsize;
524 seg->maxprot = VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE;
525 seg->initprot = VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE;
526 seg->nsects = _file.sections.size();
527 seg->flags = 0;
528 if (_swap)
529 swapStruct(*seg);
Nick Kledzik29f749e2013-11-09 00:07:28 +0000530 typename T::section *sout = reinterpret_cast<typename T::section*>
531 (lc+sizeof(typename T::command));
Nick Kledzike34182f2013-11-06 21:36:55 +0000532 uint32_t relOffset = _startOfRelocations;
533 uint32_t contentOffset = _startOfSectionsContent;
534 uint32_t indirectSymRunningIndex = 0;
535 for (const Section &sin : _file.sections) {
536 setString16(sin.sectionName, sout->sectname);
537 setString16(sin.segmentName, sout->segname);
538 sout->addr = sin.address;
539 sout->size = sin.content.size();
540 sout->offset = contentOffset;
541 sout->align = sin.alignment;
542 sout->reloff = sin.relocations.empty() ? 0 : relOffset;
543 sout->nreloc = sin.relocations.size();
544 sout->flags = sin.type | sin.attributes;
545 sout->reserved1 = indirectSymbolIndex(sin, indirectSymRunningIndex);
546 sout->reserved2 = indirectSymbolElementSize(sin);
547 relOffset += sin.relocations.size() * sizeof(any_relocation_info);
548 contentOffset += sin.content.size();
549 if (_swap)
550 swapStruct(*sout);
551 ++sout;
552 }
553 lc = next;
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000554 return std::error_code();
Nick Kledzike34182f2013-11-06 21:36:55 +0000555}
556
Nick Kledzik29f749e2013-11-09 00:07:28 +0000557template <typename T>
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000558std::error_code MachOFileLayout::writeSegmentLoadCommands(uint8_t *&lc) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000559 uint32_t indirectSymRunningIndex = 0;
560 for (const Segment &seg : _file.segments) {
561 // Write segment command with trailing sections.
562 SegExtraInfo &segInfo = _segInfo[&seg];
Nick Kledzik29f749e2013-11-09 00:07:28 +0000563 typename T::command* cmd = reinterpret_cast<typename T::command*>(lc);
564 cmd->cmd = T::LC;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000565 cmd->cmdsize = sizeof(typename T::command)
Nick Kledzik29f749e2013-11-09 00:07:28 +0000566 + segInfo.sections.size() * sizeof(typename T::section);
Nick Kledzike34182f2013-11-06 21:36:55 +0000567 uint8_t *next = lc + cmd->cmdsize;
568 setString16(seg.name, cmd->segname);
569 cmd->vmaddr = seg.address;
570 cmd->vmsize = seg.size;
571 cmd->fileoff = segInfo.fileOffset;
Tim Northover08d6a7b2014-06-30 09:49:30 +0000572 cmd->filesize = segInfo.fileSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000573 cmd->maxprot = seg.access;
574 cmd->initprot = seg.access;
575 cmd->nsects = segInfo.sections.size();
576 cmd->flags = 0;
577 if (_swap)
578 swapStruct(*cmd);
Nick Kledzik29f749e2013-11-09 00:07:28 +0000579 typename T::section *sect = reinterpret_cast<typename T::section*>
580 (lc+sizeof(typename T::command));
Nick Kledzike34182f2013-11-06 21:36:55 +0000581 for (const Section *section : segInfo.sections) {
582 setString16(section->sectionName, sect->sectname);
583 setString16(section->segmentName, sect->segname);
584 sect->addr = section->address;
585 sect->size = section->content.size();
586 sect->offset = section->address - seg.address + segInfo.fileOffset;
587 sect->align = section->alignment;
588 sect->reloff = 0;
589 sect->nreloc = 0;
590 sect->flags = section->type | section->attributes;
591 sect->reserved1 = indirectSymbolIndex(*section, indirectSymRunningIndex);
592 sect->reserved2 = indirectSymbolElementSize(*section);
593 if (_swap)
594 swapStruct(*sect);
595 ++sect;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000596 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000597 lc = reinterpret_cast<uint8_t*>(next);
598 }
599 // Add implicit __LINKEDIT segment
Nick Kledzik29f749e2013-11-09 00:07:28 +0000600 typename T::command* cmd = reinterpret_cast<typename T::command*>(lc);
601 cmd->cmd = T::LC;
602 cmd->cmdsize = sizeof(typename T::command);
Nick Kledzike34182f2013-11-06 21:36:55 +0000603 uint8_t *next = lc + cmd->cmdsize;
604 setString16("__LINKEDIT", cmd->segname);
605 cmd->vmaddr = _addressOfLinkEdit;
606 cmd->vmsize = _endOfLinkEdit - _startOfLinkEdit;
607 cmd->fileoff = _startOfLinkEdit;
608 cmd->filesize = _endOfLinkEdit - _startOfLinkEdit;
609 cmd->maxprot = VM_PROT_READ;
610 cmd->initprot = VM_PROT_READ;
611 cmd->nsects = 0;
612 cmd->flags = 0;
613 if (_swap)
614 swapStruct(*cmd);
615 lc = next;
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000616 return std::error_code();
Nick Kledzike34182f2013-11-06 21:36:55 +0000617}
618
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000619std::error_code MachOFileLayout::writeLoadCommands() {
620 std::error_code ec;
Nick Kledzike34182f2013-11-06 21:36:55 +0000621 uint8_t *lc = &_buffer[_startOfLoadCommands];
622 if (_file.fileType == llvm::MachO::MH_OBJECT) {
623 // Object files have one unnamed segment which holds all sections.
624 if (_is64)
Nick Kledzik29f749e2013-11-09 00:07:28 +0000625 ec = writeSingleSegmentLoadCommand<MachO64Trait>(lc);
Nick Kledzike34182f2013-11-06 21:36:55 +0000626 else
Nick Kledzik29f749e2013-11-09 00:07:28 +0000627 ec = writeSingleSegmentLoadCommand<MachO32Trait>(lc);
Nick Kledzike34182f2013-11-06 21:36:55 +0000628 // Add LC_SYMTAB with symbol table info
629 symtab_command* st = reinterpret_cast<symtab_command*>(lc);
630 st->cmd = LC_SYMTAB;
631 st->cmdsize = sizeof(symtab_command);
632 st->symoff = _startOfSymbols;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000633 st->nsyms = _file.localSymbols.size() + _file.globalSymbols.size()
Nick Kledzike34182f2013-11-06 21:36:55 +0000634 + _file.undefinedSymbols.size();
635 st->stroff = _startOfSymbolStrings;
636 st->strsize = _endOfSymbolStrings - _startOfSymbolStrings;
637 if (_swap)
638 swapStruct(*st);
Nick Kledzik21921372014-07-24 23:06:56 +0000639 lc += sizeof(symtab_command);
640 // Add LC_DATA_IN_CODE if needed.
641 if (_dataInCodeSize != 0) {
642 linkedit_data_command* dl = reinterpret_cast<linkedit_data_command*>(lc);
643 dl->cmd = LC_DATA_IN_CODE;
644 dl->cmdsize = sizeof(linkedit_data_command);
645 dl->dataoff = _startOfDataInCode;
646 dl->datasize = _dataInCodeSize;
647 if (_swap)
648 swapStruct(*dl);
649 lc += sizeof(linkedit_data_command);
650 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000651 } else {
652 // Final linked images have sections under segments.
653 if (_is64)
Nick Kledzik29f749e2013-11-09 00:07:28 +0000654 ec = writeSegmentLoadCommands<MachO64Trait>(lc);
Nick Kledzike34182f2013-11-06 21:36:55 +0000655 else
Nick Kledzik29f749e2013-11-09 00:07:28 +0000656 ec = writeSegmentLoadCommands<MachO32Trait>(lc);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000657
Tim Northover301c4e62014-07-01 08:15:41 +0000658 // Add LC_ID_DYLIB command for dynamic libraries.
659 if (_file.fileType == llvm::MachO::MH_DYLIB) {
660 dylib_command *dc = reinterpret_cast<dylib_command*>(lc);
661 StringRef path = _file.installName;
662 uint32_t size = sizeof(dylib_command) + pointerAlign(path.size() + 1);
663 dc->cmd = LC_ID_DYLIB;
664 dc->cmdsize = size;
665 dc->dylib.name = sizeof(dylib_command); // offset
666 dc->dylib.timestamp = 0; // FIXME
667 dc->dylib.current_version = 0; // FIXME
668 dc->dylib.compatibility_version = 0; // FIXME
669 if (_swap)
670 swapStruct(*dc);
671 memcpy(lc + sizeof(dylib_command), path.begin(), path.size());
672 lc[sizeof(dylib_command) + path.size()] = '\0';
673 lc += size;
674 }
675
Nick Kledzike34182f2013-11-06 21:36:55 +0000676 // Add LC_DYLD_INFO_ONLY.
677 dyld_info_command* di = reinterpret_cast<dyld_info_command*>(lc);
678 di->cmd = LC_DYLD_INFO_ONLY;
679 di->cmdsize = sizeof(dyld_info_command);
680 di->rebase_off = _rebaseInfo.size() ? _startOfRebaseInfo : 0;
681 di->rebase_size = _rebaseInfo.size();
682 di->bind_off = _bindingInfo.size() ? _startOfBindingInfo : 0;
683 di->bind_size = _bindingInfo.size();
684 di->weak_bind_off = 0;
685 di->weak_bind_size = 0;
686 di->lazy_bind_off = _lazyBindingInfo.size() ? _startOfLazyBindingInfo : 0;
687 di->lazy_bind_size = _lazyBindingInfo.size();
688 di->export_off = 0;
689 di->export_size = 0;
690 if (_swap)
691 swapStruct(*di);
692 lc += sizeof(dyld_info_command);
693
694 // Add LC_SYMTAB with symbol table info.
695 symtab_command* st = reinterpret_cast<symtab_command*>(lc);
696 st->cmd = LC_SYMTAB;
697 st->cmdsize = sizeof(symtab_command);
698 st->symoff = _startOfSymbols;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000699 st->nsyms = _file.localSymbols.size() + _file.globalSymbols.size()
Nick Kledzike34182f2013-11-06 21:36:55 +0000700 + _file.undefinedSymbols.size();
701 st->stroff = _startOfSymbolStrings;
702 st->strsize = _endOfSymbolStrings - _startOfSymbolStrings;
703 if (_swap)
704 swapStruct(*st);
705 lc += sizeof(symtab_command);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000706
Nick Kledzike34182f2013-11-06 21:36:55 +0000707 // Add LC_DYSYMTAB
708 if (_file.fileType != llvm::MachO::MH_PRELOAD) {
709 dysymtab_command* dst = reinterpret_cast<dysymtab_command*>(lc);
710 dst->cmd = LC_DYSYMTAB;
711 dst->cmdsize = sizeof(dysymtab_command);
712 dst->ilocalsym = _symbolTableLocalsStartIndex;
713 dst->nlocalsym = _file.localSymbols.size();
714 dst->iextdefsym = _symbolTableGlobalsStartIndex;
715 dst->nextdefsym = _file.globalSymbols.size();
716 dst->iundefsym = _symbolTableUndefinesStartIndex;
717 dst->nundefsym = _file.undefinedSymbols.size();
718 dst->tocoff = 0;
719 dst->ntoc = 0;
720 dst->modtaboff = 0;
721 dst->nmodtab = 0;
722 dst->extrefsymoff = 0;
723 dst->nextrefsyms = 0;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000724 dst->indirectsymoff = _startOfIndirectSymbols;
Nick Kledzike34182f2013-11-06 21:36:55 +0000725 dst->nindirectsyms = _indirectSymbolTableCount;
726 dst->extreloff = 0;
727 dst->nextrel = 0;
728 dst->locreloff = 0;
729 dst->nlocrel = 0;
730 if (_swap)
731 swapStruct(*dst);
732 lc += sizeof(dysymtab_command);
733 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000734
Nick Kledzike34182f2013-11-06 21:36:55 +0000735 // If main executable, add LC_LOAD_DYLINKER and LC_MAIN.
736 if (_file.fileType == llvm::MachO::MH_EXECUTE) {
737 // Build LC_LOAD_DYLINKER load command.
738 uint32_t size=pointerAlign(sizeof(dylinker_command)+dyldPath().size()+1);
739 dylinker_command* dl = reinterpret_cast<dylinker_command*>(lc);
740 dl->cmd = LC_LOAD_DYLINKER;
741 dl->cmdsize = size;
742 dl->name = sizeof(dylinker_command); // offset
743 if (_swap)
744 swapStruct(*dl);
745 memcpy(lc+sizeof(dylinker_command), dyldPath().data(), dyldPath().size());
746 lc[sizeof(dylinker_command)+dyldPath().size()] = '\0';
747 lc += size;
748 // Build LC_MAIN load command.
749 entry_point_command* ep = reinterpret_cast<entry_point_command*>(lc);
750 ep->cmd = LC_MAIN;
751 ep->cmdsize = sizeof(entry_point_command);
752 ep->entryoff = _file.entryAddress - _seg1addr;
753 ep->stacksize = 0;
754 if (_swap)
755 swapStruct(*ep);
756 lc += sizeof(entry_point_command);
757 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000758
Nick Kledzike34182f2013-11-06 21:36:55 +0000759 // Add LC_LOAD_DYLIB commands
760 for (const DependentDylib &dep : _file.dependentDylibs) {
761 dylib_command* dc = reinterpret_cast<dylib_command*>(lc);
762 uint32_t size = sizeof(dylib_command) + pointerAlign(dep.path.size()+1);
763 dc->cmd = LC_LOAD_DYLIB;
764 dc->cmdsize = size;
765 dc->dylib.name = sizeof(dylib_command); // offset
766 dc->dylib.timestamp = 0; // FIXME
767 dc->dylib.current_version = 0; // FIXME
768 dc->dylib.compatibility_version = 0; // FIXME
769 if (_swap)
770 swapStruct(*dc);
771 memcpy(lc+sizeof(dylib_command), dep.path.begin(), dep.path.size());
772 lc[sizeof(dylib_command)+dep.path.size()] = '\0';
773 lc += size;
774 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000775 }
776 return ec;
777}
778
779
780void MachOFileLayout::writeSectionContent() {
781 for (const Section &s : _file.sections) {
782 // Copy all section content to output buffer.
Nick Kledzik61fdef62014-05-15 20:59:23 +0000783 if (s.type == llvm::MachO::S_ZEROFILL)
784 continue;
Nick Kledzike34182f2013-11-06 21:36:55 +0000785 uint32_t offset = _sectInfo[&s].fileOffset;
786 uint8_t *p = &_buffer[offset];
787 memcpy(p, &s.content[0], s.content.size());
788 p += s.content.size();
789 }
790}
791
792void MachOFileLayout::writeRelocations() {
793 uint32_t relOffset = _startOfRelocations;
794 for (Section sect : _file.sections) {
795 for (Relocation r : sect.relocations) {
796 any_relocation_info* rb = reinterpret_cast<any_relocation_info*>(
797 &_buffer[relOffset]);
798 *rb = packRelocation(r, _swap, _bigEndianArch);
799 relOffset += sizeof(any_relocation_info);
800 }
801 }
802}
803
804
805void MachOFileLayout::appendSymbols(const std::vector<Symbol> &symbols,
806 uint32_t &symOffset, uint32_t &strOffset) {
807 for (const Symbol &sym : symbols) {
808 if (_is64) {
809 nlist_64* nb = reinterpret_cast<nlist_64*>(&_buffer[symOffset]);
810 nb->n_strx = strOffset - _startOfSymbolStrings;
811 nb->n_type = sym.type | sym.scope;
812 nb->n_sect = sym.sect;
813 nb->n_desc = sym.desc;
814 nb->n_value = sym.value;
815 if (_swap)
816 swapStruct(*nb);
817 symOffset += sizeof(nlist_64);
818 } else {
819 nlist* nb = reinterpret_cast<nlist*>(&_buffer[symOffset]);
820 nb->n_strx = strOffset - _startOfSymbolStrings;
821 nb->n_type = sym.type | sym.scope;
822 nb->n_sect = sym.sect;
823 nb->n_desc = sym.desc;
824 nb->n_value = sym.value;
825 if (_swap)
826 swapStruct(*nb);
827 symOffset += sizeof(nlist);
828 }
829 memcpy(&_buffer[strOffset], sym.name.begin(), sym.name.size());
830 strOffset += sym.name.size();
831 _buffer[strOffset++] ='\0'; // Strings in table have nul terminator.
832 }
833}
834
Nick Kledzik21921372014-07-24 23:06:56 +0000835void MachOFileLayout::writeDataInCodeInfo() {
836 uint32_t offset = _startOfDataInCode;
837 for (const DataInCode &entry : _file.dataInCode) {
838 data_in_code_entry *dst = reinterpret_cast<data_in_code_entry*>(
839 &_buffer[offset]);
840 dst->offset = entry.offset;
841 dst->length = entry.length;
842 dst->kind = entry.kind;
843 if (_swap)
844 swapStruct(*dst);
845 offset += sizeof(data_in_code_entry);
846 }
847}
848
Nick Kledzike34182f2013-11-06 21:36:55 +0000849void MachOFileLayout::writeSymbolTable() {
850 // Write symbol table and symbol strings in parallel.
851 uint32_t symOffset = _startOfSymbols;
852 uint32_t strOffset = _startOfSymbolStrings;
853 _buffer[strOffset++] = '\0'; // Reserve n_strx offset of zero to mean no name.
854 appendSymbols(_file.localSymbols, symOffset, strOffset);
855 appendSymbols(_file.globalSymbols, symOffset, strOffset);
856 appendSymbols(_file.undefinedSymbols, symOffset, strOffset);
857 // Write indirect symbol table array.
858 uint32_t *indirects = reinterpret_cast<uint32_t*>
859 (&_buffer[_startOfIndirectSymbols]);
860 if (_file.fileType == llvm::MachO::MH_OBJECT) {
861 // Object files have sections in same order as input normalized file.
862 for (const Section &section : _file.sections) {
863 for (uint32_t index : section.indirectSymbols) {
864 if (_swap)
Artyom Skrobov17587fb2014-06-14 12:40:04 +0000865 *indirects++ = llvm::sys::getSwappedBytes(index);
Nick Kledzike34182f2013-11-06 21:36:55 +0000866 else
867 *indirects++ = index;
868 }
869 }
870 } else {
871 // Final linked images must sort sections from normalized file.
872 for (const Segment &seg : _file.segments) {
873 SegExtraInfo &segInfo = _segInfo[&seg];
874 for (const Section *section : segInfo.sections) {
875 for (uint32_t index : section->indirectSymbols) {
876 if (_swap)
Artyom Skrobov17587fb2014-06-14 12:40:04 +0000877 *indirects++ = llvm::sys::getSwappedBytes(index);
Nick Kledzike34182f2013-11-06 21:36:55 +0000878 else
879 *indirects++ = index;
880 }
881 }
882 }
883 }
884}
885
886void MachOFileLayout::writeRebaseInfo() {
887 memcpy(&_buffer[_startOfRebaseInfo], _rebaseInfo.bytes(), _rebaseInfo.size());
888}
889
890void MachOFileLayout::writeBindingInfo() {
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000891 memcpy(&_buffer[_startOfBindingInfo],
Nick Kledzike34182f2013-11-06 21:36:55 +0000892 _bindingInfo.bytes(), _bindingInfo.size());
893}
894
895void MachOFileLayout::writeLazyBindingInfo() {
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000896 memcpy(&_buffer[_startOfLazyBindingInfo],
Nick Kledzike34182f2013-11-06 21:36:55 +0000897 _lazyBindingInfo.bytes(), _lazyBindingInfo.size());
898}
899
900void MachOFileLayout::buildLinkEditInfo() {
901 buildRebaseInfo();
902 buildBindInfo();
903 buildLazyBindInfo();
904 computeSymbolTableSizes();
Nick Kledzik21921372014-07-24 23:06:56 +0000905 computeDataInCodeSize();
Nick Kledzike34182f2013-11-06 21:36:55 +0000906}
907
908void MachOFileLayout::buildSectionRelocations() {
909
910}
911
912void MachOFileLayout::buildRebaseInfo() {
913 // TODO: compress rebasing info.
914 for (const RebaseLocation& entry : _file.rebasingInfo) {
915 _rebaseInfo.append_byte(REBASE_OPCODE_SET_TYPE_IMM | entry.kind);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000916 _rebaseInfo.append_byte(REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
Nick Kledzike34182f2013-11-06 21:36:55 +0000917 | entry.segIndex);
918 _rebaseInfo.append_uleb128(entry.segOffset);
919 _rebaseInfo.append_uleb128(REBASE_OPCODE_DO_REBASE_IMM_TIMES | 1);
920 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000921 _rebaseInfo.append_byte(REBASE_OPCODE_DONE);
Nick Kledzike34182f2013-11-06 21:36:55 +0000922 _rebaseInfo.align(_is64 ? 8 : 4);
923}
924
925void MachOFileLayout::buildBindInfo() {
926 // TODO: compress bind info.
927 for (const BindLocation& entry : _file.bindingInfo) {
928 _bindingInfo.append_byte(BIND_OPCODE_SET_TYPE_IMM | entry.kind);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000929 _bindingInfo.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
Nick Kledzike34182f2013-11-06 21:36:55 +0000930 | entry.segIndex);
931 _bindingInfo.append_uleb128(entry.segOffset);
932 _bindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM | entry.ordinal);
933 _bindingInfo.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM);
934 _bindingInfo.append_string(entry.symbolName);
935 if (entry.addend != 0) {
936 _bindingInfo.append_byte(BIND_OPCODE_SET_ADDEND_SLEB);
937 _bindingInfo.append_sleb128(entry.addend);
938 }
939 _bindingInfo.append_byte(BIND_OPCODE_DO_BIND);
940 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000941 _bindingInfo.append_byte(BIND_OPCODE_DONE);
Nick Kledzike34182f2013-11-06 21:36:55 +0000942 _bindingInfo.align(_is64 ? 8 : 4);
943}
944
945void MachOFileLayout::buildLazyBindInfo() {
946 for (const BindLocation& entry : _file.lazyBindingInfo) {
947 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_TYPE_IMM | entry.kind);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000948 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
Nick Kledzike34182f2013-11-06 21:36:55 +0000949 | entry.segIndex);
950 _lazyBindingInfo.append_uleb128(entry.segOffset);
951 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM | entry.ordinal);
952 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM);
953 _lazyBindingInfo.append_string(entry.symbolName);
954 _lazyBindingInfo.append_byte(BIND_OPCODE_DO_BIND);
955 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000956 _lazyBindingInfo.append_byte(BIND_OPCODE_DONE);
Nick Kledzike34182f2013-11-06 21:36:55 +0000957 _lazyBindingInfo.align(_is64 ? 8 : 4);
958}
959
960void MachOFileLayout::computeSymbolTableSizes() {
961 // MachO symbol tables have three ranges: locals, globals, and undefines
962 const size_t nlistSize = (_is64 ? sizeof(nlist_64) : sizeof(nlist));
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000963 _symbolTableSize = nlistSize * (_file.localSymbols.size()
Nick Kledzike34182f2013-11-06 21:36:55 +0000964 + _file.globalSymbols.size()
965 + _file.undefinedSymbols.size());
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000966 _symbolStringPoolSize = 0;
Nick Kledzike34182f2013-11-06 21:36:55 +0000967 for (const Symbol &sym : _file.localSymbols) {
968 _symbolStringPoolSize += (sym.name.size()+1);
969 }
970 for (const Symbol &sym : _file.globalSymbols) {
971 _symbolStringPoolSize += (sym.name.size()+1);
972 }
973 for (const Symbol &sym : _file.undefinedSymbols) {
974 _symbolStringPoolSize += (sym.name.size()+1);
975 }
976 _symbolTableLocalsStartIndex = 0;
977 _symbolTableGlobalsStartIndex = _file.localSymbols.size();
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000978 _symbolTableUndefinesStartIndex = _symbolTableGlobalsStartIndex
Nick Kledzike34182f2013-11-06 21:36:55 +0000979 + _file.globalSymbols.size();
980
981 _indirectSymbolTableCount = 0;
982 for (const Section &sect : _file.sections) {
983 _indirectSymbolTableCount += sect.indirectSymbols.size();
984 }
985}
986
Nick Kledzik21921372014-07-24 23:06:56 +0000987void MachOFileLayout::computeDataInCodeSize() {
988 _dataInCodeSize = _file.dataInCode.size() * sizeof(data_in_code_entry);
989}
Nick Kledzike34182f2013-11-06 21:36:55 +0000990
991void MachOFileLayout::writeLinkEditContent() {
992 if (_file.fileType == llvm::MachO::MH_OBJECT) {
993 writeRelocations();
Nick Kledzik21921372014-07-24 23:06:56 +0000994 writeDataInCodeInfo();
Nick Kledzike34182f2013-11-06 21:36:55 +0000995 writeSymbolTable();
996 } else {
997 writeRebaseInfo();
998 writeBindingInfo();
999 writeLazyBindingInfo();
1000 // TODO: add weak binding info
1001 writeSymbolTable();
1002 }
1003}
1004
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +00001005std::error_code MachOFileLayout::writeBinary(StringRef path) {
Nick Kledzike34182f2013-11-06 21:36:55 +00001006 // Check for pending error from constructor.
1007 if (_ec)
1008 return _ec;
1009 // Create FileOutputBuffer with calculated size.
Ahmed Charles13c70b62014-03-13 16:20:38 +00001010 std::unique_ptr<llvm::FileOutputBuffer> fob;
Nick Kledzike34182f2013-11-06 21:36:55 +00001011 unsigned flags = 0;
1012 if (_file.fileType != llvm::MachO::MH_OBJECT)
1013 flags = llvm::FileOutputBuffer::F_executable;
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +00001014 std::error_code ec;
Nick Kledzike34182f2013-11-06 21:36:55 +00001015 ec = llvm::FileOutputBuffer::create(path, size(), fob, flags);
1016 if (ec)
1017 return ec;
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001018
Nick Kledzike34182f2013-11-06 21:36:55 +00001019 // Write content.
1020 _buffer = fob->getBufferStart();
1021 writeMachHeader();
1022 ec = writeLoadCommands();
1023 if (ec)
1024 return ec;
1025 writeSectionContent();
1026 writeLinkEditContent();
1027 fob->commit();
1028
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +00001029 return std::error_code();
Nick Kledzike34182f2013-11-06 21:36:55 +00001030}
1031
1032
1033
1034/// Takes in-memory normalized view and writes a mach-o object file.
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +00001035std::error_code writeBinary(const NormalizedFile &file, StringRef path) {
Nick Kledzike34182f2013-11-06 21:36:55 +00001036 MachOFileLayout layout(file);
1037 return layout.writeBinary(path);
1038}
1039
1040
1041} // namespace normalized
1042} // namespace mach_o
1043} // namespace lld
1044