blob: a3542c4fc5015ac05ae3a23bab04fde3f7860cd0 [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"
32#include "llvm/Support/Debug.h"
Shankar Easwaran2b67fca2014-10-18 05:33:55 +000033#include "llvm/Support/Errc.h"
Nick Kledzike34182f2013-11-06 21:36:55 +000034#include "llvm/Support/ErrorHandling.h"
35#include "llvm/Support/FileOutputBuffer.h"
Nick Kledzik141330a2014-09-03 19:52:50 +000036#include "llvm/Support/Format.h"
Nick Kledzike34182f2013-11-06 21:36:55 +000037#include "llvm/Support/Host.h"
Nick Kledzik00a15d92013-11-09 01:00:51 +000038#include "llvm/Support/LEB128.h"
Nick Kledzike34182f2013-11-06 21:36:55 +000039#include "llvm/Support/MachO.h"
40#include "llvm/Support/MemoryBuffer.h"
41#include "llvm/Support/raw_ostream.h"
Nick Kledzike34182f2013-11-06 21:36:55 +000042#include <functional>
Nick Kledzik07ba5122014-12-02 01:50:44 +000043#include <list>
Nick Kledzike34182f2013-11-06 21:36:55 +000044#include <map>
Rafael Espindola54427cc2014-06-12 17:15:58 +000045#include <system_error>
Nick Kledzike34182f2013-11-06 21:36:55 +000046
47using namespace llvm::MachO;
48
49namespace lld {
50namespace mach_o {
51namespace normalized {
52
53/// Utility class for writing a mach-o binary file given an in-memory
Shankar Easwaran3d8de472014-01-27 03:09:26 +000054/// normalized file.
Nick Kledzike34182f2013-11-06 21:36:55 +000055class MachOFileLayout {
56public:
Joey Goulyb275d7f2013-12-23 23:29:50 +000057 /// All layout computation is done in the constructor.
58 MachOFileLayout(const NormalizedFile &file);
59
Nick Kledzike34182f2013-11-06 21:36:55 +000060 /// Returns the final file size as computed in the constructor.
61 size_t size() const;
62
Nick Kledzik2fcbe822014-07-30 00:58:06 +000063 // Returns size of the mach_header and load commands.
64 size_t headerAndLoadCommandsSize() const;
65
Shankar Easwaran3d8de472014-01-27 03:09:26 +000066 /// Writes the normalized file as a binary mach-o file to the specified
Nick Kledzike34182f2013-11-06 21:36:55 +000067 /// path. This does not have a stream interface because the generated
68 /// file may need the 'x' bit set.
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +000069 std::error_code writeBinary(StringRef path);
Shankar Easwaran3d8de472014-01-27 03:09:26 +000070
Nick Kledzike34182f2013-11-06 21:36:55 +000071private:
72 uint32_t loadCommandsSize(uint32_t &count);
73 void buildFileOffsets();
74 void writeMachHeader();
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +000075 std::error_code writeLoadCommands();
Nick Kledzike34182f2013-11-06 21:36:55 +000076 void writeSectionContent();
77 void writeRelocations();
78 void writeSymbolTable();
79 void writeRebaseInfo();
80 void writeBindingInfo();
81 void writeLazyBindingInfo();
Nick Kledzik141330a2014-09-03 19:52:50 +000082 void writeExportInfo();
Nick Kledzik21921372014-07-24 23:06:56 +000083 void writeDataInCodeInfo();
Nick Kledzike34182f2013-11-06 21:36:55 +000084 void writeLinkEditContent();
85 void buildLinkEditInfo();
86 void buildRebaseInfo();
87 void buildBindInfo();
88 void buildLazyBindInfo();
Nick Kledzik141330a2014-09-03 19:52:50 +000089 void buildExportTrie();
Nick Kledzik21921372014-07-24 23:06:56 +000090 void computeDataInCodeSize();
Nick Kledzike34182f2013-11-06 21:36:55 +000091 void computeSymbolTableSizes();
92 void buildSectionRelocations();
93 void appendSymbols(const std::vector<Symbol> &symbols,
94 uint32_t &symOffset, uint32_t &strOffset);
95 uint32_t indirectSymbolIndex(const Section &sect, uint32_t &index);
96 uint32_t indirectSymbolElementSize(const Section &sect);
97
Nick Kledzik29f749e2013-11-09 00:07:28 +000098 // For use as template parameter to load command methods.
99 struct MachO64Trait {
100 typedef llvm::MachO::segment_command_64 command;
101 typedef llvm::MachO::section_64 section;
102 enum { LC = llvm::MachO::LC_SEGMENT_64 };
103 };
104
105 // For use as template parameter to load command methods.
106 struct MachO32Trait {
107 typedef llvm::MachO::segment_command command;
108 typedef llvm::MachO::section section;
109 enum { LC = llvm::MachO::LC_SEGMENT };
110 };
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000111
Nick Kledzik29f749e2013-11-09 00:07:28 +0000112 template <typename T>
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000113 std::error_code writeSingleSegmentLoadCommand(uint8_t *&lc);
114 template <typename T> std::error_code writeSegmentLoadCommands(uint8_t *&lc);
Nick Kledzik29f749e2013-11-09 00:07:28 +0000115
Nick Kledzike34182f2013-11-06 21:36:55 +0000116 uint32_t pointerAlign(uint32_t value);
117 static StringRef dyldPath();
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000118
Nick Kledzike34182f2013-11-06 21:36:55 +0000119 class ByteBuffer {
120 public:
Nick Kledzik00a15d92013-11-09 01:00:51 +0000121 ByteBuffer() : _ostream(_bytes) { }
Nick Kledzik141330a2014-09-03 19:52:50 +0000122
Nick Kledzik00a15d92013-11-09 01:00:51 +0000123 void append_byte(uint8_t b) {
124 _ostream << b;
125 }
126 void append_uleb128(uint64_t value) {
127 llvm::encodeULEB128(value, _ostream);
128 }
Nick Kledzikf373c772014-11-11 01:31:18 +0000129 void append_uleb128Fixed(uint64_t value, unsigned byteCount) {
130 unsigned min = llvm::getULEB128Size(value);
131 assert(min <= byteCount);
132 unsigned pad = byteCount - min;
133 llvm::encodeULEB128(value, _ostream, pad);
134 }
Nick Kledzik00a15d92013-11-09 01:00:51 +0000135 void append_sleb128(int64_t value) {
136 llvm::encodeSLEB128(value, _ostream);
137 }
138 void append_string(StringRef str) {
139 _ostream << str;
140 append_byte(0);
141 }
142 void align(unsigned alignment) {
143 while ( (_ostream.tell() % alignment) != 0 )
144 append_byte(0);
145 }
146 size_t size() {
147 return _ostream.tell();
148 }
149 const uint8_t *bytes() {
150 return reinterpret_cast<const uint8_t*>(_ostream.str().data());
151 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000152 private:
Nick Kledzik00a15d92013-11-09 01:00:51 +0000153 SmallVector<char, 128> _bytes;
154 // Stream ivar must be after SmallVector ivar to construct properly.
155 llvm::raw_svector_ostream _ostream;
Nick Kledzike34182f2013-11-06 21:36:55 +0000156 };
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000157
Nick Kledzik141330a2014-09-03 19:52:50 +0000158 struct TrieNode; // Forward declaration.
159
160 struct TrieEdge {
161 TrieEdge(StringRef s, TrieNode *node) : _subString(s), _child(node) {}
162 ~TrieEdge() {}
163
164 StringRef _subString;
165 struct TrieNode *_child;
166 };
167
168 struct TrieNode {
169 TrieNode(StringRef s)
170 : _cummulativeString(s), _address(0), _flags(0), _other(0),
171 _trieOffset(0), _hasExportInfo(false) {}
172 ~TrieNode() {}
173
174 void addSymbol(const Export &entry, BumpPtrAllocator &allocator,
175 std::vector<TrieNode *> &allNodes);
176 bool updateOffset(uint32_t &offset);
177 void appendToByteBuffer(ByteBuffer &out);
178
179private:
180 StringRef _cummulativeString;
Nick Kledzik07ba5122014-12-02 01:50:44 +0000181 std::list<TrieEdge> _children;
Nick Kledzik141330a2014-09-03 19:52:50 +0000182 uint64_t _address;
183 uint64_t _flags;
184 uint64_t _other;
185 StringRef _importedName;
186 uint32_t _trieOffset;
187 bool _hasExportInfo;
188 };
Nick Kledzik00a15d92013-11-09 01:00:51 +0000189
Nick Kledzike34182f2013-11-06 21:36:55 +0000190 struct SegExtraInfo {
191 uint32_t fileOffset;
Tim Northover08d6a7b2014-06-30 09:49:30 +0000192 uint32_t fileSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000193 std::vector<const Section*> sections;
194 };
195 typedef std::map<const Segment*, SegExtraInfo> SegMap;
196 struct SectionExtraInfo {
197 uint32_t fileOffset;
198 };
199 typedef std::map<const Section*, SectionExtraInfo> SectionMap;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000200
Nick Kledzike34182f2013-11-06 21:36:55 +0000201 const NormalizedFile &_file;
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000202 std::error_code _ec;
Nick Kledzike34182f2013-11-06 21:36:55 +0000203 uint8_t *_buffer;
204 const bool _is64;
205 const bool _swap;
206 const bool _bigEndianArch;
207 uint64_t _seg1addr;
208 uint32_t _startOfLoadCommands;
209 uint32_t _countOfLoadCommands;
210 uint32_t _endOfLoadCommands;
211 uint32_t _startOfRelocations;
Nick Kledzik21921372014-07-24 23:06:56 +0000212 uint32_t _startOfDataInCode;
Nick Kledzike34182f2013-11-06 21:36:55 +0000213 uint32_t _startOfSymbols;
214 uint32_t _startOfIndirectSymbols;
215 uint32_t _startOfSymbolStrings;
216 uint32_t _endOfSymbolStrings;
217 uint32_t _symbolTableLocalsStartIndex;
218 uint32_t _symbolTableGlobalsStartIndex;
219 uint32_t _symbolTableUndefinesStartIndex;
220 uint32_t _symbolStringPoolSize;
221 uint32_t _symbolTableSize;
Nick Kledzik21921372014-07-24 23:06:56 +0000222 uint32_t _dataInCodeSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000223 uint32_t _indirectSymbolTableCount;
224 // Used in object file creation only
225 uint32_t _startOfSectionsContent;
226 uint32_t _endOfSectionsContent;
227 // Used in final linked image only
228 uint32_t _startOfLinkEdit;
229 uint32_t _startOfRebaseInfo;
230 uint32_t _endOfRebaseInfo;
231 uint32_t _startOfBindingInfo;
232 uint32_t _endOfBindingInfo;
233 uint32_t _startOfLazyBindingInfo;
234 uint32_t _endOfLazyBindingInfo;
Nick Kledzik141330a2014-09-03 19:52:50 +0000235 uint32_t _startOfExportTrie;
236 uint32_t _endOfExportTrie;
Nick Kledzike34182f2013-11-06 21:36:55 +0000237 uint32_t _endOfLinkEdit;
238 uint64_t _addressOfLinkEdit;
239 SegMap _segInfo;
240 SectionMap _sectInfo;
241 ByteBuffer _rebaseInfo;
242 ByteBuffer _bindingInfo;
243 ByteBuffer _lazyBindingInfo;
244 ByteBuffer _weakBindingInfo;
Nick Kledzik141330a2014-09-03 19:52:50 +0000245 ByteBuffer _exportTrie;
Nick Kledzike34182f2013-11-06 21:36:55 +0000246};
247
248size_t headerAndLoadCommandsSize(const NormalizedFile &file) {
249 MachOFileLayout layout(file);
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000250 return layout.headerAndLoadCommandsSize();
Nick Kledzike34182f2013-11-06 21:36:55 +0000251}
252
253StringRef MachOFileLayout::dyldPath() {
254 return "/usr/lib/dyld";
255}
256
257uint32_t MachOFileLayout::pointerAlign(uint32_t value) {
258 return llvm::RoundUpToAlignment(value, _is64 ? 8 : 4);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000259}
Nick Kledzike34182f2013-11-06 21:36:55 +0000260
261
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000262size_t MachOFileLayout::headerAndLoadCommandsSize() const {
263 return _endOfLoadCommands;
264}
Nick Kledzike34182f2013-11-06 21:36:55 +0000265
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000266
267MachOFileLayout::MachOFileLayout(const NormalizedFile &file)
Nick Kledzike34182f2013-11-06 21:36:55 +0000268 : _file(file),
269 _is64(MachOLinkingContext::is64Bit(file.arch)),
270 _swap(!MachOLinkingContext::isHostEndian(file.arch)),
271 _bigEndianArch(MachOLinkingContext::isBigEndian(file.arch)),
272 _seg1addr(INT64_MAX) {
273 _startOfLoadCommands = _is64 ? sizeof(mach_header_64) : sizeof(mach_header);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000274 const size_t segCommandBaseSize =
Nick Kledzike34182f2013-11-06 21:36:55 +0000275 (_is64 ? sizeof(segment_command_64) : sizeof(segment_command));
276 const size_t sectsSize = (_is64 ? sizeof(section_64) : sizeof(section));
277 if (file.fileType == llvm::MachO::MH_OBJECT) {
278 // object files have just one segment load command containing all sections
279 _endOfLoadCommands = _startOfLoadCommands
280 + segCommandBaseSize
281 + file.sections.size() * sectsSize
282 + sizeof(symtab_command);
283 _countOfLoadCommands = 2;
Nick Kledzik21921372014-07-24 23:06:56 +0000284 if (!_file.dataInCode.empty()) {
285 _endOfLoadCommands += sizeof(linkedit_data_command);
286 _countOfLoadCommands++;
287 }
Nick Kledzikb072c362014-11-18 00:30:29 +0000288 // Assign file offsets to each section.
Nick Kledzike34182f2013-11-06 21:36:55 +0000289 _startOfSectionsContent = _endOfLoadCommands;
Nick Kledzike34182f2013-11-06 21:36:55 +0000290 unsigned relocCount = 0;
Nick Kledzikb072c362014-11-18 00:30:29 +0000291 uint64_t offset = _startOfSectionsContent;
Nick Kledzike34182f2013-11-06 21:36:55 +0000292 for (const Section &sect : file.sections) {
Nick Kledzikb072c362014-11-18 00:30:29 +0000293 if (sect.type != llvm::MachO::S_ZEROFILL) {
294 offset = llvm::RoundUpToAlignment(offset, 1 << sect.alignment);
295 _sectInfo[&sect].fileOffset = offset;
296 offset += sect.content.size();
297 } else {
298 _sectInfo[&sect].fileOffset = 0;
299 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000300 relocCount += sect.relocations.size();
301 }
Nick Kledzikb072c362014-11-18 00:30:29 +0000302 _endOfSectionsContent = offset;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000303
Nick Kledzike34182f2013-11-06 21:36:55 +0000304 computeSymbolTableSizes();
Nick Kledzik21921372014-07-24 23:06:56 +0000305 computeDataInCodeSize();
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000306
Nick Kledzike34182f2013-11-06 21:36:55 +0000307 // Align start of relocations.
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000308 _startOfRelocations = pointerAlign(_endOfSectionsContent);
Nick Kledzik21921372014-07-24 23:06:56 +0000309 _startOfDataInCode = _startOfRelocations + relocCount * 8;
310 _startOfSymbols = _startOfDataInCode + _dataInCodeSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000311 // Add Indirect symbol table.
312 _startOfIndirectSymbols = _startOfSymbols + _symbolTableSize;
313 // Align start of symbol table and symbol strings.
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000314 _startOfSymbolStrings = _startOfIndirectSymbols
Nick Kledzike34182f2013-11-06 21:36:55 +0000315 + pointerAlign(_indirectSymbolTableCount * sizeof(uint32_t));
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000316 _endOfSymbolStrings = _startOfSymbolStrings
Nick Kledzike34182f2013-11-06 21:36:55 +0000317 + pointerAlign(_symbolStringPoolSize);
318 _endOfLinkEdit = _endOfSymbolStrings;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000319 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000320 llvm::dbgs() << "MachOFileLayout()\n"
321 << " startOfLoadCommands=" << _startOfLoadCommands << "\n"
322 << " countOfLoadCommands=" << _countOfLoadCommands << "\n"
323 << " endOfLoadCommands=" << _endOfLoadCommands << "\n"
324 << " startOfRelocations=" << _startOfRelocations << "\n"
325 << " startOfSymbols=" << _startOfSymbols << "\n"
326 << " startOfSymbolStrings=" << _startOfSymbolStrings << "\n"
327 << " endOfSymbolStrings=" << _endOfSymbolStrings << "\n"
328 << " startOfSectionsContent=" << _startOfSectionsContent << "\n"
329 << " endOfSectionsContent=" << _endOfSectionsContent << "\n");
330 } else {
331 // Final linked images have one load command per segment.
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000332 _endOfLoadCommands = _startOfLoadCommands
Nick Kledzike34182f2013-11-06 21:36:55 +0000333 + loadCommandsSize(_countOfLoadCommands);
334
335 // Assign section file offsets.
336 buildFileOffsets();
337 buildLinkEditInfo();
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000338
Nick Kledzike34182f2013-11-06 21:36:55 +0000339 // LINKEDIT of final linked images has in order:
340 // rebase info, binding info, lazy binding info, weak binding info,
Nick Kledzik21921372014-07-24 23:06:56 +0000341 // data-in-code, symbol table, indirect symbol table, symbol table strings.
Nick Kledzike34182f2013-11-06 21:36:55 +0000342 _startOfRebaseInfo = _startOfLinkEdit;
343 _endOfRebaseInfo = _startOfRebaseInfo + _rebaseInfo.size();
344 _startOfBindingInfo = _endOfRebaseInfo;
345 _endOfBindingInfo = _startOfBindingInfo + _bindingInfo.size();
346 _startOfLazyBindingInfo = _endOfBindingInfo;
347 _endOfLazyBindingInfo = _startOfLazyBindingInfo + _lazyBindingInfo.size();
Nick Kledzik141330a2014-09-03 19:52:50 +0000348 _startOfExportTrie = _endOfLazyBindingInfo;
349 _endOfExportTrie = _startOfExportTrie + _exportTrie.size();
350 _startOfDataInCode = _endOfExportTrie;
Nick Kledzik21921372014-07-24 23:06:56 +0000351 _startOfSymbols = _startOfDataInCode + _dataInCodeSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000352 _startOfIndirectSymbols = _startOfSymbols + _symbolTableSize;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000353 _startOfSymbolStrings = _startOfIndirectSymbols
Nick Kledzike34182f2013-11-06 21:36:55 +0000354 + pointerAlign(_indirectSymbolTableCount * sizeof(uint32_t));
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000355 _endOfSymbolStrings = _startOfSymbolStrings
Nick Kledzike34182f2013-11-06 21:36:55 +0000356 + pointerAlign(_symbolStringPoolSize);
357 _endOfLinkEdit = _endOfSymbolStrings;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000358 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000359 llvm::dbgs() << "MachOFileLayout()\n"
360 << " startOfLoadCommands=" << _startOfLoadCommands << "\n"
361 << " countOfLoadCommands=" << _countOfLoadCommands << "\n"
362 << " endOfLoadCommands=" << _endOfLoadCommands << "\n"
363 << " startOfLinkEdit=" << _startOfLinkEdit << "\n"
364 << " startOfRebaseInfo=" << _startOfRebaseInfo << "\n"
365 << " endOfRebaseInfo=" << _endOfRebaseInfo << "\n"
366 << " startOfBindingInfo=" << _startOfBindingInfo << "\n"
367 << " endOfBindingInfo=" << _endOfBindingInfo << "\n"
368 << " startOfLazyBindingInfo=" << _startOfLazyBindingInfo << "\n"
369 << " endOfLazyBindingInfo=" << _endOfLazyBindingInfo << "\n"
Nick Kledzik141330a2014-09-03 19:52:50 +0000370 << " startOfExportTrie=" << _startOfExportTrie << "\n"
371 << " endOfExportTrie=" << _endOfExportTrie << "\n"
Nick Kledzik21921372014-07-24 23:06:56 +0000372 << " startOfDataInCode=" << _startOfDataInCode << "\n"
Nick Kledzike34182f2013-11-06 21:36:55 +0000373 << " startOfSymbols=" << _startOfSymbols << "\n"
374 << " startOfSymbolStrings=" << _startOfSymbolStrings << "\n"
375 << " endOfSymbolStrings=" << _endOfSymbolStrings << "\n"
376 << " addressOfLinkEdit=" << _addressOfLinkEdit << "\n");
377 }
378}
379
380uint32_t MachOFileLayout::loadCommandsSize(uint32_t &count) {
381 uint32_t size = 0;
382 count = 0;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000383
384 const size_t segCommandSize =
Nick Kledzike34182f2013-11-06 21:36:55 +0000385 (_is64 ? sizeof(segment_command_64) : sizeof(segment_command));
386 const size_t sectionSize = (_is64 ? sizeof(section_64) : sizeof(section));
387
388 // Add LC_SEGMENT for each segment.
389 size += _file.segments.size() * segCommandSize;
390 count += _file.segments.size();
391 // Add section record for each section.
392 size += _file.sections.size() * sectionSize;
393 // Add one LC_SEGMENT for implicit __LINKEDIT segment
394 size += segCommandSize;
395 ++count;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000396
Tim Northover301c4e62014-07-01 08:15:41 +0000397 // If creating a dylib, add LC_ID_DYLIB.
398 if (_file.fileType == llvm::MachO::MH_DYLIB) {
399 size += sizeof(dylib_command) + pointerAlign(_file.installName.size() + 1);
400 ++count;
401 }
402
Nick Kledzike34182f2013-11-06 21:36:55 +0000403 // Add LC_DYLD_INFO
404 size += sizeof(dyld_info_command);
405 ++count;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000406
Nick Kledzike34182f2013-11-06 21:36:55 +0000407 // Add LC_SYMTAB
408 size += sizeof(symtab_command);
409 ++count;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000410
Nick Kledzike34182f2013-11-06 21:36:55 +0000411 // Add LC_DYSYMTAB
412 if (_file.fileType != llvm::MachO::MH_PRELOAD) {
413 size += sizeof(dysymtab_command);
414 ++count;
415 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000416
Nick Kledzike34182f2013-11-06 21:36:55 +0000417 // If main executable add LC_LOAD_DYLINKER and LC_MAIN
418 if (_file.fileType == llvm::MachO::MH_EXECUTE) {
419 size += pointerAlign(sizeof(dylinker_command) + dyldPath().size()+1);
420 ++count;
421 size += sizeof(entry_point_command);
422 ++count;
423 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000424
Nick Kledzike34182f2013-11-06 21:36:55 +0000425 // Add LC_LOAD_DYLIB for each dependent dylib.
426 for (const DependentDylib &dep : _file.dependentDylibs) {
427 size += sizeof(dylib_command) + pointerAlign(dep.path.size()+1);
428 ++count;
429 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000430
Jean-Daniel Dupas23dd15e2014-12-18 21:33:38 +0000431 // Add LC_RPATH
432 for (const StringRef &path : _file.rpaths) {
433 size += sizeof(rpath_command) + pointerAlign(path.size()+1);
434 ++count;
435 }
436
Nick Kledzik54ce29582014-10-28 22:21:10 +0000437 // Add LC_DATA_IN_CODE if needed
438 if (!_file.dataInCode.empty()) {
439 size += sizeof(linkedit_data_command);
440 ++count;
441 }
442
Nick Kledzike34182f2013-11-06 21:36:55 +0000443 return size;
444}
445
446static bool overlaps(const Segment &s1, const Segment &s2) {
447 if (s2.address >= s1.address+s1.size)
448 return false;
449 if (s1.address >= s2.address+s2.size)
450 return false;
451 return true;
452}
453
454static bool overlaps(const Section &s1, const Section &s2) {
455 if (s2.address >= s1.address+s1.content.size())
456 return false;
457 if (s1.address >= s2.address+s2.content.size())
458 return false;
459 return true;
460}
461
462void MachOFileLayout::buildFileOffsets() {
463 // Verify no segments overlap
464 for (const Segment &sg1 : _file.segments) {
465 for (const Segment &sg2 : _file.segments) {
466 if (&sg1 == &sg2)
467 continue;
468 if (overlaps(sg1,sg2)) {
Rafael Espindola372bc702014-06-13 17:20:48 +0000469 _ec = make_error_code(llvm::errc::executable_format_error);
Nick Kledzike34182f2013-11-06 21:36:55 +0000470 return;
471 }
472 }
473 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000474
475 // Verify no sections overlap
Nick Kledzike34182f2013-11-06 21:36:55 +0000476 for (const Section &s1 : _file.sections) {
477 for (const Section &s2 : _file.sections) {
478 if (&s1 == &s2)
479 continue;
480 if (overlaps(s1,s2)) {
Rafael Espindola372bc702014-06-13 17:20:48 +0000481 _ec = make_error_code(llvm::errc::executable_format_error);
Nick Kledzike34182f2013-11-06 21:36:55 +0000482 return;
483 }
484 }
485 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000486
Nick Kledzike34182f2013-11-06 21:36:55 +0000487 // Build side table of extra info about segments and sections.
488 SegExtraInfo t;
489 t.fileOffset = 0;
490 for (const Segment &sg : _file.segments) {
491 _segInfo[&sg] = t;
492 }
493 SectionExtraInfo t2;
494 t2.fileOffset = 0;
495 // Assign sections to segments.
496 for (const Section &s : _file.sections) {
497 _sectInfo[&s] = t2;
Nick Kledzik1bebb282014-09-09 23:52:59 +0000498 bool foundSegment = false;
Nick Kledzike34182f2013-11-06 21:36:55 +0000499 for (const Segment &sg : _file.segments) {
Nick Kledzik1bebb282014-09-09 23:52:59 +0000500 if (sg.name.equals(s.segmentName)) {
501 if ((s.address >= sg.address)
Nick Kledzike34182f2013-11-06 21:36:55 +0000502 && (s.address+s.content.size() <= sg.address+sg.size)) {
Nick Kledzik1bebb282014-09-09 23:52:59 +0000503 _segInfo[&sg].sections.push_back(&s);
504 foundSegment = true;
505 break;
Nick Kledzike34182f2013-11-06 21:36:55 +0000506 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000507 }
508 }
Nick Kledzik1bebb282014-09-09 23:52:59 +0000509 if (!foundSegment) {
510 _ec = make_error_code(llvm::errc::executable_format_error);
511 return;
512 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000513 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000514
Nick Kledzike34182f2013-11-06 21:36:55 +0000515 // Assign file offsets.
516 uint32_t fileOffset = 0;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000517 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000518 llvm::dbgs() << "buildFileOffsets()\n");
519 for (const Segment &sg : _file.segments) {
Tim Northover08d6a7b2014-06-30 09:49:30 +0000520 _segInfo[&sg].fileOffset = fileOffset;
Nick Kledzike34182f2013-11-06 21:36:55 +0000521 if ((_seg1addr == INT64_MAX) && sg.access)
522 _seg1addr = sg.address;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000523 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000524 llvm::dbgs() << " segment=" << sg.name
525 << ", fileOffset=" << _segInfo[&sg].fileOffset << "\n");
Tim Northover08d6a7b2014-06-30 09:49:30 +0000526
527 uint32_t segFileSize = 0;
Nick Kledzik761d6542014-10-24 22:19:22 +0000528 // A segment that is not zero-fill must use a least one page of disk space.
529 if (sg.access)
530 segFileSize = _file.pageSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000531 for (const Section *s : _segInfo[&sg].sections) {
Tim Northover08d6a7b2014-06-30 09:49:30 +0000532 uint32_t sectOffset = s->address - sg.address;
533 uint32_t sectFileSize =
534 s->type == llvm::MachO::S_ZEROFILL ? 0 : s->content.size();
535 segFileSize = std::max(segFileSize, sectOffset + sectFileSize);
536
537 _sectInfo[s].fileOffset = _segInfo[&sg].fileOffset + sectOffset;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000538 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000539 llvm::dbgs() << " section=" << s->sectionName
540 << ", fileOffset=" << fileOffset << "\n");
541 }
Tim Northover08d6a7b2014-06-30 09:49:30 +0000542
Nick Kledzik1bebb282014-09-09 23:52:59 +0000543 _segInfo[&sg].fileSize = llvm::RoundUpToAlignment(segFileSize,
544 _file.pageSize);
545 fileOffset = llvm::RoundUpToAlignment(fileOffset + segFileSize,
546 _file.pageSize);
Nick Kledzike34182f2013-11-06 21:36:55 +0000547 _addressOfLinkEdit = sg.address + sg.size;
548 }
Tim Northover08d6a7b2014-06-30 09:49:30 +0000549 _startOfLinkEdit = fileOffset;
Nick Kledzike34182f2013-11-06 21:36:55 +0000550}
551
552
553size_t MachOFileLayout::size() const {
554 return _endOfSymbolStrings;
555}
556
557void MachOFileLayout::writeMachHeader() {
558 mach_header *mh = reinterpret_cast<mach_header*>(_buffer);
559 mh->magic = _is64 ? llvm::MachO::MH_MAGIC_64 : llvm::MachO::MH_MAGIC;
560 mh->cputype = MachOLinkingContext::cpuTypeFromArch(_file.arch);
561 mh->cpusubtype = MachOLinkingContext::cpuSubtypeFromArch(_file.arch);
562 mh->filetype = _file.fileType;
563 mh->ncmds = _countOfLoadCommands;
564 mh->sizeofcmds = _endOfLoadCommands - _startOfLoadCommands;
565 mh->flags = _file.flags;
566 if (_swap)
567 swapStruct(*mh);
568}
569
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000570uint32_t MachOFileLayout::indirectSymbolIndex(const Section &sect,
Nick Kledzike34182f2013-11-06 21:36:55 +0000571 uint32_t &index) {
572 if (sect.indirectSymbols.empty())
573 return 0;
574 uint32_t result = index;
575 index += sect.indirectSymbols.size();
576 return result;
577}
578
579uint32_t MachOFileLayout::indirectSymbolElementSize(const Section &sect) {
580 if (sect.indirectSymbols.empty())
581 return 0;
582 if (sect.type != S_SYMBOL_STUBS)
583 return 0;
584 return sect.content.size() / sect.indirectSymbols.size();
585}
586
Nick Kledzik29f749e2013-11-09 00:07:28 +0000587template <typename T>
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000588std::error_code MachOFileLayout::writeSingleSegmentLoadCommand(uint8_t *&lc) {
Nick Kledzik29f749e2013-11-09 00:07:28 +0000589 typename T::command* seg = reinterpret_cast<typename T::command*>(lc);
590 seg->cmd = T::LC;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000591 seg->cmdsize = sizeof(typename T::command)
Nick Kledzik29f749e2013-11-09 00:07:28 +0000592 + _file.sections.size() * sizeof(typename T::section);
Nick Kledzike34182f2013-11-06 21:36:55 +0000593 uint8_t *next = lc + seg->cmdsize;
594 memset(seg->segname, 0, 16);
595 seg->vmaddr = 0;
Nick Kledzikb072c362014-11-18 00:30:29 +0000596 seg->vmsize = _file.sections.back().address
597 + _file.sections.back().content.size();
Nick Kledzike34182f2013-11-06 21:36:55 +0000598 seg->fileoff = _endOfLoadCommands;
599 seg->filesize = seg->vmsize;
600 seg->maxprot = VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE;
601 seg->initprot = VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE;
602 seg->nsects = _file.sections.size();
603 seg->flags = 0;
604 if (_swap)
605 swapStruct(*seg);
Nick Kledzik29f749e2013-11-09 00:07:28 +0000606 typename T::section *sout = reinterpret_cast<typename T::section*>
607 (lc+sizeof(typename T::command));
Nick Kledzike34182f2013-11-06 21:36:55 +0000608 uint32_t relOffset = _startOfRelocations;
Nick Kledzike34182f2013-11-06 21:36:55 +0000609 uint32_t indirectSymRunningIndex = 0;
610 for (const Section &sin : _file.sections) {
611 setString16(sin.sectionName, sout->sectname);
612 setString16(sin.segmentName, sout->segname);
613 sout->addr = sin.address;
614 sout->size = sin.content.size();
Nick Kledzikb072c362014-11-18 00:30:29 +0000615 sout->offset = _sectInfo[&sin].fileOffset;
Nick Kledzike34182f2013-11-06 21:36:55 +0000616 sout->align = sin.alignment;
617 sout->reloff = sin.relocations.empty() ? 0 : relOffset;
618 sout->nreloc = sin.relocations.size();
619 sout->flags = sin.type | sin.attributes;
620 sout->reserved1 = indirectSymbolIndex(sin, indirectSymRunningIndex);
621 sout->reserved2 = indirectSymbolElementSize(sin);
622 relOffset += sin.relocations.size() * sizeof(any_relocation_info);
Nick Kledzike34182f2013-11-06 21:36:55 +0000623 if (_swap)
624 swapStruct(*sout);
625 ++sout;
626 }
627 lc = next;
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000628 return std::error_code();
Nick Kledzike34182f2013-11-06 21:36:55 +0000629}
630
Nick Kledzik29f749e2013-11-09 00:07:28 +0000631template <typename T>
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000632std::error_code MachOFileLayout::writeSegmentLoadCommands(uint8_t *&lc) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000633 uint32_t indirectSymRunningIndex = 0;
634 for (const Segment &seg : _file.segments) {
635 // Write segment command with trailing sections.
636 SegExtraInfo &segInfo = _segInfo[&seg];
Nick Kledzik29f749e2013-11-09 00:07:28 +0000637 typename T::command* cmd = reinterpret_cast<typename T::command*>(lc);
638 cmd->cmd = T::LC;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000639 cmd->cmdsize = sizeof(typename T::command)
Nick Kledzik29f749e2013-11-09 00:07:28 +0000640 + segInfo.sections.size() * sizeof(typename T::section);
Nick Kledzike34182f2013-11-06 21:36:55 +0000641 uint8_t *next = lc + cmd->cmdsize;
642 setString16(seg.name, cmd->segname);
643 cmd->vmaddr = seg.address;
644 cmd->vmsize = seg.size;
645 cmd->fileoff = segInfo.fileOffset;
Tim Northover08d6a7b2014-06-30 09:49:30 +0000646 cmd->filesize = segInfo.fileSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000647 cmd->maxprot = seg.access;
648 cmd->initprot = seg.access;
649 cmd->nsects = segInfo.sections.size();
650 cmd->flags = 0;
651 if (_swap)
652 swapStruct(*cmd);
Nick Kledzik29f749e2013-11-09 00:07:28 +0000653 typename T::section *sect = reinterpret_cast<typename T::section*>
654 (lc+sizeof(typename T::command));
Nick Kledzike34182f2013-11-06 21:36:55 +0000655 for (const Section *section : segInfo.sections) {
656 setString16(section->sectionName, sect->sectname);
657 setString16(section->segmentName, sect->segname);
658 sect->addr = section->address;
659 sect->size = section->content.size();
Nick Kledzikb072c362014-11-18 00:30:29 +0000660 if (section->type == llvm::MachO::S_ZEROFILL)
661 sect->offset = 0;
662 else
663 sect->offset = section->address - seg.address + segInfo.fileOffset;
Nick Kledzike34182f2013-11-06 21:36:55 +0000664 sect->align = section->alignment;
665 sect->reloff = 0;
666 sect->nreloc = 0;
667 sect->flags = section->type | section->attributes;
668 sect->reserved1 = indirectSymbolIndex(*section, indirectSymRunningIndex);
669 sect->reserved2 = indirectSymbolElementSize(*section);
670 if (_swap)
671 swapStruct(*sect);
672 ++sect;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000673 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000674 lc = reinterpret_cast<uint8_t*>(next);
675 }
676 // Add implicit __LINKEDIT segment
Nick Kledzik1bebb282014-09-09 23:52:59 +0000677 size_t linkeditSize = _endOfLinkEdit - _startOfLinkEdit;
Nick Kledzik29f749e2013-11-09 00:07:28 +0000678 typename T::command* cmd = reinterpret_cast<typename T::command*>(lc);
679 cmd->cmd = T::LC;
680 cmd->cmdsize = sizeof(typename T::command);
Nick Kledzike34182f2013-11-06 21:36:55 +0000681 uint8_t *next = lc + cmd->cmdsize;
682 setString16("__LINKEDIT", cmd->segname);
683 cmd->vmaddr = _addressOfLinkEdit;
Nick Kledzik1bebb282014-09-09 23:52:59 +0000684 cmd->vmsize = llvm::RoundUpToAlignment(linkeditSize, _file.pageSize);
Nick Kledzike34182f2013-11-06 21:36:55 +0000685 cmd->fileoff = _startOfLinkEdit;
Nick Kledzik1bebb282014-09-09 23:52:59 +0000686 cmd->filesize = linkeditSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000687 cmd->maxprot = VM_PROT_READ;
688 cmd->initprot = VM_PROT_READ;
689 cmd->nsects = 0;
690 cmd->flags = 0;
691 if (_swap)
692 swapStruct(*cmd);
693 lc = next;
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000694 return std::error_code();
Nick Kledzike34182f2013-11-06 21:36:55 +0000695}
696
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000697std::error_code MachOFileLayout::writeLoadCommands() {
698 std::error_code ec;
Nick Kledzike34182f2013-11-06 21:36:55 +0000699 uint8_t *lc = &_buffer[_startOfLoadCommands];
700 if (_file.fileType == llvm::MachO::MH_OBJECT) {
701 // Object files have one unnamed segment which holds all sections.
702 if (_is64)
Nick Kledzik29f749e2013-11-09 00:07:28 +0000703 ec = writeSingleSegmentLoadCommand<MachO64Trait>(lc);
Nick Kledzike34182f2013-11-06 21:36:55 +0000704 else
Nick Kledzik29f749e2013-11-09 00:07:28 +0000705 ec = writeSingleSegmentLoadCommand<MachO32Trait>(lc);
Nick Kledzike34182f2013-11-06 21:36:55 +0000706 // Add LC_SYMTAB with symbol table info
707 symtab_command* st = reinterpret_cast<symtab_command*>(lc);
708 st->cmd = LC_SYMTAB;
709 st->cmdsize = sizeof(symtab_command);
710 st->symoff = _startOfSymbols;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000711 st->nsyms = _file.localSymbols.size() + _file.globalSymbols.size()
Nick Kledzike34182f2013-11-06 21:36:55 +0000712 + _file.undefinedSymbols.size();
713 st->stroff = _startOfSymbolStrings;
714 st->strsize = _endOfSymbolStrings - _startOfSymbolStrings;
715 if (_swap)
716 swapStruct(*st);
Nick Kledzik21921372014-07-24 23:06:56 +0000717 lc += sizeof(symtab_command);
718 // Add LC_DATA_IN_CODE if needed.
719 if (_dataInCodeSize != 0) {
720 linkedit_data_command* dl = reinterpret_cast<linkedit_data_command*>(lc);
721 dl->cmd = LC_DATA_IN_CODE;
722 dl->cmdsize = sizeof(linkedit_data_command);
723 dl->dataoff = _startOfDataInCode;
724 dl->datasize = _dataInCodeSize;
725 if (_swap)
726 swapStruct(*dl);
727 lc += sizeof(linkedit_data_command);
728 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000729 } else {
730 // Final linked images have sections under segments.
731 if (_is64)
Nick Kledzik29f749e2013-11-09 00:07:28 +0000732 ec = writeSegmentLoadCommands<MachO64Trait>(lc);
Nick Kledzike34182f2013-11-06 21:36:55 +0000733 else
Nick Kledzik29f749e2013-11-09 00:07:28 +0000734 ec = writeSegmentLoadCommands<MachO32Trait>(lc);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000735
Tim Northover301c4e62014-07-01 08:15:41 +0000736 // Add LC_ID_DYLIB command for dynamic libraries.
737 if (_file.fileType == llvm::MachO::MH_DYLIB) {
738 dylib_command *dc = reinterpret_cast<dylib_command*>(lc);
739 StringRef path = _file.installName;
740 uint32_t size = sizeof(dylib_command) + pointerAlign(path.size() + 1);
741 dc->cmd = LC_ID_DYLIB;
742 dc->cmdsize = size;
743 dc->dylib.name = sizeof(dylib_command); // offset
Nick Kledzik5b9e48b2014-11-19 02:21:53 +0000744 dc->dylib.timestamp = 2;
745 dc->dylib.current_version = _file.currentVersion;
746 dc->dylib.compatibility_version = _file.compatVersion;
Tim Northover301c4e62014-07-01 08:15:41 +0000747 if (_swap)
748 swapStruct(*dc);
749 memcpy(lc + sizeof(dylib_command), path.begin(), path.size());
750 lc[sizeof(dylib_command) + path.size()] = '\0';
751 lc += size;
752 }
753
Nick Kledzike34182f2013-11-06 21:36:55 +0000754 // Add LC_DYLD_INFO_ONLY.
755 dyld_info_command* di = reinterpret_cast<dyld_info_command*>(lc);
756 di->cmd = LC_DYLD_INFO_ONLY;
757 di->cmdsize = sizeof(dyld_info_command);
758 di->rebase_off = _rebaseInfo.size() ? _startOfRebaseInfo : 0;
759 di->rebase_size = _rebaseInfo.size();
760 di->bind_off = _bindingInfo.size() ? _startOfBindingInfo : 0;
761 di->bind_size = _bindingInfo.size();
762 di->weak_bind_off = 0;
763 di->weak_bind_size = 0;
764 di->lazy_bind_off = _lazyBindingInfo.size() ? _startOfLazyBindingInfo : 0;
765 di->lazy_bind_size = _lazyBindingInfo.size();
Nick Kledzik141330a2014-09-03 19:52:50 +0000766 di->export_off = _exportTrie.size() ? _startOfExportTrie : 0;
767 di->export_size = _exportTrie.size();
Nick Kledzike34182f2013-11-06 21:36:55 +0000768 if (_swap)
769 swapStruct(*di);
770 lc += sizeof(dyld_info_command);
771
772 // Add LC_SYMTAB with symbol table info.
773 symtab_command* st = reinterpret_cast<symtab_command*>(lc);
774 st->cmd = LC_SYMTAB;
775 st->cmdsize = sizeof(symtab_command);
776 st->symoff = _startOfSymbols;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000777 st->nsyms = _file.localSymbols.size() + _file.globalSymbols.size()
Nick Kledzike34182f2013-11-06 21:36:55 +0000778 + _file.undefinedSymbols.size();
779 st->stroff = _startOfSymbolStrings;
780 st->strsize = _endOfSymbolStrings - _startOfSymbolStrings;
781 if (_swap)
782 swapStruct(*st);
783 lc += sizeof(symtab_command);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000784
Nick Kledzike34182f2013-11-06 21:36:55 +0000785 // Add LC_DYSYMTAB
786 if (_file.fileType != llvm::MachO::MH_PRELOAD) {
787 dysymtab_command* dst = reinterpret_cast<dysymtab_command*>(lc);
788 dst->cmd = LC_DYSYMTAB;
789 dst->cmdsize = sizeof(dysymtab_command);
790 dst->ilocalsym = _symbolTableLocalsStartIndex;
791 dst->nlocalsym = _file.localSymbols.size();
792 dst->iextdefsym = _symbolTableGlobalsStartIndex;
793 dst->nextdefsym = _file.globalSymbols.size();
794 dst->iundefsym = _symbolTableUndefinesStartIndex;
795 dst->nundefsym = _file.undefinedSymbols.size();
796 dst->tocoff = 0;
797 dst->ntoc = 0;
798 dst->modtaboff = 0;
799 dst->nmodtab = 0;
800 dst->extrefsymoff = 0;
801 dst->nextrefsyms = 0;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000802 dst->indirectsymoff = _startOfIndirectSymbols;
Nick Kledzike34182f2013-11-06 21:36:55 +0000803 dst->nindirectsyms = _indirectSymbolTableCount;
804 dst->extreloff = 0;
805 dst->nextrel = 0;
806 dst->locreloff = 0;
807 dst->nlocrel = 0;
808 if (_swap)
809 swapStruct(*dst);
810 lc += sizeof(dysymtab_command);
811 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000812
Nick Kledzike34182f2013-11-06 21:36:55 +0000813 // If main executable, add LC_LOAD_DYLINKER and LC_MAIN.
814 if (_file.fileType == llvm::MachO::MH_EXECUTE) {
815 // Build LC_LOAD_DYLINKER load command.
816 uint32_t size=pointerAlign(sizeof(dylinker_command)+dyldPath().size()+1);
817 dylinker_command* dl = reinterpret_cast<dylinker_command*>(lc);
818 dl->cmd = LC_LOAD_DYLINKER;
819 dl->cmdsize = size;
820 dl->name = sizeof(dylinker_command); // offset
821 if (_swap)
822 swapStruct(*dl);
823 memcpy(lc+sizeof(dylinker_command), dyldPath().data(), dyldPath().size());
824 lc[sizeof(dylinker_command)+dyldPath().size()] = '\0';
825 lc += size;
826 // Build LC_MAIN load command.
827 entry_point_command* ep = reinterpret_cast<entry_point_command*>(lc);
828 ep->cmd = LC_MAIN;
829 ep->cmdsize = sizeof(entry_point_command);
830 ep->entryoff = _file.entryAddress - _seg1addr;
831 ep->stacksize = 0;
832 if (_swap)
833 swapStruct(*ep);
834 lc += sizeof(entry_point_command);
835 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000836
Nick Kledzike34182f2013-11-06 21:36:55 +0000837 // Add LC_LOAD_DYLIB commands
838 for (const DependentDylib &dep : _file.dependentDylibs) {
839 dylib_command* dc = reinterpret_cast<dylib_command*>(lc);
840 uint32_t size = sizeof(dylib_command) + pointerAlign(dep.path.size()+1);
Nick Kledzik51720672014-10-16 19:31:28 +0000841 dc->cmd = dep.kind;
Nick Kledzike34182f2013-11-06 21:36:55 +0000842 dc->cmdsize = size;
843 dc->dylib.name = sizeof(dylib_command); // offset
Nick Kledzik5b9e48b2014-11-19 02:21:53 +0000844 dc->dylib.timestamp = 2;
845 dc->dylib.current_version = dep.currentVersion;
846 dc->dylib.compatibility_version = dep.compatVersion;
Nick Kledzike34182f2013-11-06 21:36:55 +0000847 if (_swap)
848 swapStruct(*dc);
849 memcpy(lc+sizeof(dylib_command), dep.path.begin(), dep.path.size());
850 lc[sizeof(dylib_command)+dep.path.size()] = '\0';
851 lc += size;
852 }
Jean-Daniel Dupas23dd15e2014-12-18 21:33:38 +0000853
854 // Add LC_RPATH
855 for (const StringRef &path : _file.rpaths) {
856 rpath_command *rpc = reinterpret_cast<rpath_command *>(lc);
857 uint32_t size = sizeof(rpath_command) + pointerAlign(path.size()+1);
858 rpc->cmd = LC_RPATH;
859 rpc->cmdsize = size;
860 rpc->path = sizeof(rpath_command); // offset
861 if (_swap)
862 swapStruct(*rpc);
863 memcpy(lc+sizeof(rpath_command), path.begin(), path.size());
864 lc[sizeof(rpath_command)+path.size()] = '\0';
865 lc += size;
866 }
867
Nick Kledzik54ce29582014-10-28 22:21:10 +0000868 // Add LC_DATA_IN_CODE if needed.
869 if (_dataInCodeSize != 0) {
870 linkedit_data_command* dl = reinterpret_cast<linkedit_data_command*>(lc);
871 dl->cmd = LC_DATA_IN_CODE;
872 dl->cmdsize = sizeof(linkedit_data_command);
873 dl->dataoff = _startOfDataInCode;
874 dl->datasize = _dataInCodeSize;
875 if (_swap)
876 swapStruct(*dl);
877 lc += sizeof(linkedit_data_command);
878 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000879 }
880 return ec;
881}
882
883
884void MachOFileLayout::writeSectionContent() {
885 for (const Section &s : _file.sections) {
886 // Copy all section content to output buffer.
Nick Kledzik61fdef62014-05-15 20:59:23 +0000887 if (s.type == llvm::MachO::S_ZEROFILL)
888 continue;
Nick Kledzik1bebb282014-09-09 23:52:59 +0000889 if (s.content.empty())
890 continue;
Nick Kledzike34182f2013-11-06 21:36:55 +0000891 uint32_t offset = _sectInfo[&s].fileOffset;
892 uint8_t *p = &_buffer[offset];
893 memcpy(p, &s.content[0], s.content.size());
894 p += s.content.size();
895 }
896}
897
898void MachOFileLayout::writeRelocations() {
899 uint32_t relOffset = _startOfRelocations;
900 for (Section sect : _file.sections) {
901 for (Relocation r : sect.relocations) {
902 any_relocation_info* rb = reinterpret_cast<any_relocation_info*>(
903 &_buffer[relOffset]);
904 *rb = packRelocation(r, _swap, _bigEndianArch);
905 relOffset += sizeof(any_relocation_info);
906 }
907 }
908}
909
910
911void MachOFileLayout::appendSymbols(const std::vector<Symbol> &symbols,
912 uint32_t &symOffset, uint32_t &strOffset) {
913 for (const Symbol &sym : symbols) {
914 if (_is64) {
915 nlist_64* nb = reinterpret_cast<nlist_64*>(&_buffer[symOffset]);
916 nb->n_strx = strOffset - _startOfSymbolStrings;
917 nb->n_type = sym.type | sym.scope;
918 nb->n_sect = sym.sect;
919 nb->n_desc = sym.desc;
920 nb->n_value = sym.value;
921 if (_swap)
922 swapStruct(*nb);
923 symOffset += sizeof(nlist_64);
924 } else {
925 nlist* nb = reinterpret_cast<nlist*>(&_buffer[symOffset]);
926 nb->n_strx = strOffset - _startOfSymbolStrings;
927 nb->n_type = sym.type | sym.scope;
928 nb->n_sect = sym.sect;
929 nb->n_desc = sym.desc;
930 nb->n_value = sym.value;
931 if (_swap)
932 swapStruct(*nb);
933 symOffset += sizeof(nlist);
934 }
935 memcpy(&_buffer[strOffset], sym.name.begin(), sym.name.size());
936 strOffset += sym.name.size();
937 _buffer[strOffset++] ='\0'; // Strings in table have nul terminator.
938 }
939}
940
Nick Kledzik21921372014-07-24 23:06:56 +0000941void MachOFileLayout::writeDataInCodeInfo() {
942 uint32_t offset = _startOfDataInCode;
943 for (const DataInCode &entry : _file.dataInCode) {
944 data_in_code_entry *dst = reinterpret_cast<data_in_code_entry*>(
945 &_buffer[offset]);
946 dst->offset = entry.offset;
947 dst->length = entry.length;
948 dst->kind = entry.kind;
949 if (_swap)
950 swapStruct(*dst);
951 offset += sizeof(data_in_code_entry);
952 }
953}
954
Nick Kledzike34182f2013-11-06 21:36:55 +0000955void MachOFileLayout::writeSymbolTable() {
956 // Write symbol table and symbol strings in parallel.
957 uint32_t symOffset = _startOfSymbols;
958 uint32_t strOffset = _startOfSymbolStrings;
959 _buffer[strOffset++] = '\0'; // Reserve n_strx offset of zero to mean no name.
960 appendSymbols(_file.localSymbols, symOffset, strOffset);
961 appendSymbols(_file.globalSymbols, symOffset, strOffset);
962 appendSymbols(_file.undefinedSymbols, symOffset, strOffset);
963 // Write indirect symbol table array.
964 uint32_t *indirects = reinterpret_cast<uint32_t*>
965 (&_buffer[_startOfIndirectSymbols]);
966 if (_file.fileType == llvm::MachO::MH_OBJECT) {
967 // Object files have sections in same order as input normalized file.
968 for (const Section &section : _file.sections) {
969 for (uint32_t index : section.indirectSymbols) {
970 if (_swap)
Artyom Skrobov17587fb2014-06-14 12:40:04 +0000971 *indirects++ = llvm::sys::getSwappedBytes(index);
Nick Kledzike34182f2013-11-06 21:36:55 +0000972 else
973 *indirects++ = index;
974 }
975 }
976 } else {
977 // Final linked images must sort sections from normalized file.
978 for (const Segment &seg : _file.segments) {
979 SegExtraInfo &segInfo = _segInfo[&seg];
980 for (const Section *section : segInfo.sections) {
981 for (uint32_t index : section->indirectSymbols) {
982 if (_swap)
Artyom Skrobov17587fb2014-06-14 12:40:04 +0000983 *indirects++ = llvm::sys::getSwappedBytes(index);
Nick Kledzike34182f2013-11-06 21:36:55 +0000984 else
985 *indirects++ = index;
986 }
987 }
988 }
989 }
990}
991
992void MachOFileLayout::writeRebaseInfo() {
993 memcpy(&_buffer[_startOfRebaseInfo], _rebaseInfo.bytes(), _rebaseInfo.size());
994}
995
996void MachOFileLayout::writeBindingInfo() {
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000997 memcpy(&_buffer[_startOfBindingInfo],
Nick Kledzike34182f2013-11-06 21:36:55 +0000998 _bindingInfo.bytes(), _bindingInfo.size());
999}
1000
1001void MachOFileLayout::writeLazyBindingInfo() {
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001002 memcpy(&_buffer[_startOfLazyBindingInfo],
Nick Kledzike34182f2013-11-06 21:36:55 +00001003 _lazyBindingInfo.bytes(), _lazyBindingInfo.size());
1004}
1005
Nick Kledzik141330a2014-09-03 19:52:50 +00001006void MachOFileLayout::writeExportInfo() {
1007 memcpy(&_buffer[_startOfExportTrie], _exportTrie.bytes(), _exportTrie.size());
1008}
1009
Nick Kledzike34182f2013-11-06 21:36:55 +00001010void MachOFileLayout::buildLinkEditInfo() {
1011 buildRebaseInfo();
1012 buildBindInfo();
1013 buildLazyBindInfo();
Nick Kledzik141330a2014-09-03 19:52:50 +00001014 buildExportTrie();
Nick Kledzike34182f2013-11-06 21:36:55 +00001015 computeSymbolTableSizes();
Nick Kledzik21921372014-07-24 23:06:56 +00001016 computeDataInCodeSize();
Nick Kledzike34182f2013-11-06 21:36:55 +00001017}
1018
1019void MachOFileLayout::buildSectionRelocations() {
1020
1021}
1022
1023void MachOFileLayout::buildRebaseInfo() {
1024 // TODO: compress rebasing info.
1025 for (const RebaseLocation& entry : _file.rebasingInfo) {
1026 _rebaseInfo.append_byte(REBASE_OPCODE_SET_TYPE_IMM | entry.kind);
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001027 _rebaseInfo.append_byte(REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
Nick Kledzike34182f2013-11-06 21:36:55 +00001028 | entry.segIndex);
1029 _rebaseInfo.append_uleb128(entry.segOffset);
1030 _rebaseInfo.append_uleb128(REBASE_OPCODE_DO_REBASE_IMM_TIMES | 1);
1031 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001032 _rebaseInfo.append_byte(REBASE_OPCODE_DONE);
Nick Kledzike34182f2013-11-06 21:36:55 +00001033 _rebaseInfo.align(_is64 ? 8 : 4);
1034}
1035
1036void MachOFileLayout::buildBindInfo() {
1037 // TODO: compress bind info.
Nick Kledzikf373c772014-11-11 01:31:18 +00001038 uint64_t lastAddend = 0;
Nick Kledzike34182f2013-11-06 21:36:55 +00001039 for (const BindLocation& entry : _file.bindingInfo) {
1040 _bindingInfo.append_byte(BIND_OPCODE_SET_TYPE_IMM | entry.kind);
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001041 _bindingInfo.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
Nick Kledzike34182f2013-11-06 21:36:55 +00001042 | entry.segIndex);
1043 _bindingInfo.append_uleb128(entry.segOffset);
1044 _bindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM | entry.ordinal);
1045 _bindingInfo.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM);
1046 _bindingInfo.append_string(entry.symbolName);
Nick Kledzikf373c772014-11-11 01:31:18 +00001047 if (entry.addend != lastAddend) {
Nick Kledzike34182f2013-11-06 21:36:55 +00001048 _bindingInfo.append_byte(BIND_OPCODE_SET_ADDEND_SLEB);
1049 _bindingInfo.append_sleb128(entry.addend);
Nick Kledzikf373c772014-11-11 01:31:18 +00001050 lastAddend = entry.addend;
Nick Kledzike34182f2013-11-06 21:36:55 +00001051 }
1052 _bindingInfo.append_byte(BIND_OPCODE_DO_BIND);
1053 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001054 _bindingInfo.append_byte(BIND_OPCODE_DONE);
Nick Kledzike34182f2013-11-06 21:36:55 +00001055 _bindingInfo.align(_is64 ? 8 : 4);
1056}
1057
1058void MachOFileLayout::buildLazyBindInfo() {
1059 for (const BindLocation& entry : _file.lazyBindingInfo) {
1060 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_TYPE_IMM | entry.kind);
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001061 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
Nick Kledzike34182f2013-11-06 21:36:55 +00001062 | entry.segIndex);
Nick Kledzikf373c772014-11-11 01:31:18 +00001063 _lazyBindingInfo.append_uleb128Fixed(entry.segOffset, 5);
Nick Kledzike34182f2013-11-06 21:36:55 +00001064 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM | entry.ordinal);
1065 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM);
1066 _lazyBindingInfo.append_string(entry.symbolName);
1067 _lazyBindingInfo.append_byte(BIND_OPCODE_DO_BIND);
Nick Kledzikf373c772014-11-11 01:31:18 +00001068 _lazyBindingInfo.append_byte(BIND_OPCODE_DONE);
Nick Kledzike34182f2013-11-06 21:36:55 +00001069 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001070 _lazyBindingInfo.append_byte(BIND_OPCODE_DONE);
Nick Kledzike34182f2013-11-06 21:36:55 +00001071 _lazyBindingInfo.align(_is64 ? 8 : 4);
1072}
1073
Nick Kledzik141330a2014-09-03 19:52:50 +00001074void MachOFileLayout::TrieNode::addSymbol(const Export& entry,
1075 BumpPtrAllocator &allocator,
1076 std::vector<TrieNode*> &allNodes) {
1077 StringRef partialStr = entry.name.drop_front(_cummulativeString.size());
1078 for (TrieEdge &edge : _children) {
1079 StringRef edgeStr = edge._subString;
1080 if (partialStr.startswith(edgeStr)) {
1081 // Already have matching edge, go down that path.
1082 edge._child->addSymbol(entry, allocator, allNodes);
1083 return;
1084 }
1085 // See if string has commmon prefix with existing edge.
1086 for (int n=edgeStr.size()-1; n > 0; --n) {
1087 if (partialStr.substr(0, n).equals(edgeStr.substr(0, n))) {
1088 // Splice in new node: was A -> C, now A -> B -> C
1089 StringRef bNodeStr = edge._child->_cummulativeString;
1090 bNodeStr = bNodeStr.drop_back(edgeStr.size()-n).copy(allocator);
1091 TrieNode* bNode = new (allocator) TrieNode(bNodeStr);
1092 allNodes.push_back(bNode);
1093 TrieNode* cNode = edge._child;
1094 StringRef abEdgeStr = edgeStr.substr(0,n).copy(allocator);
1095 StringRef bcEdgeStr = edgeStr.substr(n).copy(allocator);
1096 DEBUG_WITH_TYPE("trie-builder", llvm::dbgs()
1097 << "splice in TrieNode('" << bNodeStr
1098 << "') between edge '"
1099 << abEdgeStr << "' and edge='"
1100 << bcEdgeStr<< "'\n");
1101 TrieEdge& abEdge = edge;
1102 abEdge._subString = abEdgeStr;
1103 abEdge._child = bNode;
Nick Kledzik07ba5122014-12-02 01:50:44 +00001104 TrieEdge *bcEdge = new (allocator) TrieEdge(bcEdgeStr, cNode);
1105 bNode->_children.push_back(std::move(*bcEdge));
Nick Kledzik141330a2014-09-03 19:52:50 +00001106 bNode->addSymbol(entry, allocator, allNodes);
1107 return;
1108 }
1109 }
1110 }
1111 if (entry.flags & EXPORT_SYMBOL_FLAGS_REEXPORT) {
1112 assert(entry.otherOffset != 0);
1113 }
1114 if (entry.flags & EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER) {
1115 assert(entry.otherOffset != 0);
1116 }
1117 // No commonality with any existing child, make a new edge.
1118 TrieNode* newNode = new (allocator) TrieNode(entry.name.copy(allocator));
Nick Kledzik07ba5122014-12-02 01:50:44 +00001119 TrieEdge *newEdge = new (allocator) TrieEdge(partialStr, newNode);
1120 _children.push_back(std::move(*newEdge));
Nick Kledzik141330a2014-09-03 19:52:50 +00001121 DEBUG_WITH_TYPE("trie-builder", llvm::dbgs()
1122 << "new TrieNode('" << entry.name << "') with edge '"
1123 << partialStr << "' from node='"
1124 << _cummulativeString << "'\n");
1125 newNode->_address = entry.offset;
1126 newNode->_flags = entry.flags | entry.kind;
1127 newNode->_other = entry.otherOffset;
1128 if ((entry.flags & EXPORT_SYMBOL_FLAGS_REEXPORT) && !entry.otherName.empty())
1129 newNode->_importedName = entry.otherName.copy(allocator);
1130 newNode->_hasExportInfo = true;
1131 allNodes.push_back(newNode);
1132}
1133
1134bool MachOFileLayout::TrieNode::updateOffset(uint32_t& offset) {
1135 uint32_t nodeSize = 1; // Length when no export info
1136 if (_hasExportInfo) {
1137 if (_flags & EXPORT_SYMBOL_FLAGS_REEXPORT) {
1138 nodeSize = llvm::getULEB128Size(_flags);
1139 nodeSize += llvm::getULEB128Size(_other); // Other contains ordinal.
1140 nodeSize += _importedName.size();
1141 ++nodeSize; // Trailing zero in imported name.
1142 } else {
1143 nodeSize = llvm::getULEB128Size(_flags) + llvm::getULEB128Size(_address);
1144 if (_flags & EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1145 nodeSize += llvm::getULEB128Size(_other);
1146 }
1147 // Overall node size so far is uleb128 of export info + actual export info.
1148 nodeSize += llvm::getULEB128Size(nodeSize);
1149 }
1150 // Compute size of all child edges.
1151 ++nodeSize; // Byte for number of chidren.
1152 for (TrieEdge &edge : _children) {
1153 nodeSize += edge._subString.size() + 1 // String length.
1154 + llvm::getULEB128Size(edge._child->_trieOffset); // Offset len.
1155 }
1156 // On input, 'offset' is new prefered location for this node.
1157 bool result = (_trieOffset != offset);
1158 // Store new location in node object for use by parents.
1159 _trieOffset = offset;
1160 // Update offset for next iteration.
1161 offset += nodeSize;
1162 // Return true if _trieOffset was changed.
1163 return result;
1164}
1165
1166void MachOFileLayout::TrieNode::appendToByteBuffer(ByteBuffer &out) {
1167 if (_hasExportInfo) {
1168 if (_flags & EXPORT_SYMBOL_FLAGS_REEXPORT) {
1169 if (!_importedName.empty()) {
1170 // nodes with re-export info: size, flags, ordinal, import-name
1171 uint32_t nodeSize = llvm::getULEB128Size(_flags)
1172 + llvm::getULEB128Size(_other)
1173 + _importedName.size() + 1;
1174 assert(nodeSize < 256);
1175 out.append_byte(nodeSize);
1176 out.append_uleb128(_flags);
1177 out.append_uleb128(_other);
1178 out.append_string(_importedName);
1179 } else {
1180 // nodes without re-export info: size, flags, ordinal, empty-string
1181 uint32_t nodeSize = llvm::getULEB128Size(_flags)
1182 + llvm::getULEB128Size(_other) + 1;
1183 assert(nodeSize < 256);
1184 out.append_byte(nodeSize);
1185 out.append_uleb128(_flags);
1186 out.append_uleb128(_other);
1187 out.append_byte(0);
1188 }
1189 } else if ( _flags & EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER ) {
1190 // Nodes with export info: size, flags, address, other
1191 uint32_t nodeSize = llvm::getULEB128Size(_flags)
1192 + llvm::getULEB128Size(_address)
1193 + llvm::getULEB128Size(_other);
1194 assert(nodeSize < 256);
1195 out.append_byte(nodeSize);
1196 out.append_uleb128(_flags);
1197 out.append_uleb128(_address);
1198 out.append_uleb128(_other);
1199 } else {
1200 // Nodes with export info: size, flags, address
1201 uint32_t nodeSize = llvm::getULEB128Size(_flags)
1202 + llvm::getULEB128Size(_address);
1203 assert(nodeSize < 256);
1204 out.append_byte(nodeSize);
1205 out.append_uleb128(_flags);
1206 out.append_uleb128(_address);
1207 }
1208 } else {
1209 // Node with no export info.
1210 uint32_t nodeSize = 0;
1211 out.append_byte(nodeSize);
1212 }
1213 // Add number of children.
1214 assert(_children.size() < 256);
1215 out.append_byte(_children.size());
1216 // Append each child edge substring and node offset.
1217 for (TrieEdge &edge : _children) {
1218 out.append_string(edge._subString);
1219 out.append_uleb128(edge._child->_trieOffset);
1220 }
1221}
1222
1223void MachOFileLayout::buildExportTrie() {
1224 if (_file.exportInfo.empty())
1225 return;
1226
1227 // For all temporary strings and objects used building trie.
1228 BumpPtrAllocator allocator;
1229
1230 // Build trie of all exported symbols.
1231 TrieNode* rootNode = new (allocator) TrieNode(StringRef());
1232 std::vector<TrieNode*> allNodes;
1233 allNodes.reserve(_file.exportInfo.size()*2);
1234 allNodes.push_back(rootNode);
1235 for (const Export& entry : _file.exportInfo) {
1236 rootNode->addSymbol(entry, allocator, allNodes);
1237 }
1238
1239 // Assign each node in the vector an offset in the trie stream, iterating
1240 // until all uleb128 sizes have stabilized.
1241 bool more;
1242 do {
1243 uint32_t offset = 0;
1244 more = false;
1245 for (TrieNode* node : allNodes) {
1246 if (node->updateOffset(offset))
1247 more = true;
1248 }
1249 } while (more);
1250
1251 // Serialize trie to ByteBuffer.
1252 for (TrieNode* node : allNodes) {
1253 node->appendToByteBuffer(_exportTrie);
1254 }
1255 _exportTrie.align(_is64 ? 8 : 4);
1256}
1257
1258
Nick Kledzike34182f2013-11-06 21:36:55 +00001259void MachOFileLayout::computeSymbolTableSizes() {
1260 // MachO symbol tables have three ranges: locals, globals, and undefines
1261 const size_t nlistSize = (_is64 ? sizeof(nlist_64) : sizeof(nlist));
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001262 _symbolTableSize = nlistSize * (_file.localSymbols.size()
Nick Kledzike34182f2013-11-06 21:36:55 +00001263 + _file.globalSymbols.size()
1264 + _file.undefinedSymbols.size());
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001265 _symbolStringPoolSize = 0;
Nick Kledzike34182f2013-11-06 21:36:55 +00001266 for (const Symbol &sym : _file.localSymbols) {
1267 _symbolStringPoolSize += (sym.name.size()+1);
1268 }
1269 for (const Symbol &sym : _file.globalSymbols) {
1270 _symbolStringPoolSize += (sym.name.size()+1);
1271 }
1272 for (const Symbol &sym : _file.undefinedSymbols) {
1273 _symbolStringPoolSize += (sym.name.size()+1);
1274 }
1275 _symbolTableLocalsStartIndex = 0;
1276 _symbolTableGlobalsStartIndex = _file.localSymbols.size();
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001277 _symbolTableUndefinesStartIndex = _symbolTableGlobalsStartIndex
Nick Kledzike34182f2013-11-06 21:36:55 +00001278 + _file.globalSymbols.size();
1279
1280 _indirectSymbolTableCount = 0;
1281 for (const Section &sect : _file.sections) {
1282 _indirectSymbolTableCount += sect.indirectSymbols.size();
1283 }
1284}
1285
Nick Kledzik21921372014-07-24 23:06:56 +00001286void MachOFileLayout::computeDataInCodeSize() {
1287 _dataInCodeSize = _file.dataInCode.size() * sizeof(data_in_code_entry);
1288}
Nick Kledzike34182f2013-11-06 21:36:55 +00001289
1290void MachOFileLayout::writeLinkEditContent() {
1291 if (_file.fileType == llvm::MachO::MH_OBJECT) {
1292 writeRelocations();
Nick Kledzik21921372014-07-24 23:06:56 +00001293 writeDataInCodeInfo();
Nick Kledzike34182f2013-11-06 21:36:55 +00001294 writeSymbolTable();
1295 } else {
1296 writeRebaseInfo();
1297 writeBindingInfo();
1298 writeLazyBindingInfo();
1299 // TODO: add weak binding info
Nick Kledzik141330a2014-09-03 19:52:50 +00001300 writeExportInfo();
Nick Kledzik54ce29582014-10-28 22:21:10 +00001301 writeDataInCodeInfo();
Nick Kledzike34182f2013-11-06 21:36:55 +00001302 writeSymbolTable();
1303 }
1304}
1305
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +00001306std::error_code MachOFileLayout::writeBinary(StringRef path) {
Nick Kledzike34182f2013-11-06 21:36:55 +00001307 // Check for pending error from constructor.
1308 if (_ec)
1309 return _ec;
1310 // Create FileOutputBuffer with calculated size.
Ahmed Charles13c70b62014-03-13 16:20:38 +00001311 std::unique_ptr<llvm::FileOutputBuffer> fob;
Nick Kledzike34182f2013-11-06 21:36:55 +00001312 unsigned flags = 0;
1313 if (_file.fileType != llvm::MachO::MH_OBJECT)
1314 flags = llvm::FileOutputBuffer::F_executable;
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +00001315 std::error_code ec;
Nick Kledzike34182f2013-11-06 21:36:55 +00001316 ec = llvm::FileOutputBuffer::create(path, size(), fob, flags);
1317 if (ec)
1318 return ec;
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001319
Nick Kledzike34182f2013-11-06 21:36:55 +00001320 // Write content.
1321 _buffer = fob->getBufferStart();
1322 writeMachHeader();
1323 ec = writeLoadCommands();
1324 if (ec)
1325 return ec;
1326 writeSectionContent();
1327 writeLinkEditContent();
1328 fob->commit();
1329
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +00001330 return std::error_code();
Nick Kledzike34182f2013-11-06 21:36:55 +00001331}
1332
1333
Nick Kledzike34182f2013-11-06 21:36:55 +00001334/// Takes in-memory normalized view and writes a mach-o object file.
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +00001335std::error_code writeBinary(const NormalizedFile &file, StringRef path) {
Nick Kledzike34182f2013-11-06 21:36:55 +00001336 MachOFileLayout layout(file);
1337 return layout.writeBinary(path);
1338}
1339
1340
1341} // namespace normalized
1342} // namespace mach_o
1343} // namespace lld
1344