blob: fc90e8b34cb2945fc0a5828d816dadb6980bfc0a [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
Shankar Easwaran3d8de472014-01-27 03:09:26 +000061 /// Writes the normalized file as a binary mach-o file to the specified
Nick Kledzike34182f2013-11-06 21:36:55 +000062 /// path. This does not have a stream interface because the generated
63 /// file may need the 'x' bit set.
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +000064 std::error_code writeBinary(StringRef path);
Shankar Easwaran3d8de472014-01-27 03:09:26 +000065
Nick Kledzike34182f2013-11-06 21:36:55 +000066private:
67 uint32_t loadCommandsSize(uint32_t &count);
68 void buildFileOffsets();
69 void writeMachHeader();
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +000070 std::error_code writeLoadCommands();
Nick Kledzike34182f2013-11-06 21:36:55 +000071 void writeSectionContent();
72 void writeRelocations();
73 void writeSymbolTable();
74 void writeRebaseInfo();
75 void writeBindingInfo();
76 void writeLazyBindingInfo();
Nick Kledzik21921372014-07-24 23:06:56 +000077 void writeDataInCodeInfo();
Nick Kledzike34182f2013-11-06 21:36:55 +000078 void writeLinkEditContent();
79 void buildLinkEditInfo();
80 void buildRebaseInfo();
81 void buildBindInfo();
82 void buildLazyBindInfo();
Nick Kledzik21921372014-07-24 23:06:56 +000083 void computeDataInCodeSize();
Nick Kledzike34182f2013-11-06 21:36:55 +000084 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>
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000106 std::error_code writeSingleSegmentLoadCommand(uint8_t *&lc);
107 template <typename T> std::error_code writeSegmentLoadCommands(uint8_t *&lc);
Nick Kledzik29f749e2013-11-09 00:07:28 +0000108
Nick Kledzike34182f2013-11-06 21:36:55 +0000109 uint32_t pointerAlign(uint32_t value);
110 static StringRef dyldPath();
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000111
Nick Kledzike34182f2013-11-06 21:36:55 +0000112 class ByteBuffer {
113 public:
Nick Kledzik00a15d92013-11-09 01:00:51 +0000114 ByteBuffer() : _ostream(_bytes) { }
115 void append_byte(uint8_t b) {
116 _ostream << b;
117 }
118 void append_uleb128(uint64_t value) {
119 llvm::encodeULEB128(value, _ostream);
120 }
121 void append_sleb128(int64_t value) {
122 llvm::encodeSLEB128(value, _ostream);
123 }
124 void append_string(StringRef str) {
125 _ostream << str;
126 append_byte(0);
127 }
128 void align(unsigned alignment) {
129 while ( (_ostream.tell() % alignment) != 0 )
130 append_byte(0);
131 }
132 size_t size() {
133 return _ostream.tell();
134 }
135 const uint8_t *bytes() {
136 return reinterpret_cast<const uint8_t*>(_ostream.str().data());
137 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000138 private:
Nick Kledzik00a15d92013-11-09 01:00:51 +0000139 SmallVector<char, 128> _bytes;
140 // Stream ivar must be after SmallVector ivar to construct properly.
141 llvm::raw_svector_ostream _ostream;
Nick Kledzike34182f2013-11-06 21:36:55 +0000142 };
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000143
Nick Kledzik00a15d92013-11-09 01:00:51 +0000144
Nick Kledzike34182f2013-11-06 21:36:55 +0000145 struct SegExtraInfo {
146 uint32_t fileOffset;
Tim Northover08d6a7b2014-06-30 09:49:30 +0000147 uint32_t fileSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000148 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;
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000157 std::error_code _ec;
Nick Kledzike34182f2013-11-06 21:36:55 +0000158 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;
Nick Kledzik21921372014-07-24 23:06:56 +0000167 uint32_t _startOfDataInCode;
Nick Kledzike34182f2013-11-06 21:36:55 +0000168 uint32_t _startOfSymbols;
169 uint32_t _startOfIndirectSymbols;
170 uint32_t _startOfSymbolStrings;
171 uint32_t _endOfSymbolStrings;
172 uint32_t _symbolTableLocalsStartIndex;
173 uint32_t _symbolTableGlobalsStartIndex;
174 uint32_t _symbolTableUndefinesStartIndex;
175 uint32_t _symbolStringPoolSize;
176 uint32_t _symbolTableSize;
Nick Kledzik21921372014-07-24 23:06:56 +0000177 uint32_t _dataInCodeSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000178 uint32_t _indirectSymbolTableCount;
179 // Used in object file creation only
180 uint32_t _startOfSectionsContent;
181 uint32_t _endOfSectionsContent;
182 // Used in final linked image only
183 uint32_t _startOfLinkEdit;
184 uint32_t _startOfRebaseInfo;
185 uint32_t _endOfRebaseInfo;
186 uint32_t _startOfBindingInfo;
187 uint32_t _endOfBindingInfo;
188 uint32_t _startOfLazyBindingInfo;
189 uint32_t _endOfLazyBindingInfo;
190 uint32_t _endOfLinkEdit;
191 uint64_t _addressOfLinkEdit;
192 SegMap _segInfo;
193 SectionMap _sectInfo;
194 ByteBuffer _rebaseInfo;
195 ByteBuffer _bindingInfo;
196 ByteBuffer _lazyBindingInfo;
197 ByteBuffer _weakBindingInfo;
198 ByteBuffer _exportInfo;
199};
200
201size_t headerAndLoadCommandsSize(const NormalizedFile &file) {
202 MachOFileLayout layout(file);
203 return layout.size();
204}
205
206StringRef MachOFileLayout::dyldPath() {
207 return "/usr/lib/dyld";
208}
209
210uint32_t MachOFileLayout::pointerAlign(uint32_t value) {
211 return llvm::RoundUpToAlignment(value, _is64 ? 8 : 4);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000212}
Nick Kledzike34182f2013-11-06 21:36:55 +0000213
214
Nick Kledzike34182f2013-11-06 21:36:55 +0000215
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000216
217MachOFileLayout::MachOFileLayout(const NormalizedFile &file)
Nick Kledzike34182f2013-11-06 21:36:55 +0000218 : _file(file),
219 _is64(MachOLinkingContext::is64Bit(file.arch)),
220 _swap(!MachOLinkingContext::isHostEndian(file.arch)),
221 _bigEndianArch(MachOLinkingContext::isBigEndian(file.arch)),
222 _seg1addr(INT64_MAX) {
223 _startOfLoadCommands = _is64 ? sizeof(mach_header_64) : sizeof(mach_header);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000224 const size_t segCommandBaseSize =
Nick Kledzike34182f2013-11-06 21:36:55 +0000225 (_is64 ? sizeof(segment_command_64) : sizeof(segment_command));
226 const size_t sectsSize = (_is64 ? sizeof(section_64) : sizeof(section));
227 if (file.fileType == llvm::MachO::MH_OBJECT) {
228 // object files have just one segment load command containing all sections
229 _endOfLoadCommands = _startOfLoadCommands
230 + segCommandBaseSize
231 + file.sections.size() * sectsSize
232 + sizeof(symtab_command);
233 _countOfLoadCommands = 2;
Nick Kledzik21921372014-07-24 23:06:56 +0000234 if (!_file.dataInCode.empty()) {
235 _endOfLoadCommands += sizeof(linkedit_data_command);
236 _countOfLoadCommands++;
237 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000238 // Accumulate size of each section.
239 _startOfSectionsContent = _endOfLoadCommands;
240 _endOfSectionsContent = _startOfSectionsContent;
241 unsigned relocCount = 0;
242 for (const Section &sect : file.sections) {
243 _sectInfo[&sect].fileOffset = _endOfSectionsContent;
244 _endOfSectionsContent += sect.content.size();
245 relocCount += sect.relocations.size();
246 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000247
Nick Kledzike34182f2013-11-06 21:36:55 +0000248 computeSymbolTableSizes();
Nick Kledzik21921372014-07-24 23:06:56 +0000249 computeDataInCodeSize();
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000250
Nick Kledzike34182f2013-11-06 21:36:55 +0000251 // Align start of relocations.
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000252 _startOfRelocations = pointerAlign(_endOfSectionsContent);
Nick Kledzik21921372014-07-24 23:06:56 +0000253 _startOfDataInCode = _startOfRelocations + relocCount * 8;
254 _startOfSymbols = _startOfDataInCode + _dataInCodeSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000255 // Add Indirect symbol table.
256 _startOfIndirectSymbols = _startOfSymbols + _symbolTableSize;
257 // Align start of symbol table and symbol strings.
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000258 _startOfSymbolStrings = _startOfIndirectSymbols
Nick Kledzike34182f2013-11-06 21:36:55 +0000259 + pointerAlign(_indirectSymbolTableCount * sizeof(uint32_t));
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000260 _endOfSymbolStrings = _startOfSymbolStrings
Nick Kledzike34182f2013-11-06 21:36:55 +0000261 + pointerAlign(_symbolStringPoolSize);
262 _endOfLinkEdit = _endOfSymbolStrings;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000263 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000264 llvm::dbgs() << "MachOFileLayout()\n"
265 << " startOfLoadCommands=" << _startOfLoadCommands << "\n"
266 << " countOfLoadCommands=" << _countOfLoadCommands << "\n"
267 << " endOfLoadCommands=" << _endOfLoadCommands << "\n"
268 << " startOfRelocations=" << _startOfRelocations << "\n"
269 << " startOfSymbols=" << _startOfSymbols << "\n"
270 << " startOfSymbolStrings=" << _startOfSymbolStrings << "\n"
271 << " endOfSymbolStrings=" << _endOfSymbolStrings << "\n"
272 << " startOfSectionsContent=" << _startOfSectionsContent << "\n"
273 << " endOfSectionsContent=" << _endOfSectionsContent << "\n");
274 } else {
275 // Final linked images have one load command per segment.
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000276 _endOfLoadCommands = _startOfLoadCommands
Nick Kledzike34182f2013-11-06 21:36:55 +0000277 + loadCommandsSize(_countOfLoadCommands);
278
279 // Assign section file offsets.
280 buildFileOffsets();
281 buildLinkEditInfo();
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000282
Nick Kledzike34182f2013-11-06 21:36:55 +0000283 // LINKEDIT of final linked images has in order:
284 // rebase info, binding info, lazy binding info, weak binding info,
Nick Kledzik21921372014-07-24 23:06:56 +0000285 // data-in-code, symbol table, indirect symbol table, symbol table strings.
Nick Kledzike34182f2013-11-06 21:36:55 +0000286 _startOfRebaseInfo = _startOfLinkEdit;
287 _endOfRebaseInfo = _startOfRebaseInfo + _rebaseInfo.size();
288 _startOfBindingInfo = _endOfRebaseInfo;
289 _endOfBindingInfo = _startOfBindingInfo + _bindingInfo.size();
290 _startOfLazyBindingInfo = _endOfBindingInfo;
291 _endOfLazyBindingInfo = _startOfLazyBindingInfo + _lazyBindingInfo.size();
Nick Kledzik21921372014-07-24 23:06:56 +0000292 _startOfDataInCode = _endOfLazyBindingInfo;
293 _startOfSymbols = _startOfDataInCode + _dataInCodeSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000294 _startOfIndirectSymbols = _startOfSymbols + _symbolTableSize;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000295 _startOfSymbolStrings = _startOfIndirectSymbols
Nick Kledzike34182f2013-11-06 21:36:55 +0000296 + pointerAlign(_indirectSymbolTableCount * sizeof(uint32_t));
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000297 _endOfSymbolStrings = _startOfSymbolStrings
Nick Kledzike34182f2013-11-06 21:36:55 +0000298 + pointerAlign(_symbolStringPoolSize);
299 _endOfLinkEdit = _endOfSymbolStrings;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000300 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000301 llvm::dbgs() << "MachOFileLayout()\n"
302 << " startOfLoadCommands=" << _startOfLoadCommands << "\n"
303 << " countOfLoadCommands=" << _countOfLoadCommands << "\n"
304 << " endOfLoadCommands=" << _endOfLoadCommands << "\n"
305 << " startOfLinkEdit=" << _startOfLinkEdit << "\n"
306 << " startOfRebaseInfo=" << _startOfRebaseInfo << "\n"
307 << " endOfRebaseInfo=" << _endOfRebaseInfo << "\n"
308 << " startOfBindingInfo=" << _startOfBindingInfo << "\n"
309 << " endOfBindingInfo=" << _endOfBindingInfo << "\n"
310 << " startOfLazyBindingInfo=" << _startOfLazyBindingInfo << "\n"
311 << " endOfLazyBindingInfo=" << _endOfLazyBindingInfo << "\n"
Nick Kledzik21921372014-07-24 23:06:56 +0000312 << " startOfDataInCode=" << _startOfDataInCode << "\n"
Nick Kledzike34182f2013-11-06 21:36:55 +0000313 << " startOfSymbols=" << _startOfSymbols << "\n"
314 << " startOfSymbolStrings=" << _startOfSymbolStrings << "\n"
315 << " endOfSymbolStrings=" << _endOfSymbolStrings << "\n"
316 << " addressOfLinkEdit=" << _addressOfLinkEdit << "\n");
317 }
318}
319
320uint32_t MachOFileLayout::loadCommandsSize(uint32_t &count) {
321 uint32_t size = 0;
322 count = 0;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000323
324 const size_t segCommandSize =
Nick Kledzike34182f2013-11-06 21:36:55 +0000325 (_is64 ? sizeof(segment_command_64) : sizeof(segment_command));
326 const size_t sectionSize = (_is64 ? sizeof(section_64) : sizeof(section));
327
328 // Add LC_SEGMENT for each segment.
329 size += _file.segments.size() * segCommandSize;
330 count += _file.segments.size();
331 // Add section record for each section.
332 size += _file.sections.size() * sectionSize;
333 // Add one LC_SEGMENT for implicit __LINKEDIT segment
334 size += segCommandSize;
335 ++count;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000336
Tim Northover301c4e62014-07-01 08:15:41 +0000337 // If creating a dylib, add LC_ID_DYLIB.
338 if (_file.fileType == llvm::MachO::MH_DYLIB) {
339 size += sizeof(dylib_command) + pointerAlign(_file.installName.size() + 1);
340 ++count;
341 }
342
Nick Kledzike34182f2013-11-06 21:36:55 +0000343 // Add LC_DYLD_INFO
344 size += sizeof(dyld_info_command);
345 ++count;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000346
Nick Kledzike34182f2013-11-06 21:36:55 +0000347 // Add LC_SYMTAB
348 size += sizeof(symtab_command);
349 ++count;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000350
Nick Kledzike34182f2013-11-06 21:36:55 +0000351 // Add LC_DYSYMTAB
352 if (_file.fileType != llvm::MachO::MH_PRELOAD) {
353 size += sizeof(dysymtab_command);
354 ++count;
355 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000356
Nick Kledzike34182f2013-11-06 21:36:55 +0000357 // If main executable add LC_LOAD_DYLINKER and LC_MAIN
358 if (_file.fileType == llvm::MachO::MH_EXECUTE) {
359 size += pointerAlign(sizeof(dylinker_command) + dyldPath().size()+1);
360 ++count;
361 size += sizeof(entry_point_command);
362 ++count;
363 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000364
Nick Kledzike34182f2013-11-06 21:36:55 +0000365 // Add LC_LOAD_DYLIB for each dependent dylib.
366 for (const DependentDylib &dep : _file.dependentDylibs) {
367 size += sizeof(dylib_command) + pointerAlign(dep.path.size()+1);
368 ++count;
369 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000370
Nick Kledzike34182f2013-11-06 21:36:55 +0000371 return size;
372}
373
374static bool overlaps(const Segment &s1, const Segment &s2) {
375 if (s2.address >= s1.address+s1.size)
376 return false;
377 if (s1.address >= s2.address+s2.size)
378 return false;
379 return true;
380}
381
382static bool overlaps(const Section &s1, const Section &s2) {
383 if (s2.address >= s1.address+s1.content.size())
384 return false;
385 if (s1.address >= s2.address+s2.content.size())
386 return false;
387 return true;
388}
389
390void MachOFileLayout::buildFileOffsets() {
391 // Verify no segments overlap
392 for (const Segment &sg1 : _file.segments) {
393 for (const Segment &sg2 : _file.segments) {
394 if (&sg1 == &sg2)
395 continue;
396 if (overlaps(sg1,sg2)) {
Rafael Espindola372bc702014-06-13 17:20:48 +0000397 _ec = make_error_code(llvm::errc::executable_format_error);
Nick Kledzike34182f2013-11-06 21:36:55 +0000398 return;
399 }
400 }
401 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000402
403 // Verify no sections overlap
Nick Kledzike34182f2013-11-06 21:36:55 +0000404 for (const Section &s1 : _file.sections) {
405 for (const Section &s2 : _file.sections) {
406 if (&s1 == &s2)
407 continue;
408 if (overlaps(s1,s2)) {
Rafael Espindola372bc702014-06-13 17:20:48 +0000409 _ec = make_error_code(llvm::errc::executable_format_error);
Nick Kledzike34182f2013-11-06 21:36:55 +0000410 return;
411 }
412 }
413 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000414
Nick Kledzike34182f2013-11-06 21:36:55 +0000415 // Build side table of extra info about segments and sections.
416 SegExtraInfo t;
417 t.fileOffset = 0;
418 for (const Segment &sg : _file.segments) {
419 _segInfo[&sg] = t;
420 }
421 SectionExtraInfo t2;
422 t2.fileOffset = 0;
423 // Assign sections to segments.
424 for (const Section &s : _file.sections) {
425 _sectInfo[&s] = t2;
426 for (const Segment &sg : _file.segments) {
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000427 if ((s.address >= sg.address)
Nick Kledzike34182f2013-11-06 21:36:55 +0000428 && (s.address+s.content.size() <= sg.address+sg.size)) {
429 if (!sg.name.equals(s.segmentName)) {
Rafael Espindola372bc702014-06-13 17:20:48 +0000430 _ec = make_error_code(llvm::errc::executable_format_error);
Nick Kledzike34182f2013-11-06 21:36:55 +0000431 return;
432 }
433 _segInfo[&sg].sections.push_back(&s);
434 }
435 }
436 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000437
Nick Kledzike34182f2013-11-06 21:36:55 +0000438 // Assign file offsets.
439 uint32_t fileOffset = 0;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000440 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000441 llvm::dbgs() << "buildFileOffsets()\n");
442 for (const Segment &sg : _file.segments) {
Tim Northover08d6a7b2014-06-30 09:49:30 +0000443 _segInfo[&sg].fileOffset = fileOffset;
Nick Kledzike34182f2013-11-06 21:36:55 +0000444 if ((_seg1addr == INT64_MAX) && sg.access)
445 _seg1addr = sg.address;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000446 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000447 llvm::dbgs() << " segment=" << sg.name
448 << ", fileOffset=" << _segInfo[&sg].fileOffset << "\n");
Tim Northover08d6a7b2014-06-30 09:49:30 +0000449
450 uint32_t segFileSize = 0;
Nick Kledzike34182f2013-11-06 21:36:55 +0000451 for (const Section *s : _segInfo[&sg].sections) {
Tim Northover08d6a7b2014-06-30 09:49:30 +0000452 uint32_t sectOffset = s->address - sg.address;
453 uint32_t sectFileSize =
454 s->type == llvm::MachO::S_ZEROFILL ? 0 : s->content.size();
455 segFileSize = std::max(segFileSize, sectOffset + sectFileSize);
456
457 _sectInfo[s].fileOffset = _segInfo[&sg].fileOffset + sectOffset;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000458 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000459 llvm::dbgs() << " section=" << s->sectionName
460 << ", fileOffset=" << fileOffset << "\n");
461 }
Tim Northover08d6a7b2014-06-30 09:49:30 +0000462
463 // FIXME: 4096 should be inferred from segments in normalized file.
464 _segInfo[&sg].fileSize = llvm::RoundUpToAlignment(segFileSize, 4096);
465 fileOffset = llvm::RoundUpToAlignment(fileOffset + segFileSize, 4096);
Nick Kledzike34182f2013-11-06 21:36:55 +0000466 _addressOfLinkEdit = sg.address + sg.size;
467 }
Tim Northover08d6a7b2014-06-30 09:49:30 +0000468 _startOfLinkEdit = fileOffset;
Nick Kledzike34182f2013-11-06 21:36:55 +0000469}
470
471
472size_t MachOFileLayout::size() const {
473 return _endOfSymbolStrings;
474}
475
476void MachOFileLayout::writeMachHeader() {
477 mach_header *mh = reinterpret_cast<mach_header*>(_buffer);
478 mh->magic = _is64 ? llvm::MachO::MH_MAGIC_64 : llvm::MachO::MH_MAGIC;
479 mh->cputype = MachOLinkingContext::cpuTypeFromArch(_file.arch);
480 mh->cpusubtype = MachOLinkingContext::cpuSubtypeFromArch(_file.arch);
481 mh->filetype = _file.fileType;
482 mh->ncmds = _countOfLoadCommands;
483 mh->sizeofcmds = _endOfLoadCommands - _startOfLoadCommands;
484 mh->flags = _file.flags;
485 if (_swap)
486 swapStruct(*mh);
487}
488
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000489uint32_t MachOFileLayout::indirectSymbolIndex(const Section &sect,
Nick Kledzike34182f2013-11-06 21:36:55 +0000490 uint32_t &index) {
491 if (sect.indirectSymbols.empty())
492 return 0;
493 uint32_t result = index;
494 index += sect.indirectSymbols.size();
495 return result;
496}
497
498uint32_t MachOFileLayout::indirectSymbolElementSize(const Section &sect) {
499 if (sect.indirectSymbols.empty())
500 return 0;
501 if (sect.type != S_SYMBOL_STUBS)
502 return 0;
503 return sect.content.size() / sect.indirectSymbols.size();
504}
505
Nick Kledzik29f749e2013-11-09 00:07:28 +0000506template <typename T>
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000507std::error_code MachOFileLayout::writeSingleSegmentLoadCommand(uint8_t *&lc) {
Nick Kledzik29f749e2013-11-09 00:07:28 +0000508 typename T::command* seg = reinterpret_cast<typename T::command*>(lc);
509 seg->cmd = T::LC;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000510 seg->cmdsize = sizeof(typename T::command)
Nick Kledzik29f749e2013-11-09 00:07:28 +0000511 + _file.sections.size() * sizeof(typename T::section);
Nick Kledzike34182f2013-11-06 21:36:55 +0000512 uint8_t *next = lc + seg->cmdsize;
513 memset(seg->segname, 0, 16);
514 seg->vmaddr = 0;
515 seg->vmsize = _endOfSectionsContent - _endOfLoadCommands;
516 seg->fileoff = _endOfLoadCommands;
517 seg->filesize = seg->vmsize;
518 seg->maxprot = VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE;
519 seg->initprot = VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE;
520 seg->nsects = _file.sections.size();
521 seg->flags = 0;
522 if (_swap)
523 swapStruct(*seg);
Nick Kledzik29f749e2013-11-09 00:07:28 +0000524 typename T::section *sout = reinterpret_cast<typename T::section*>
525 (lc+sizeof(typename T::command));
Nick Kledzike34182f2013-11-06 21:36:55 +0000526 uint32_t relOffset = _startOfRelocations;
527 uint32_t contentOffset = _startOfSectionsContent;
528 uint32_t indirectSymRunningIndex = 0;
529 for (const Section &sin : _file.sections) {
530 setString16(sin.sectionName, sout->sectname);
531 setString16(sin.segmentName, sout->segname);
532 sout->addr = sin.address;
533 sout->size = sin.content.size();
534 sout->offset = contentOffset;
535 sout->align = sin.alignment;
536 sout->reloff = sin.relocations.empty() ? 0 : relOffset;
537 sout->nreloc = sin.relocations.size();
538 sout->flags = sin.type | sin.attributes;
539 sout->reserved1 = indirectSymbolIndex(sin, indirectSymRunningIndex);
540 sout->reserved2 = indirectSymbolElementSize(sin);
541 relOffset += sin.relocations.size() * sizeof(any_relocation_info);
542 contentOffset += sin.content.size();
543 if (_swap)
544 swapStruct(*sout);
545 ++sout;
546 }
547 lc = next;
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000548 return std::error_code();
Nick Kledzike34182f2013-11-06 21:36:55 +0000549}
550
Nick Kledzik29f749e2013-11-09 00:07:28 +0000551template <typename T>
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000552std::error_code MachOFileLayout::writeSegmentLoadCommands(uint8_t *&lc) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000553 uint32_t indirectSymRunningIndex = 0;
554 for (const Segment &seg : _file.segments) {
555 // Write segment command with trailing sections.
556 SegExtraInfo &segInfo = _segInfo[&seg];
Nick Kledzik29f749e2013-11-09 00:07:28 +0000557 typename T::command* cmd = reinterpret_cast<typename T::command*>(lc);
558 cmd->cmd = T::LC;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000559 cmd->cmdsize = sizeof(typename T::command)
Nick Kledzik29f749e2013-11-09 00:07:28 +0000560 + segInfo.sections.size() * sizeof(typename T::section);
Nick Kledzike34182f2013-11-06 21:36:55 +0000561 uint8_t *next = lc + cmd->cmdsize;
562 setString16(seg.name, cmd->segname);
563 cmd->vmaddr = seg.address;
564 cmd->vmsize = seg.size;
565 cmd->fileoff = segInfo.fileOffset;
Tim Northover08d6a7b2014-06-30 09:49:30 +0000566 cmd->filesize = segInfo.fileSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000567 cmd->maxprot = seg.access;
568 cmd->initprot = seg.access;
569 cmd->nsects = segInfo.sections.size();
570 cmd->flags = 0;
571 if (_swap)
572 swapStruct(*cmd);
Nick Kledzik29f749e2013-11-09 00:07:28 +0000573 typename T::section *sect = reinterpret_cast<typename T::section*>
574 (lc+sizeof(typename T::command));
Nick Kledzike34182f2013-11-06 21:36:55 +0000575 for (const Section *section : segInfo.sections) {
576 setString16(section->sectionName, sect->sectname);
577 setString16(section->segmentName, sect->segname);
578 sect->addr = section->address;
579 sect->size = section->content.size();
580 sect->offset = section->address - seg.address + segInfo.fileOffset;
581 sect->align = section->alignment;
582 sect->reloff = 0;
583 sect->nreloc = 0;
584 sect->flags = section->type | section->attributes;
585 sect->reserved1 = indirectSymbolIndex(*section, indirectSymRunningIndex);
586 sect->reserved2 = indirectSymbolElementSize(*section);
587 if (_swap)
588 swapStruct(*sect);
589 ++sect;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000590 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000591 lc = reinterpret_cast<uint8_t*>(next);
592 }
593 // Add implicit __LINKEDIT segment
Nick Kledzik29f749e2013-11-09 00:07:28 +0000594 typename T::command* cmd = reinterpret_cast<typename T::command*>(lc);
595 cmd->cmd = T::LC;
596 cmd->cmdsize = sizeof(typename T::command);
Nick Kledzike34182f2013-11-06 21:36:55 +0000597 uint8_t *next = lc + cmd->cmdsize;
598 setString16("__LINKEDIT", cmd->segname);
599 cmd->vmaddr = _addressOfLinkEdit;
600 cmd->vmsize = _endOfLinkEdit - _startOfLinkEdit;
601 cmd->fileoff = _startOfLinkEdit;
602 cmd->filesize = _endOfLinkEdit - _startOfLinkEdit;
603 cmd->maxprot = VM_PROT_READ;
604 cmd->initprot = VM_PROT_READ;
605 cmd->nsects = 0;
606 cmd->flags = 0;
607 if (_swap)
608 swapStruct(*cmd);
609 lc = next;
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000610 return std::error_code();
Nick Kledzike34182f2013-11-06 21:36:55 +0000611}
612
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000613std::error_code MachOFileLayout::writeLoadCommands() {
614 std::error_code ec;
Nick Kledzike34182f2013-11-06 21:36:55 +0000615 uint8_t *lc = &_buffer[_startOfLoadCommands];
616 if (_file.fileType == llvm::MachO::MH_OBJECT) {
617 // Object files have one unnamed segment which holds all sections.
618 if (_is64)
Nick Kledzik29f749e2013-11-09 00:07:28 +0000619 ec = writeSingleSegmentLoadCommand<MachO64Trait>(lc);
Nick Kledzike34182f2013-11-06 21:36:55 +0000620 else
Nick Kledzik29f749e2013-11-09 00:07:28 +0000621 ec = writeSingleSegmentLoadCommand<MachO32Trait>(lc);
Nick Kledzike34182f2013-11-06 21:36:55 +0000622 // Add LC_SYMTAB with symbol table info
623 symtab_command* st = reinterpret_cast<symtab_command*>(lc);
624 st->cmd = LC_SYMTAB;
625 st->cmdsize = sizeof(symtab_command);
626 st->symoff = _startOfSymbols;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000627 st->nsyms = _file.localSymbols.size() + _file.globalSymbols.size()
Nick Kledzike34182f2013-11-06 21:36:55 +0000628 + _file.undefinedSymbols.size();
629 st->stroff = _startOfSymbolStrings;
630 st->strsize = _endOfSymbolStrings - _startOfSymbolStrings;
631 if (_swap)
632 swapStruct(*st);
Nick Kledzik21921372014-07-24 23:06:56 +0000633 lc += sizeof(symtab_command);
634 // Add LC_DATA_IN_CODE if needed.
635 if (_dataInCodeSize != 0) {
636 linkedit_data_command* dl = reinterpret_cast<linkedit_data_command*>(lc);
637 dl->cmd = LC_DATA_IN_CODE;
638 dl->cmdsize = sizeof(linkedit_data_command);
639 dl->dataoff = _startOfDataInCode;
640 dl->datasize = _dataInCodeSize;
641 if (_swap)
642 swapStruct(*dl);
643 lc += sizeof(linkedit_data_command);
644 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000645 } else {
646 // Final linked images have sections under segments.
647 if (_is64)
Nick Kledzik29f749e2013-11-09 00:07:28 +0000648 ec = writeSegmentLoadCommands<MachO64Trait>(lc);
Nick Kledzike34182f2013-11-06 21:36:55 +0000649 else
Nick Kledzik29f749e2013-11-09 00:07:28 +0000650 ec = writeSegmentLoadCommands<MachO32Trait>(lc);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000651
Tim Northover301c4e62014-07-01 08:15:41 +0000652 // Add LC_ID_DYLIB command for dynamic libraries.
653 if (_file.fileType == llvm::MachO::MH_DYLIB) {
654 dylib_command *dc = reinterpret_cast<dylib_command*>(lc);
655 StringRef path = _file.installName;
656 uint32_t size = sizeof(dylib_command) + pointerAlign(path.size() + 1);
657 dc->cmd = LC_ID_DYLIB;
658 dc->cmdsize = size;
659 dc->dylib.name = sizeof(dylib_command); // offset
660 dc->dylib.timestamp = 0; // FIXME
661 dc->dylib.current_version = 0; // FIXME
662 dc->dylib.compatibility_version = 0; // FIXME
663 if (_swap)
664 swapStruct(*dc);
665 memcpy(lc + sizeof(dylib_command), path.begin(), path.size());
666 lc[sizeof(dylib_command) + path.size()] = '\0';
667 lc += size;
668 }
669
Nick Kledzike34182f2013-11-06 21:36:55 +0000670 // Add LC_DYLD_INFO_ONLY.
671 dyld_info_command* di = reinterpret_cast<dyld_info_command*>(lc);
672 di->cmd = LC_DYLD_INFO_ONLY;
673 di->cmdsize = sizeof(dyld_info_command);
674 di->rebase_off = _rebaseInfo.size() ? _startOfRebaseInfo : 0;
675 di->rebase_size = _rebaseInfo.size();
676 di->bind_off = _bindingInfo.size() ? _startOfBindingInfo : 0;
677 di->bind_size = _bindingInfo.size();
678 di->weak_bind_off = 0;
679 di->weak_bind_size = 0;
680 di->lazy_bind_off = _lazyBindingInfo.size() ? _startOfLazyBindingInfo : 0;
681 di->lazy_bind_size = _lazyBindingInfo.size();
682 di->export_off = 0;
683 di->export_size = 0;
684 if (_swap)
685 swapStruct(*di);
686 lc += sizeof(dyld_info_command);
687
688 // Add LC_SYMTAB with symbol table info.
689 symtab_command* st = reinterpret_cast<symtab_command*>(lc);
690 st->cmd = LC_SYMTAB;
691 st->cmdsize = sizeof(symtab_command);
692 st->symoff = _startOfSymbols;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000693 st->nsyms = _file.localSymbols.size() + _file.globalSymbols.size()
Nick Kledzike34182f2013-11-06 21:36:55 +0000694 + _file.undefinedSymbols.size();
695 st->stroff = _startOfSymbolStrings;
696 st->strsize = _endOfSymbolStrings - _startOfSymbolStrings;
697 if (_swap)
698 swapStruct(*st);
699 lc += sizeof(symtab_command);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000700
Nick Kledzike34182f2013-11-06 21:36:55 +0000701 // Add LC_DYSYMTAB
702 if (_file.fileType != llvm::MachO::MH_PRELOAD) {
703 dysymtab_command* dst = reinterpret_cast<dysymtab_command*>(lc);
704 dst->cmd = LC_DYSYMTAB;
705 dst->cmdsize = sizeof(dysymtab_command);
706 dst->ilocalsym = _symbolTableLocalsStartIndex;
707 dst->nlocalsym = _file.localSymbols.size();
708 dst->iextdefsym = _symbolTableGlobalsStartIndex;
709 dst->nextdefsym = _file.globalSymbols.size();
710 dst->iundefsym = _symbolTableUndefinesStartIndex;
711 dst->nundefsym = _file.undefinedSymbols.size();
712 dst->tocoff = 0;
713 dst->ntoc = 0;
714 dst->modtaboff = 0;
715 dst->nmodtab = 0;
716 dst->extrefsymoff = 0;
717 dst->nextrefsyms = 0;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000718 dst->indirectsymoff = _startOfIndirectSymbols;
Nick Kledzike34182f2013-11-06 21:36:55 +0000719 dst->nindirectsyms = _indirectSymbolTableCount;
720 dst->extreloff = 0;
721 dst->nextrel = 0;
722 dst->locreloff = 0;
723 dst->nlocrel = 0;
724 if (_swap)
725 swapStruct(*dst);
726 lc += sizeof(dysymtab_command);
727 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000728
Nick Kledzike34182f2013-11-06 21:36:55 +0000729 // If main executable, add LC_LOAD_DYLINKER and LC_MAIN.
730 if (_file.fileType == llvm::MachO::MH_EXECUTE) {
731 // Build LC_LOAD_DYLINKER load command.
732 uint32_t size=pointerAlign(sizeof(dylinker_command)+dyldPath().size()+1);
733 dylinker_command* dl = reinterpret_cast<dylinker_command*>(lc);
734 dl->cmd = LC_LOAD_DYLINKER;
735 dl->cmdsize = size;
736 dl->name = sizeof(dylinker_command); // offset
737 if (_swap)
738 swapStruct(*dl);
739 memcpy(lc+sizeof(dylinker_command), dyldPath().data(), dyldPath().size());
740 lc[sizeof(dylinker_command)+dyldPath().size()] = '\0';
741 lc += size;
742 // Build LC_MAIN load command.
743 entry_point_command* ep = reinterpret_cast<entry_point_command*>(lc);
744 ep->cmd = LC_MAIN;
745 ep->cmdsize = sizeof(entry_point_command);
746 ep->entryoff = _file.entryAddress - _seg1addr;
747 ep->stacksize = 0;
748 if (_swap)
749 swapStruct(*ep);
750 lc += sizeof(entry_point_command);
751 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000752
Nick Kledzike34182f2013-11-06 21:36:55 +0000753 // Add LC_LOAD_DYLIB commands
754 for (const DependentDylib &dep : _file.dependentDylibs) {
755 dylib_command* dc = reinterpret_cast<dylib_command*>(lc);
756 uint32_t size = sizeof(dylib_command) + pointerAlign(dep.path.size()+1);
757 dc->cmd = LC_LOAD_DYLIB;
758 dc->cmdsize = size;
759 dc->dylib.name = sizeof(dylib_command); // offset
760 dc->dylib.timestamp = 0; // FIXME
761 dc->dylib.current_version = 0; // FIXME
762 dc->dylib.compatibility_version = 0; // FIXME
763 if (_swap)
764 swapStruct(*dc);
765 memcpy(lc+sizeof(dylib_command), dep.path.begin(), dep.path.size());
766 lc[sizeof(dylib_command)+dep.path.size()] = '\0';
767 lc += size;
768 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000769 }
770 return ec;
771}
772
773
774void MachOFileLayout::writeSectionContent() {
775 for (const Section &s : _file.sections) {
776 // Copy all section content to output buffer.
Nick Kledzik61fdef62014-05-15 20:59:23 +0000777 if (s.type == llvm::MachO::S_ZEROFILL)
778 continue;
Nick Kledzike34182f2013-11-06 21:36:55 +0000779 uint32_t offset = _sectInfo[&s].fileOffset;
780 uint8_t *p = &_buffer[offset];
781 memcpy(p, &s.content[0], s.content.size());
782 p += s.content.size();
783 }
784}
785
786void MachOFileLayout::writeRelocations() {
787 uint32_t relOffset = _startOfRelocations;
788 for (Section sect : _file.sections) {
789 for (Relocation r : sect.relocations) {
790 any_relocation_info* rb = reinterpret_cast<any_relocation_info*>(
791 &_buffer[relOffset]);
792 *rb = packRelocation(r, _swap, _bigEndianArch);
793 relOffset += sizeof(any_relocation_info);
794 }
795 }
796}
797
798
799void MachOFileLayout::appendSymbols(const std::vector<Symbol> &symbols,
800 uint32_t &symOffset, uint32_t &strOffset) {
801 for (const Symbol &sym : symbols) {
802 if (_is64) {
803 nlist_64* nb = reinterpret_cast<nlist_64*>(&_buffer[symOffset]);
804 nb->n_strx = strOffset - _startOfSymbolStrings;
805 nb->n_type = sym.type | sym.scope;
806 nb->n_sect = sym.sect;
807 nb->n_desc = sym.desc;
808 nb->n_value = sym.value;
809 if (_swap)
810 swapStruct(*nb);
811 symOffset += sizeof(nlist_64);
812 } else {
813 nlist* nb = reinterpret_cast<nlist*>(&_buffer[symOffset]);
814 nb->n_strx = strOffset - _startOfSymbolStrings;
815 nb->n_type = sym.type | sym.scope;
816 nb->n_sect = sym.sect;
817 nb->n_desc = sym.desc;
818 nb->n_value = sym.value;
819 if (_swap)
820 swapStruct(*nb);
821 symOffset += sizeof(nlist);
822 }
823 memcpy(&_buffer[strOffset], sym.name.begin(), sym.name.size());
824 strOffset += sym.name.size();
825 _buffer[strOffset++] ='\0'; // Strings in table have nul terminator.
826 }
827}
828
Nick Kledzik21921372014-07-24 23:06:56 +0000829void MachOFileLayout::writeDataInCodeInfo() {
830 uint32_t offset = _startOfDataInCode;
831 for (const DataInCode &entry : _file.dataInCode) {
832 data_in_code_entry *dst = reinterpret_cast<data_in_code_entry*>(
833 &_buffer[offset]);
834 dst->offset = entry.offset;
835 dst->length = entry.length;
836 dst->kind = entry.kind;
837 if (_swap)
838 swapStruct(*dst);
839 offset += sizeof(data_in_code_entry);
840 }
841}
842
Nick Kledzike34182f2013-11-06 21:36:55 +0000843void MachOFileLayout::writeSymbolTable() {
844 // Write symbol table and symbol strings in parallel.
845 uint32_t symOffset = _startOfSymbols;
846 uint32_t strOffset = _startOfSymbolStrings;
847 _buffer[strOffset++] = '\0'; // Reserve n_strx offset of zero to mean no name.
848 appendSymbols(_file.localSymbols, symOffset, strOffset);
849 appendSymbols(_file.globalSymbols, symOffset, strOffset);
850 appendSymbols(_file.undefinedSymbols, symOffset, strOffset);
851 // Write indirect symbol table array.
852 uint32_t *indirects = reinterpret_cast<uint32_t*>
853 (&_buffer[_startOfIndirectSymbols]);
854 if (_file.fileType == llvm::MachO::MH_OBJECT) {
855 // Object files have sections in same order as input normalized file.
856 for (const Section &section : _file.sections) {
857 for (uint32_t index : section.indirectSymbols) {
858 if (_swap)
Artyom Skrobov17587fb2014-06-14 12:40:04 +0000859 *indirects++ = llvm::sys::getSwappedBytes(index);
Nick Kledzike34182f2013-11-06 21:36:55 +0000860 else
861 *indirects++ = index;
862 }
863 }
864 } else {
865 // Final linked images must sort sections from normalized file.
866 for (const Segment &seg : _file.segments) {
867 SegExtraInfo &segInfo = _segInfo[&seg];
868 for (const Section *section : segInfo.sections) {
869 for (uint32_t index : section->indirectSymbols) {
870 if (_swap)
Artyom Skrobov17587fb2014-06-14 12:40:04 +0000871 *indirects++ = llvm::sys::getSwappedBytes(index);
Nick Kledzike34182f2013-11-06 21:36:55 +0000872 else
873 *indirects++ = index;
874 }
875 }
876 }
877 }
878}
879
880void MachOFileLayout::writeRebaseInfo() {
881 memcpy(&_buffer[_startOfRebaseInfo], _rebaseInfo.bytes(), _rebaseInfo.size());
882}
883
884void MachOFileLayout::writeBindingInfo() {
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000885 memcpy(&_buffer[_startOfBindingInfo],
Nick Kledzike34182f2013-11-06 21:36:55 +0000886 _bindingInfo.bytes(), _bindingInfo.size());
887}
888
889void MachOFileLayout::writeLazyBindingInfo() {
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000890 memcpy(&_buffer[_startOfLazyBindingInfo],
Nick Kledzike34182f2013-11-06 21:36:55 +0000891 _lazyBindingInfo.bytes(), _lazyBindingInfo.size());
892}
893
894void MachOFileLayout::buildLinkEditInfo() {
895 buildRebaseInfo();
896 buildBindInfo();
897 buildLazyBindInfo();
898 computeSymbolTableSizes();
Nick Kledzik21921372014-07-24 23:06:56 +0000899 computeDataInCodeSize();
Nick Kledzike34182f2013-11-06 21:36:55 +0000900}
901
902void MachOFileLayout::buildSectionRelocations() {
903
904}
905
906void MachOFileLayout::buildRebaseInfo() {
907 // TODO: compress rebasing info.
908 for (const RebaseLocation& entry : _file.rebasingInfo) {
909 _rebaseInfo.append_byte(REBASE_OPCODE_SET_TYPE_IMM | entry.kind);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000910 _rebaseInfo.append_byte(REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
Nick Kledzike34182f2013-11-06 21:36:55 +0000911 | entry.segIndex);
912 _rebaseInfo.append_uleb128(entry.segOffset);
913 _rebaseInfo.append_uleb128(REBASE_OPCODE_DO_REBASE_IMM_TIMES | 1);
914 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000915 _rebaseInfo.append_byte(REBASE_OPCODE_DONE);
Nick Kledzike34182f2013-11-06 21:36:55 +0000916 _rebaseInfo.align(_is64 ? 8 : 4);
917}
918
919void MachOFileLayout::buildBindInfo() {
920 // TODO: compress bind info.
921 for (const BindLocation& entry : _file.bindingInfo) {
922 _bindingInfo.append_byte(BIND_OPCODE_SET_TYPE_IMM | entry.kind);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000923 _bindingInfo.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
Nick Kledzike34182f2013-11-06 21:36:55 +0000924 | entry.segIndex);
925 _bindingInfo.append_uleb128(entry.segOffset);
926 _bindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM | entry.ordinal);
927 _bindingInfo.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM);
928 _bindingInfo.append_string(entry.symbolName);
929 if (entry.addend != 0) {
930 _bindingInfo.append_byte(BIND_OPCODE_SET_ADDEND_SLEB);
931 _bindingInfo.append_sleb128(entry.addend);
932 }
933 _bindingInfo.append_byte(BIND_OPCODE_DO_BIND);
934 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000935 _bindingInfo.append_byte(BIND_OPCODE_DONE);
Nick Kledzike34182f2013-11-06 21:36:55 +0000936 _bindingInfo.align(_is64 ? 8 : 4);
937}
938
939void MachOFileLayout::buildLazyBindInfo() {
940 for (const BindLocation& entry : _file.lazyBindingInfo) {
941 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_TYPE_IMM | entry.kind);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000942 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
Nick Kledzike34182f2013-11-06 21:36:55 +0000943 | entry.segIndex);
944 _lazyBindingInfo.append_uleb128(entry.segOffset);
945 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM | entry.ordinal);
946 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM);
947 _lazyBindingInfo.append_string(entry.symbolName);
948 _lazyBindingInfo.append_byte(BIND_OPCODE_DO_BIND);
949 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000950 _lazyBindingInfo.append_byte(BIND_OPCODE_DONE);
Nick Kledzike34182f2013-11-06 21:36:55 +0000951 _lazyBindingInfo.align(_is64 ? 8 : 4);
952}
953
954void MachOFileLayout::computeSymbolTableSizes() {
955 // MachO symbol tables have three ranges: locals, globals, and undefines
956 const size_t nlistSize = (_is64 ? sizeof(nlist_64) : sizeof(nlist));
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000957 _symbolTableSize = nlistSize * (_file.localSymbols.size()
Nick Kledzike34182f2013-11-06 21:36:55 +0000958 + _file.globalSymbols.size()
959 + _file.undefinedSymbols.size());
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000960 _symbolStringPoolSize = 0;
Nick Kledzike34182f2013-11-06 21:36:55 +0000961 for (const Symbol &sym : _file.localSymbols) {
962 _symbolStringPoolSize += (sym.name.size()+1);
963 }
964 for (const Symbol &sym : _file.globalSymbols) {
965 _symbolStringPoolSize += (sym.name.size()+1);
966 }
967 for (const Symbol &sym : _file.undefinedSymbols) {
968 _symbolStringPoolSize += (sym.name.size()+1);
969 }
970 _symbolTableLocalsStartIndex = 0;
971 _symbolTableGlobalsStartIndex = _file.localSymbols.size();
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000972 _symbolTableUndefinesStartIndex = _symbolTableGlobalsStartIndex
Nick Kledzike34182f2013-11-06 21:36:55 +0000973 + _file.globalSymbols.size();
974
975 _indirectSymbolTableCount = 0;
976 for (const Section &sect : _file.sections) {
977 _indirectSymbolTableCount += sect.indirectSymbols.size();
978 }
979}
980
Nick Kledzik21921372014-07-24 23:06:56 +0000981void MachOFileLayout::computeDataInCodeSize() {
982 _dataInCodeSize = _file.dataInCode.size() * sizeof(data_in_code_entry);
983}
Nick Kledzike34182f2013-11-06 21:36:55 +0000984
985void MachOFileLayout::writeLinkEditContent() {
986 if (_file.fileType == llvm::MachO::MH_OBJECT) {
987 writeRelocations();
Nick Kledzik21921372014-07-24 23:06:56 +0000988 writeDataInCodeInfo();
Nick Kledzike34182f2013-11-06 21:36:55 +0000989 writeSymbolTable();
990 } else {
991 writeRebaseInfo();
992 writeBindingInfo();
993 writeLazyBindingInfo();
994 // TODO: add weak binding info
995 writeSymbolTable();
996 }
997}
998
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000999std::error_code MachOFileLayout::writeBinary(StringRef path) {
Nick Kledzike34182f2013-11-06 21:36:55 +00001000 // Check for pending error from constructor.
1001 if (_ec)
1002 return _ec;
1003 // Create FileOutputBuffer with calculated size.
Ahmed Charles13c70b62014-03-13 16:20:38 +00001004 std::unique_ptr<llvm::FileOutputBuffer> fob;
Nick Kledzike34182f2013-11-06 21:36:55 +00001005 unsigned flags = 0;
1006 if (_file.fileType != llvm::MachO::MH_OBJECT)
1007 flags = llvm::FileOutputBuffer::F_executable;
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +00001008 std::error_code ec;
Nick Kledzike34182f2013-11-06 21:36:55 +00001009 ec = llvm::FileOutputBuffer::create(path, size(), fob, flags);
1010 if (ec)
1011 return ec;
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001012
Nick Kledzike34182f2013-11-06 21:36:55 +00001013 // Write content.
1014 _buffer = fob->getBufferStart();
1015 writeMachHeader();
1016 ec = writeLoadCommands();
1017 if (ec)
1018 return ec;
1019 writeSectionContent();
1020 writeLinkEditContent();
1021 fob->commit();
1022
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +00001023 return std::error_code();
Nick Kledzike34182f2013-11-06 21:36:55 +00001024}
1025
1026
1027
1028/// Takes in-memory normalized view and writes a mach-o object file.
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +00001029std::error_code writeBinary(const NormalizedFile &file, StringRef path) {
Nick Kledzike34182f2013-11-06 21:36:55 +00001030 MachOFileLayout layout(file);
1031 return layout.writeBinary(path);
1032}
1033
1034
1035} // namespace normalized
1036} // namespace mach_o
1037} // namespace lld
1038