blob: 5d851898fc529f610c1c696d9290754fde294648 [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) {
Rui Ueyamaf217ef02015-03-26 02:03:44 +0000294 offset = llvm::RoundUpToAlignment(offset, sect.alignment);
Nick Kledzikb072c362014-11-18 00:30:29 +0000295 _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;
Rui Ueyamaf217ef02015-03-26 02:03:44 +0000616 sout->align = llvm::Log2_32(sin.alignment);
Nick Kledzike34182f2013-11-06 21:36:55 +0000617 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;
Rui Ueyamaf217ef02015-03-26 02:03:44 +0000664 sect->align = llvm::Log2_32(section->alignment);
Nick Kledzike34182f2013-11-06 21:36:55 +0000665 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
Jean-Daniel Dupasedefccc2014-12-20 09:22:56 +0000744 // needs to be some constant value different than the one in LC_LOAD_DYLIB
745 dc->dylib.timestamp = 1;
Nick Kledzik5b9e48b2014-11-19 02:21:53 +0000746 dc->dylib.current_version = _file.currentVersion;
747 dc->dylib.compatibility_version = _file.compatVersion;
Tim Northover301c4e62014-07-01 08:15:41 +0000748 if (_swap)
749 swapStruct(*dc);
750 memcpy(lc + sizeof(dylib_command), path.begin(), path.size());
751 lc[sizeof(dylib_command) + path.size()] = '\0';
752 lc += size;
753 }
754
Nick Kledzike34182f2013-11-06 21:36:55 +0000755 // Add LC_DYLD_INFO_ONLY.
756 dyld_info_command* di = reinterpret_cast<dyld_info_command*>(lc);
757 di->cmd = LC_DYLD_INFO_ONLY;
758 di->cmdsize = sizeof(dyld_info_command);
759 di->rebase_off = _rebaseInfo.size() ? _startOfRebaseInfo : 0;
760 di->rebase_size = _rebaseInfo.size();
761 di->bind_off = _bindingInfo.size() ? _startOfBindingInfo : 0;
762 di->bind_size = _bindingInfo.size();
763 di->weak_bind_off = 0;
764 di->weak_bind_size = 0;
765 di->lazy_bind_off = _lazyBindingInfo.size() ? _startOfLazyBindingInfo : 0;
766 di->lazy_bind_size = _lazyBindingInfo.size();
Nick Kledzik141330a2014-09-03 19:52:50 +0000767 di->export_off = _exportTrie.size() ? _startOfExportTrie : 0;
768 di->export_size = _exportTrie.size();
Nick Kledzike34182f2013-11-06 21:36:55 +0000769 if (_swap)
770 swapStruct(*di);
771 lc += sizeof(dyld_info_command);
772
773 // Add LC_SYMTAB with symbol table info.
774 symtab_command* st = reinterpret_cast<symtab_command*>(lc);
775 st->cmd = LC_SYMTAB;
776 st->cmdsize = sizeof(symtab_command);
777 st->symoff = _startOfSymbols;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000778 st->nsyms = _file.localSymbols.size() + _file.globalSymbols.size()
Nick Kledzike34182f2013-11-06 21:36:55 +0000779 + _file.undefinedSymbols.size();
780 st->stroff = _startOfSymbolStrings;
781 st->strsize = _endOfSymbolStrings - _startOfSymbolStrings;
782 if (_swap)
783 swapStruct(*st);
784 lc += sizeof(symtab_command);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000785
Nick Kledzike34182f2013-11-06 21:36:55 +0000786 // Add LC_DYSYMTAB
787 if (_file.fileType != llvm::MachO::MH_PRELOAD) {
788 dysymtab_command* dst = reinterpret_cast<dysymtab_command*>(lc);
789 dst->cmd = LC_DYSYMTAB;
790 dst->cmdsize = sizeof(dysymtab_command);
791 dst->ilocalsym = _symbolTableLocalsStartIndex;
792 dst->nlocalsym = _file.localSymbols.size();
793 dst->iextdefsym = _symbolTableGlobalsStartIndex;
794 dst->nextdefsym = _file.globalSymbols.size();
795 dst->iundefsym = _symbolTableUndefinesStartIndex;
796 dst->nundefsym = _file.undefinedSymbols.size();
797 dst->tocoff = 0;
798 dst->ntoc = 0;
799 dst->modtaboff = 0;
800 dst->nmodtab = 0;
801 dst->extrefsymoff = 0;
802 dst->nextrefsyms = 0;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000803 dst->indirectsymoff = _startOfIndirectSymbols;
Nick Kledzike34182f2013-11-06 21:36:55 +0000804 dst->nindirectsyms = _indirectSymbolTableCount;
805 dst->extreloff = 0;
806 dst->nextrel = 0;
807 dst->locreloff = 0;
808 dst->nlocrel = 0;
809 if (_swap)
810 swapStruct(*dst);
811 lc += sizeof(dysymtab_command);
812 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000813
Nick Kledzike34182f2013-11-06 21:36:55 +0000814 // If main executable, add LC_LOAD_DYLINKER and LC_MAIN.
815 if (_file.fileType == llvm::MachO::MH_EXECUTE) {
816 // Build LC_LOAD_DYLINKER load command.
817 uint32_t size=pointerAlign(sizeof(dylinker_command)+dyldPath().size()+1);
818 dylinker_command* dl = reinterpret_cast<dylinker_command*>(lc);
819 dl->cmd = LC_LOAD_DYLINKER;
820 dl->cmdsize = size;
821 dl->name = sizeof(dylinker_command); // offset
822 if (_swap)
823 swapStruct(*dl);
824 memcpy(lc+sizeof(dylinker_command), dyldPath().data(), dyldPath().size());
825 lc[sizeof(dylinker_command)+dyldPath().size()] = '\0';
826 lc += size;
827 // Build LC_MAIN load command.
828 entry_point_command* ep = reinterpret_cast<entry_point_command*>(lc);
829 ep->cmd = LC_MAIN;
830 ep->cmdsize = sizeof(entry_point_command);
831 ep->entryoff = _file.entryAddress - _seg1addr;
832 ep->stacksize = 0;
833 if (_swap)
834 swapStruct(*ep);
835 lc += sizeof(entry_point_command);
836 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000837
Nick Kledzike34182f2013-11-06 21:36:55 +0000838 // Add LC_LOAD_DYLIB commands
839 for (const DependentDylib &dep : _file.dependentDylibs) {
840 dylib_command* dc = reinterpret_cast<dylib_command*>(lc);
841 uint32_t size = sizeof(dylib_command) + pointerAlign(dep.path.size()+1);
Nick Kledzik51720672014-10-16 19:31:28 +0000842 dc->cmd = dep.kind;
Nick Kledzike34182f2013-11-06 21:36:55 +0000843 dc->cmdsize = size;
844 dc->dylib.name = sizeof(dylib_command); // offset
Jean-Daniel Dupasedefccc2014-12-20 09:22:56 +0000845 // needs to be some constant value different than the one in LC_ID_DYLIB
Nick Kledzik5b9e48b2014-11-19 02:21:53 +0000846 dc->dylib.timestamp = 2;
847 dc->dylib.current_version = dep.currentVersion;
848 dc->dylib.compatibility_version = dep.compatVersion;
Nick Kledzike34182f2013-11-06 21:36:55 +0000849 if (_swap)
850 swapStruct(*dc);
851 memcpy(lc+sizeof(dylib_command), dep.path.begin(), dep.path.size());
852 lc[sizeof(dylib_command)+dep.path.size()] = '\0';
853 lc += size;
854 }
Jean-Daniel Dupas23dd15e2014-12-18 21:33:38 +0000855
856 // Add LC_RPATH
857 for (const StringRef &path : _file.rpaths) {
858 rpath_command *rpc = reinterpret_cast<rpath_command *>(lc);
859 uint32_t size = sizeof(rpath_command) + pointerAlign(path.size()+1);
860 rpc->cmd = LC_RPATH;
861 rpc->cmdsize = size;
862 rpc->path = sizeof(rpath_command); // offset
863 if (_swap)
864 swapStruct(*rpc);
865 memcpy(lc+sizeof(rpath_command), path.begin(), path.size());
866 lc[sizeof(rpath_command)+path.size()] = '\0';
867 lc += size;
868 }
869
Nick Kledzik54ce29582014-10-28 22:21:10 +0000870 // Add LC_DATA_IN_CODE if needed.
871 if (_dataInCodeSize != 0) {
872 linkedit_data_command* dl = reinterpret_cast<linkedit_data_command*>(lc);
873 dl->cmd = LC_DATA_IN_CODE;
874 dl->cmdsize = sizeof(linkedit_data_command);
875 dl->dataoff = _startOfDataInCode;
876 dl->datasize = _dataInCodeSize;
877 if (_swap)
878 swapStruct(*dl);
879 lc += sizeof(linkedit_data_command);
880 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000881 }
882 return ec;
883}
884
885
886void MachOFileLayout::writeSectionContent() {
887 for (const Section &s : _file.sections) {
888 // Copy all section content to output buffer.
Nick Kledzik61fdef62014-05-15 20:59:23 +0000889 if (s.type == llvm::MachO::S_ZEROFILL)
890 continue;
Nick Kledzik1bebb282014-09-09 23:52:59 +0000891 if (s.content.empty())
892 continue;
Nick Kledzike34182f2013-11-06 21:36:55 +0000893 uint32_t offset = _sectInfo[&s].fileOffset;
894 uint8_t *p = &_buffer[offset];
895 memcpy(p, &s.content[0], s.content.size());
896 p += s.content.size();
897 }
898}
899
900void MachOFileLayout::writeRelocations() {
901 uint32_t relOffset = _startOfRelocations;
902 for (Section sect : _file.sections) {
903 for (Relocation r : sect.relocations) {
904 any_relocation_info* rb = reinterpret_cast<any_relocation_info*>(
905 &_buffer[relOffset]);
906 *rb = packRelocation(r, _swap, _bigEndianArch);
907 relOffset += sizeof(any_relocation_info);
908 }
909 }
910}
911
912
913void MachOFileLayout::appendSymbols(const std::vector<Symbol> &symbols,
914 uint32_t &symOffset, uint32_t &strOffset) {
915 for (const Symbol &sym : symbols) {
916 if (_is64) {
917 nlist_64* nb = reinterpret_cast<nlist_64*>(&_buffer[symOffset]);
918 nb->n_strx = strOffset - _startOfSymbolStrings;
919 nb->n_type = sym.type | sym.scope;
920 nb->n_sect = sym.sect;
921 nb->n_desc = sym.desc;
922 nb->n_value = sym.value;
923 if (_swap)
924 swapStruct(*nb);
925 symOffset += sizeof(nlist_64);
926 } else {
927 nlist* nb = reinterpret_cast<nlist*>(&_buffer[symOffset]);
928 nb->n_strx = strOffset - _startOfSymbolStrings;
929 nb->n_type = sym.type | sym.scope;
930 nb->n_sect = sym.sect;
931 nb->n_desc = sym.desc;
932 nb->n_value = sym.value;
933 if (_swap)
934 swapStruct(*nb);
935 symOffset += sizeof(nlist);
936 }
937 memcpy(&_buffer[strOffset], sym.name.begin(), sym.name.size());
938 strOffset += sym.name.size();
939 _buffer[strOffset++] ='\0'; // Strings in table have nul terminator.
940 }
941}
942
Nick Kledzik21921372014-07-24 23:06:56 +0000943void MachOFileLayout::writeDataInCodeInfo() {
944 uint32_t offset = _startOfDataInCode;
945 for (const DataInCode &entry : _file.dataInCode) {
946 data_in_code_entry *dst = reinterpret_cast<data_in_code_entry*>(
947 &_buffer[offset]);
948 dst->offset = entry.offset;
949 dst->length = entry.length;
950 dst->kind = entry.kind;
951 if (_swap)
952 swapStruct(*dst);
953 offset += sizeof(data_in_code_entry);
954 }
955}
956
Nick Kledzike34182f2013-11-06 21:36:55 +0000957void MachOFileLayout::writeSymbolTable() {
958 // Write symbol table and symbol strings in parallel.
959 uint32_t symOffset = _startOfSymbols;
960 uint32_t strOffset = _startOfSymbolStrings;
961 _buffer[strOffset++] = '\0'; // Reserve n_strx offset of zero to mean no name.
962 appendSymbols(_file.localSymbols, symOffset, strOffset);
963 appendSymbols(_file.globalSymbols, symOffset, strOffset);
964 appendSymbols(_file.undefinedSymbols, symOffset, strOffset);
965 // Write indirect symbol table array.
966 uint32_t *indirects = reinterpret_cast<uint32_t*>
967 (&_buffer[_startOfIndirectSymbols]);
968 if (_file.fileType == llvm::MachO::MH_OBJECT) {
969 // Object files have sections in same order as input normalized file.
970 for (const Section &section : _file.sections) {
971 for (uint32_t index : section.indirectSymbols) {
972 if (_swap)
Artyom Skrobov17587fb2014-06-14 12:40:04 +0000973 *indirects++ = llvm::sys::getSwappedBytes(index);
Nick Kledzike34182f2013-11-06 21:36:55 +0000974 else
975 *indirects++ = index;
976 }
977 }
978 } else {
979 // Final linked images must sort sections from normalized file.
980 for (const Segment &seg : _file.segments) {
981 SegExtraInfo &segInfo = _segInfo[&seg];
982 for (const Section *section : segInfo.sections) {
983 for (uint32_t index : section->indirectSymbols) {
984 if (_swap)
Artyom Skrobov17587fb2014-06-14 12:40:04 +0000985 *indirects++ = llvm::sys::getSwappedBytes(index);
Nick Kledzike34182f2013-11-06 21:36:55 +0000986 else
987 *indirects++ = index;
988 }
989 }
990 }
991 }
992}
993
994void MachOFileLayout::writeRebaseInfo() {
995 memcpy(&_buffer[_startOfRebaseInfo], _rebaseInfo.bytes(), _rebaseInfo.size());
996}
997
998void MachOFileLayout::writeBindingInfo() {
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000999 memcpy(&_buffer[_startOfBindingInfo],
Nick Kledzike34182f2013-11-06 21:36:55 +00001000 _bindingInfo.bytes(), _bindingInfo.size());
1001}
1002
1003void MachOFileLayout::writeLazyBindingInfo() {
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001004 memcpy(&_buffer[_startOfLazyBindingInfo],
Nick Kledzike34182f2013-11-06 21:36:55 +00001005 _lazyBindingInfo.bytes(), _lazyBindingInfo.size());
1006}
1007
Nick Kledzik141330a2014-09-03 19:52:50 +00001008void MachOFileLayout::writeExportInfo() {
1009 memcpy(&_buffer[_startOfExportTrie], _exportTrie.bytes(), _exportTrie.size());
1010}
1011
Nick Kledzike34182f2013-11-06 21:36:55 +00001012void MachOFileLayout::buildLinkEditInfo() {
1013 buildRebaseInfo();
1014 buildBindInfo();
1015 buildLazyBindInfo();
Nick Kledzik141330a2014-09-03 19:52:50 +00001016 buildExportTrie();
Nick Kledzike34182f2013-11-06 21:36:55 +00001017 computeSymbolTableSizes();
Nick Kledzik21921372014-07-24 23:06:56 +00001018 computeDataInCodeSize();
Nick Kledzike34182f2013-11-06 21:36:55 +00001019}
1020
1021void MachOFileLayout::buildSectionRelocations() {
1022
1023}
1024
1025void MachOFileLayout::buildRebaseInfo() {
1026 // TODO: compress rebasing info.
1027 for (const RebaseLocation& entry : _file.rebasingInfo) {
1028 _rebaseInfo.append_byte(REBASE_OPCODE_SET_TYPE_IMM | entry.kind);
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001029 _rebaseInfo.append_byte(REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
Nick Kledzike34182f2013-11-06 21:36:55 +00001030 | entry.segIndex);
1031 _rebaseInfo.append_uleb128(entry.segOffset);
1032 _rebaseInfo.append_uleb128(REBASE_OPCODE_DO_REBASE_IMM_TIMES | 1);
1033 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001034 _rebaseInfo.append_byte(REBASE_OPCODE_DONE);
Nick Kledzike34182f2013-11-06 21:36:55 +00001035 _rebaseInfo.align(_is64 ? 8 : 4);
1036}
1037
1038void MachOFileLayout::buildBindInfo() {
1039 // TODO: compress bind info.
Nick Kledzikf373c772014-11-11 01:31:18 +00001040 uint64_t lastAddend = 0;
Nick Kledzike34182f2013-11-06 21:36:55 +00001041 for (const BindLocation& entry : _file.bindingInfo) {
1042 _bindingInfo.append_byte(BIND_OPCODE_SET_TYPE_IMM | entry.kind);
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001043 _bindingInfo.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
Nick Kledzike34182f2013-11-06 21:36:55 +00001044 | entry.segIndex);
1045 _bindingInfo.append_uleb128(entry.segOffset);
1046 _bindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM | entry.ordinal);
1047 _bindingInfo.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM);
1048 _bindingInfo.append_string(entry.symbolName);
Nick Kledzikf373c772014-11-11 01:31:18 +00001049 if (entry.addend != lastAddend) {
Nick Kledzike34182f2013-11-06 21:36:55 +00001050 _bindingInfo.append_byte(BIND_OPCODE_SET_ADDEND_SLEB);
1051 _bindingInfo.append_sleb128(entry.addend);
Nick Kledzikf373c772014-11-11 01:31:18 +00001052 lastAddend = entry.addend;
Nick Kledzike34182f2013-11-06 21:36:55 +00001053 }
1054 _bindingInfo.append_byte(BIND_OPCODE_DO_BIND);
1055 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001056 _bindingInfo.append_byte(BIND_OPCODE_DONE);
Nick Kledzike34182f2013-11-06 21:36:55 +00001057 _bindingInfo.align(_is64 ? 8 : 4);
1058}
1059
1060void MachOFileLayout::buildLazyBindInfo() {
1061 for (const BindLocation& entry : _file.lazyBindingInfo) {
1062 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_TYPE_IMM | entry.kind);
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001063 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
Nick Kledzike34182f2013-11-06 21:36:55 +00001064 | entry.segIndex);
Nick Kledzikf373c772014-11-11 01:31:18 +00001065 _lazyBindingInfo.append_uleb128Fixed(entry.segOffset, 5);
Nick Kledzike34182f2013-11-06 21:36:55 +00001066 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM | entry.ordinal);
1067 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM);
1068 _lazyBindingInfo.append_string(entry.symbolName);
1069 _lazyBindingInfo.append_byte(BIND_OPCODE_DO_BIND);
Nick Kledzikf373c772014-11-11 01:31:18 +00001070 _lazyBindingInfo.append_byte(BIND_OPCODE_DONE);
Nick Kledzike34182f2013-11-06 21:36:55 +00001071 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001072 _lazyBindingInfo.append_byte(BIND_OPCODE_DONE);
Nick Kledzike34182f2013-11-06 21:36:55 +00001073 _lazyBindingInfo.align(_is64 ? 8 : 4);
1074}
1075
Nick Kledzik141330a2014-09-03 19:52:50 +00001076void MachOFileLayout::TrieNode::addSymbol(const Export& entry,
1077 BumpPtrAllocator &allocator,
1078 std::vector<TrieNode*> &allNodes) {
1079 StringRef partialStr = entry.name.drop_front(_cummulativeString.size());
1080 for (TrieEdge &edge : _children) {
1081 StringRef edgeStr = edge._subString;
1082 if (partialStr.startswith(edgeStr)) {
1083 // Already have matching edge, go down that path.
1084 edge._child->addSymbol(entry, allocator, allNodes);
1085 return;
1086 }
1087 // See if string has commmon prefix with existing edge.
1088 for (int n=edgeStr.size()-1; n > 0; --n) {
1089 if (partialStr.substr(0, n).equals(edgeStr.substr(0, n))) {
1090 // Splice in new node: was A -> C, now A -> B -> C
1091 StringRef bNodeStr = edge._child->_cummulativeString;
1092 bNodeStr = bNodeStr.drop_back(edgeStr.size()-n).copy(allocator);
1093 TrieNode* bNode = new (allocator) TrieNode(bNodeStr);
1094 allNodes.push_back(bNode);
1095 TrieNode* cNode = edge._child;
1096 StringRef abEdgeStr = edgeStr.substr(0,n).copy(allocator);
1097 StringRef bcEdgeStr = edgeStr.substr(n).copy(allocator);
1098 DEBUG_WITH_TYPE("trie-builder", llvm::dbgs()
1099 << "splice in TrieNode('" << bNodeStr
1100 << "') between edge '"
1101 << abEdgeStr << "' and edge='"
1102 << bcEdgeStr<< "'\n");
1103 TrieEdge& abEdge = edge;
1104 abEdge._subString = abEdgeStr;
1105 abEdge._child = bNode;
Nick Kledzik07ba5122014-12-02 01:50:44 +00001106 TrieEdge *bcEdge = new (allocator) TrieEdge(bcEdgeStr, cNode);
1107 bNode->_children.push_back(std::move(*bcEdge));
Nick Kledzik141330a2014-09-03 19:52:50 +00001108 bNode->addSymbol(entry, allocator, allNodes);
1109 return;
1110 }
1111 }
1112 }
1113 if (entry.flags & EXPORT_SYMBOL_FLAGS_REEXPORT) {
1114 assert(entry.otherOffset != 0);
1115 }
1116 if (entry.flags & EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER) {
1117 assert(entry.otherOffset != 0);
1118 }
1119 // No commonality with any existing child, make a new edge.
1120 TrieNode* newNode = new (allocator) TrieNode(entry.name.copy(allocator));
Nick Kledzik07ba5122014-12-02 01:50:44 +00001121 TrieEdge *newEdge = new (allocator) TrieEdge(partialStr, newNode);
1122 _children.push_back(std::move(*newEdge));
Nick Kledzik141330a2014-09-03 19:52:50 +00001123 DEBUG_WITH_TYPE("trie-builder", llvm::dbgs()
1124 << "new TrieNode('" << entry.name << "') with edge '"
1125 << partialStr << "' from node='"
1126 << _cummulativeString << "'\n");
1127 newNode->_address = entry.offset;
1128 newNode->_flags = entry.flags | entry.kind;
1129 newNode->_other = entry.otherOffset;
1130 if ((entry.flags & EXPORT_SYMBOL_FLAGS_REEXPORT) && !entry.otherName.empty())
1131 newNode->_importedName = entry.otherName.copy(allocator);
1132 newNode->_hasExportInfo = true;
1133 allNodes.push_back(newNode);
1134}
1135
1136bool MachOFileLayout::TrieNode::updateOffset(uint32_t& offset) {
1137 uint32_t nodeSize = 1; // Length when no export info
1138 if (_hasExportInfo) {
1139 if (_flags & EXPORT_SYMBOL_FLAGS_REEXPORT) {
1140 nodeSize = llvm::getULEB128Size(_flags);
1141 nodeSize += llvm::getULEB128Size(_other); // Other contains ordinal.
1142 nodeSize += _importedName.size();
1143 ++nodeSize; // Trailing zero in imported name.
1144 } else {
1145 nodeSize = llvm::getULEB128Size(_flags) + llvm::getULEB128Size(_address);
1146 if (_flags & EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1147 nodeSize += llvm::getULEB128Size(_other);
1148 }
1149 // Overall node size so far is uleb128 of export info + actual export info.
1150 nodeSize += llvm::getULEB128Size(nodeSize);
1151 }
1152 // Compute size of all child edges.
1153 ++nodeSize; // Byte for number of chidren.
1154 for (TrieEdge &edge : _children) {
1155 nodeSize += edge._subString.size() + 1 // String length.
1156 + llvm::getULEB128Size(edge._child->_trieOffset); // Offset len.
1157 }
1158 // On input, 'offset' is new prefered location for this node.
1159 bool result = (_trieOffset != offset);
1160 // Store new location in node object for use by parents.
1161 _trieOffset = offset;
1162 // Update offset for next iteration.
1163 offset += nodeSize;
1164 // Return true if _trieOffset was changed.
1165 return result;
1166}
1167
1168void MachOFileLayout::TrieNode::appendToByteBuffer(ByteBuffer &out) {
1169 if (_hasExportInfo) {
1170 if (_flags & EXPORT_SYMBOL_FLAGS_REEXPORT) {
1171 if (!_importedName.empty()) {
1172 // nodes with re-export info: size, flags, ordinal, import-name
1173 uint32_t nodeSize = llvm::getULEB128Size(_flags)
1174 + llvm::getULEB128Size(_other)
1175 + _importedName.size() + 1;
1176 assert(nodeSize < 256);
1177 out.append_byte(nodeSize);
1178 out.append_uleb128(_flags);
1179 out.append_uleb128(_other);
1180 out.append_string(_importedName);
1181 } else {
1182 // nodes without re-export info: size, flags, ordinal, empty-string
1183 uint32_t nodeSize = llvm::getULEB128Size(_flags)
1184 + llvm::getULEB128Size(_other) + 1;
1185 assert(nodeSize < 256);
1186 out.append_byte(nodeSize);
1187 out.append_uleb128(_flags);
1188 out.append_uleb128(_other);
1189 out.append_byte(0);
1190 }
1191 } else if ( _flags & EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER ) {
1192 // Nodes with export info: size, flags, address, other
1193 uint32_t nodeSize = llvm::getULEB128Size(_flags)
1194 + llvm::getULEB128Size(_address)
1195 + llvm::getULEB128Size(_other);
1196 assert(nodeSize < 256);
1197 out.append_byte(nodeSize);
1198 out.append_uleb128(_flags);
1199 out.append_uleb128(_address);
1200 out.append_uleb128(_other);
1201 } else {
1202 // Nodes with export info: size, flags, address
1203 uint32_t nodeSize = llvm::getULEB128Size(_flags)
1204 + llvm::getULEB128Size(_address);
1205 assert(nodeSize < 256);
1206 out.append_byte(nodeSize);
1207 out.append_uleb128(_flags);
1208 out.append_uleb128(_address);
1209 }
1210 } else {
1211 // Node with no export info.
1212 uint32_t nodeSize = 0;
1213 out.append_byte(nodeSize);
1214 }
1215 // Add number of children.
1216 assert(_children.size() < 256);
1217 out.append_byte(_children.size());
1218 // Append each child edge substring and node offset.
1219 for (TrieEdge &edge : _children) {
1220 out.append_string(edge._subString);
1221 out.append_uleb128(edge._child->_trieOffset);
1222 }
1223}
1224
1225void MachOFileLayout::buildExportTrie() {
1226 if (_file.exportInfo.empty())
1227 return;
1228
1229 // For all temporary strings and objects used building trie.
1230 BumpPtrAllocator allocator;
1231
1232 // Build trie of all exported symbols.
1233 TrieNode* rootNode = new (allocator) TrieNode(StringRef());
1234 std::vector<TrieNode*> allNodes;
1235 allNodes.reserve(_file.exportInfo.size()*2);
1236 allNodes.push_back(rootNode);
1237 for (const Export& entry : _file.exportInfo) {
1238 rootNode->addSymbol(entry, allocator, allNodes);
1239 }
1240
1241 // Assign each node in the vector an offset in the trie stream, iterating
1242 // until all uleb128 sizes have stabilized.
1243 bool more;
1244 do {
1245 uint32_t offset = 0;
1246 more = false;
1247 for (TrieNode* node : allNodes) {
1248 if (node->updateOffset(offset))
1249 more = true;
1250 }
1251 } while (more);
1252
1253 // Serialize trie to ByteBuffer.
1254 for (TrieNode* node : allNodes) {
1255 node->appendToByteBuffer(_exportTrie);
1256 }
1257 _exportTrie.align(_is64 ? 8 : 4);
1258}
1259
1260
Nick Kledzike34182f2013-11-06 21:36:55 +00001261void MachOFileLayout::computeSymbolTableSizes() {
1262 // MachO symbol tables have three ranges: locals, globals, and undefines
1263 const size_t nlistSize = (_is64 ? sizeof(nlist_64) : sizeof(nlist));
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001264 _symbolTableSize = nlistSize * (_file.localSymbols.size()
Nick Kledzike34182f2013-11-06 21:36:55 +00001265 + _file.globalSymbols.size()
1266 + _file.undefinedSymbols.size());
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001267 _symbolStringPoolSize = 0;
Nick Kledzike34182f2013-11-06 21:36:55 +00001268 for (const Symbol &sym : _file.localSymbols) {
1269 _symbolStringPoolSize += (sym.name.size()+1);
1270 }
1271 for (const Symbol &sym : _file.globalSymbols) {
1272 _symbolStringPoolSize += (sym.name.size()+1);
1273 }
1274 for (const Symbol &sym : _file.undefinedSymbols) {
1275 _symbolStringPoolSize += (sym.name.size()+1);
1276 }
1277 _symbolTableLocalsStartIndex = 0;
1278 _symbolTableGlobalsStartIndex = _file.localSymbols.size();
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001279 _symbolTableUndefinesStartIndex = _symbolTableGlobalsStartIndex
Nick Kledzike34182f2013-11-06 21:36:55 +00001280 + _file.globalSymbols.size();
1281
1282 _indirectSymbolTableCount = 0;
1283 for (const Section &sect : _file.sections) {
1284 _indirectSymbolTableCount += sect.indirectSymbols.size();
1285 }
1286}
1287
Nick Kledzik21921372014-07-24 23:06:56 +00001288void MachOFileLayout::computeDataInCodeSize() {
1289 _dataInCodeSize = _file.dataInCode.size() * sizeof(data_in_code_entry);
1290}
Nick Kledzike34182f2013-11-06 21:36:55 +00001291
1292void MachOFileLayout::writeLinkEditContent() {
1293 if (_file.fileType == llvm::MachO::MH_OBJECT) {
1294 writeRelocations();
Nick Kledzik21921372014-07-24 23:06:56 +00001295 writeDataInCodeInfo();
Nick Kledzike34182f2013-11-06 21:36:55 +00001296 writeSymbolTable();
1297 } else {
1298 writeRebaseInfo();
1299 writeBindingInfo();
1300 writeLazyBindingInfo();
1301 // TODO: add weak binding info
Nick Kledzik141330a2014-09-03 19:52:50 +00001302 writeExportInfo();
Nick Kledzik54ce29582014-10-28 22:21:10 +00001303 writeDataInCodeInfo();
Nick Kledzike34182f2013-11-06 21:36:55 +00001304 writeSymbolTable();
1305 }
1306}
1307
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +00001308std::error_code MachOFileLayout::writeBinary(StringRef path) {
Nick Kledzike34182f2013-11-06 21:36:55 +00001309 // Check for pending error from constructor.
1310 if (_ec)
1311 return _ec;
1312 // Create FileOutputBuffer with calculated size.
Ahmed Charles13c70b62014-03-13 16:20:38 +00001313 std::unique_ptr<llvm::FileOutputBuffer> fob;
Nick Kledzike34182f2013-11-06 21:36:55 +00001314 unsigned flags = 0;
1315 if (_file.fileType != llvm::MachO::MH_OBJECT)
1316 flags = llvm::FileOutputBuffer::F_executable;
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +00001317 std::error_code ec;
Nick Kledzike34182f2013-11-06 21:36:55 +00001318 ec = llvm::FileOutputBuffer::create(path, size(), fob, flags);
1319 if (ec)
1320 return ec;
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001321
Nick Kledzike34182f2013-11-06 21:36:55 +00001322 // Write content.
1323 _buffer = fob->getBufferStart();
1324 writeMachHeader();
1325 ec = writeLoadCommands();
1326 if (ec)
1327 return ec;
1328 writeSectionContent();
1329 writeLinkEditContent();
1330 fob->commit();
1331
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +00001332 return std::error_code();
Nick Kledzike34182f2013-11-06 21:36:55 +00001333}
1334
1335
Nick Kledzike34182f2013-11-06 21:36:55 +00001336/// Takes in-memory normalized view and writes a mach-o object file.
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +00001337std::error_code writeBinary(const NormalizedFile &file, StringRef path) {
Nick Kledzike34182f2013-11-06 21:36:55 +00001338 MachOFileLayout layout(file);
1339 return layout.writeBinary(path);
1340}
1341
1342
1343} // namespace normalized
1344} // namespace mach_o
1345} // namespace lld