blob: 7afb253957933230300e305eabee54f19c4f09dc [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 }
Eugene Zelenko41547942015-11-10 22:37:38 +0000152
Nick Kledzike34182f2013-11-06 21:36:55 +0000153 private:
Nick Kledzik00a15d92013-11-09 01:00:51 +0000154 SmallVector<char, 128> _bytes;
155 // Stream ivar must be after SmallVector ivar to construct properly.
156 llvm::raw_svector_ostream _ostream;
Nick Kledzike34182f2013-11-06 21:36:55 +0000157 };
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000158
Nick Kledzik141330a2014-09-03 19:52:50 +0000159 struct TrieNode; // Forward declaration.
160
161 struct TrieEdge {
162 TrieEdge(StringRef s, TrieNode *node) : _subString(s), _child(node) {}
Nick Kledzik141330a2014-09-03 19:52:50 +0000163
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) {}
Eugene Zelenko41547942015-11-10 22:37:38 +0000172 ~TrieNode() = default;
Nick Kledzik141330a2014-09-03 19:52:50 +0000173
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
Eugene Zelenko41547942015-11-10 22:37:38 +0000179 private:
Nick Kledzik141330a2014-09-03 19:52:50 +0000180 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 +0000266MachOFileLayout::MachOFileLayout(const NormalizedFile &file)
Nick Kledzike34182f2013-11-06 21:36:55 +0000267 : _file(file),
268 _is64(MachOLinkingContext::is64Bit(file.arch)),
269 _swap(!MachOLinkingContext::isHostEndian(file.arch)),
270 _bigEndianArch(MachOLinkingContext::isBigEndian(file.arch)),
271 _seg1addr(INT64_MAX) {
272 _startOfLoadCommands = _is64 ? sizeof(mach_header_64) : sizeof(mach_header);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000273 const size_t segCommandBaseSize =
Nick Kledzike34182f2013-11-06 21:36:55 +0000274 (_is64 ? sizeof(segment_command_64) : sizeof(segment_command));
275 const size_t sectsSize = (_is64 ? sizeof(section_64) : sizeof(section));
276 if (file.fileType == llvm::MachO::MH_OBJECT) {
277 // object files have just one segment load command containing all sections
278 _endOfLoadCommands = _startOfLoadCommands
279 + segCommandBaseSize
280 + file.sections.size() * sectsSize
281 + sizeof(symtab_command);
282 _countOfLoadCommands = 2;
Nick Kledzik21921372014-07-24 23:06:56 +0000283 if (!_file.dataInCode.empty()) {
284 _endOfLoadCommands += sizeof(linkedit_data_command);
285 _countOfLoadCommands++;
286 }
Nick Kledzikb072c362014-11-18 00:30:29 +0000287 // Assign file offsets to each section.
Nick Kledzike34182f2013-11-06 21:36:55 +0000288 _startOfSectionsContent = _endOfLoadCommands;
Nick Kledzike34182f2013-11-06 21:36:55 +0000289 unsigned relocCount = 0;
Nick Kledzikb072c362014-11-18 00:30:29 +0000290 uint64_t offset = _startOfSectionsContent;
Nick Kledzike34182f2013-11-06 21:36:55 +0000291 for (const Section &sect : file.sections) {
Nick Kledzikb072c362014-11-18 00:30:29 +0000292 if (sect.type != llvm::MachO::S_ZEROFILL) {
Rui Ueyamaf217ef02015-03-26 02:03:44 +0000293 offset = llvm::RoundUpToAlignment(offset, sect.alignment);
Nick Kledzikb072c362014-11-18 00:30:29 +0000294 _sectInfo[&sect].fileOffset = offset;
295 offset += sect.content.size();
296 } else {
297 _sectInfo[&sect].fileOffset = 0;
298 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000299 relocCount += sect.relocations.size();
300 }
Nick Kledzikb072c362014-11-18 00:30:29 +0000301 _endOfSectionsContent = offset;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000302
Nick Kledzike34182f2013-11-06 21:36:55 +0000303 computeSymbolTableSizes();
Nick Kledzik21921372014-07-24 23:06:56 +0000304 computeDataInCodeSize();
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000305
Nick Kledzike34182f2013-11-06 21:36:55 +0000306 // Align start of relocations.
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000307 _startOfRelocations = pointerAlign(_endOfSectionsContent);
Nick Kledzik21921372014-07-24 23:06:56 +0000308 _startOfDataInCode = _startOfRelocations + relocCount * 8;
309 _startOfSymbols = _startOfDataInCode + _dataInCodeSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000310 // Add Indirect symbol table.
311 _startOfIndirectSymbols = _startOfSymbols + _symbolTableSize;
312 // Align start of symbol table and symbol strings.
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000313 _startOfSymbolStrings = _startOfIndirectSymbols
Nick Kledzike34182f2013-11-06 21:36:55 +0000314 + pointerAlign(_indirectSymbolTableCount * sizeof(uint32_t));
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000315 _endOfSymbolStrings = _startOfSymbolStrings
Nick Kledzike34182f2013-11-06 21:36:55 +0000316 + pointerAlign(_symbolStringPoolSize);
317 _endOfLinkEdit = _endOfSymbolStrings;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000318 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000319 llvm::dbgs() << "MachOFileLayout()\n"
320 << " startOfLoadCommands=" << _startOfLoadCommands << "\n"
321 << " countOfLoadCommands=" << _countOfLoadCommands << "\n"
322 << " endOfLoadCommands=" << _endOfLoadCommands << "\n"
323 << " startOfRelocations=" << _startOfRelocations << "\n"
324 << " startOfSymbols=" << _startOfSymbols << "\n"
325 << " startOfSymbolStrings=" << _startOfSymbolStrings << "\n"
326 << " endOfSymbolStrings=" << _endOfSymbolStrings << "\n"
327 << " startOfSectionsContent=" << _startOfSectionsContent << "\n"
328 << " endOfSectionsContent=" << _endOfSectionsContent << "\n");
329 } else {
330 // Final linked images have one load command per segment.
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000331 _endOfLoadCommands = _startOfLoadCommands
Nick Kledzike34182f2013-11-06 21:36:55 +0000332 + loadCommandsSize(_countOfLoadCommands);
333
334 // Assign section file offsets.
335 buildFileOffsets();
336 buildLinkEditInfo();
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000337
Nick Kledzike34182f2013-11-06 21:36:55 +0000338 // LINKEDIT of final linked images has in order:
339 // rebase info, binding info, lazy binding info, weak binding info,
Nick Kledzik21921372014-07-24 23:06:56 +0000340 // data-in-code, symbol table, indirect symbol table, symbol table strings.
Nick Kledzike34182f2013-11-06 21:36:55 +0000341 _startOfRebaseInfo = _startOfLinkEdit;
342 _endOfRebaseInfo = _startOfRebaseInfo + _rebaseInfo.size();
343 _startOfBindingInfo = _endOfRebaseInfo;
344 _endOfBindingInfo = _startOfBindingInfo + _bindingInfo.size();
345 _startOfLazyBindingInfo = _endOfBindingInfo;
346 _endOfLazyBindingInfo = _startOfLazyBindingInfo + _lazyBindingInfo.size();
Nick Kledzik141330a2014-09-03 19:52:50 +0000347 _startOfExportTrie = _endOfLazyBindingInfo;
348 _endOfExportTrie = _startOfExportTrie + _exportTrie.size();
349 _startOfDataInCode = _endOfExportTrie;
Nick Kledzik21921372014-07-24 23:06:56 +0000350 _startOfSymbols = _startOfDataInCode + _dataInCodeSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000351 _startOfIndirectSymbols = _startOfSymbols + _symbolTableSize;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000352 _startOfSymbolStrings = _startOfIndirectSymbols
Nick Kledzike34182f2013-11-06 21:36:55 +0000353 + pointerAlign(_indirectSymbolTableCount * sizeof(uint32_t));
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000354 _endOfSymbolStrings = _startOfSymbolStrings
Nick Kledzike34182f2013-11-06 21:36:55 +0000355 + pointerAlign(_symbolStringPoolSize);
356 _endOfLinkEdit = _endOfSymbolStrings;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000357 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000358 llvm::dbgs() << "MachOFileLayout()\n"
359 << " startOfLoadCommands=" << _startOfLoadCommands << "\n"
360 << " countOfLoadCommands=" << _countOfLoadCommands << "\n"
361 << " endOfLoadCommands=" << _endOfLoadCommands << "\n"
362 << " startOfLinkEdit=" << _startOfLinkEdit << "\n"
363 << " startOfRebaseInfo=" << _startOfRebaseInfo << "\n"
364 << " endOfRebaseInfo=" << _endOfRebaseInfo << "\n"
365 << " startOfBindingInfo=" << _startOfBindingInfo << "\n"
366 << " endOfBindingInfo=" << _endOfBindingInfo << "\n"
367 << " startOfLazyBindingInfo=" << _startOfLazyBindingInfo << "\n"
368 << " endOfLazyBindingInfo=" << _endOfLazyBindingInfo << "\n"
Nick Kledzik141330a2014-09-03 19:52:50 +0000369 << " startOfExportTrie=" << _startOfExportTrie << "\n"
370 << " endOfExportTrie=" << _endOfExportTrie << "\n"
Nick Kledzik21921372014-07-24 23:06:56 +0000371 << " startOfDataInCode=" << _startOfDataInCode << "\n"
Nick Kledzike34182f2013-11-06 21:36:55 +0000372 << " startOfSymbols=" << _startOfSymbols << "\n"
373 << " startOfSymbolStrings=" << _startOfSymbolStrings << "\n"
374 << " endOfSymbolStrings=" << _endOfSymbolStrings << "\n"
375 << " addressOfLinkEdit=" << _addressOfLinkEdit << "\n");
376 }
377}
378
379uint32_t MachOFileLayout::loadCommandsSize(uint32_t &count) {
380 uint32_t size = 0;
381 count = 0;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000382
383 const size_t segCommandSize =
Nick Kledzike34182f2013-11-06 21:36:55 +0000384 (_is64 ? sizeof(segment_command_64) : sizeof(segment_command));
385 const size_t sectionSize = (_is64 ? sizeof(section_64) : sizeof(section));
386
387 // Add LC_SEGMENT for each segment.
388 size += _file.segments.size() * segCommandSize;
389 count += _file.segments.size();
390 // Add section record for each section.
391 size += _file.sections.size() * sectionSize;
392 // Add one LC_SEGMENT for implicit __LINKEDIT segment
393 size += segCommandSize;
394 ++count;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000395
Tim Northover301c4e62014-07-01 08:15:41 +0000396 // If creating a dylib, add LC_ID_DYLIB.
397 if (_file.fileType == llvm::MachO::MH_DYLIB) {
398 size += sizeof(dylib_command) + pointerAlign(_file.installName.size() + 1);
399 ++count;
400 }
401
Nick Kledzike34182f2013-11-06 21:36:55 +0000402 // Add LC_DYLD_INFO
403 size += sizeof(dyld_info_command);
404 ++count;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000405
Nick Kledzike34182f2013-11-06 21:36:55 +0000406 // Add LC_SYMTAB
407 size += sizeof(symtab_command);
408 ++count;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000409
Nick Kledzike34182f2013-11-06 21:36:55 +0000410 // Add LC_DYSYMTAB
411 if (_file.fileType != llvm::MachO::MH_PRELOAD) {
412 size += sizeof(dysymtab_command);
413 ++count;
414 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000415
Nick Kledzike34182f2013-11-06 21:36:55 +0000416 // If main executable add LC_LOAD_DYLINKER and LC_MAIN
417 if (_file.fileType == llvm::MachO::MH_EXECUTE) {
418 size += pointerAlign(sizeof(dylinker_command) + dyldPath().size()+1);
419 ++count;
420 size += sizeof(entry_point_command);
421 ++count;
422 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000423
Nick Kledzike34182f2013-11-06 21:36:55 +0000424 // Add LC_LOAD_DYLIB for each dependent dylib.
425 for (const DependentDylib &dep : _file.dependentDylibs) {
426 size += sizeof(dylib_command) + pointerAlign(dep.path.size()+1);
427 ++count;
428 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000429
Jean-Daniel Dupas23dd15e2014-12-18 21:33:38 +0000430 // Add LC_RPATH
431 for (const StringRef &path : _file.rpaths) {
Lang Hames2ed3bf92015-10-29 16:50:26 +0000432 size += pointerAlign(sizeof(rpath_command) + path.size() + 1);
Jean-Daniel Dupas23dd15e2014-12-18 21:33:38 +0000433 ++count;
434 }
435
Nick Kledzik54ce29582014-10-28 22:21:10 +0000436 // Add LC_DATA_IN_CODE if needed
437 if (!_file.dataInCode.empty()) {
438 size += sizeof(linkedit_data_command);
439 ++count;
440 }
441
Nick Kledzike34182f2013-11-06 21:36:55 +0000442 return size;
443}
444
445static bool overlaps(const Segment &s1, const Segment &s2) {
446 if (s2.address >= s1.address+s1.size)
447 return false;
448 if (s1.address >= s2.address+s2.size)
449 return false;
450 return true;
451}
452
453static bool overlaps(const Section &s1, const Section &s2) {
454 if (s2.address >= s1.address+s1.content.size())
455 return false;
456 if (s1.address >= s2.address+s2.content.size())
457 return false;
458 return true;
459}
460
461void MachOFileLayout::buildFileOffsets() {
462 // Verify no segments overlap
463 for (const Segment &sg1 : _file.segments) {
464 for (const Segment &sg2 : _file.segments) {
465 if (&sg1 == &sg2)
466 continue;
467 if (overlaps(sg1,sg2)) {
Rafael Espindola372bc702014-06-13 17:20:48 +0000468 _ec = make_error_code(llvm::errc::executable_format_error);
Nick Kledzike34182f2013-11-06 21:36:55 +0000469 return;
470 }
471 }
472 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000473
474 // Verify no sections overlap
Nick Kledzike34182f2013-11-06 21:36:55 +0000475 for (const Section &s1 : _file.sections) {
476 for (const Section &s2 : _file.sections) {
477 if (&s1 == &s2)
478 continue;
479 if (overlaps(s1,s2)) {
Rafael Espindola372bc702014-06-13 17:20:48 +0000480 _ec = make_error_code(llvm::errc::executable_format_error);
Nick Kledzike34182f2013-11-06 21:36:55 +0000481 return;
482 }
483 }
484 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000485
Nick Kledzike34182f2013-11-06 21:36:55 +0000486 // Build side table of extra info about segments and sections.
487 SegExtraInfo t;
488 t.fileOffset = 0;
489 for (const Segment &sg : _file.segments) {
490 _segInfo[&sg] = t;
491 }
492 SectionExtraInfo t2;
493 t2.fileOffset = 0;
494 // Assign sections to segments.
495 for (const Section &s : _file.sections) {
496 _sectInfo[&s] = t2;
Nick Kledzik1bebb282014-09-09 23:52:59 +0000497 bool foundSegment = false;
Nick Kledzike34182f2013-11-06 21:36:55 +0000498 for (const Segment &sg : _file.segments) {
Nick Kledzik1bebb282014-09-09 23:52:59 +0000499 if (sg.name.equals(s.segmentName)) {
500 if ((s.address >= sg.address)
Nick Kledzike34182f2013-11-06 21:36:55 +0000501 && (s.address+s.content.size() <= sg.address+sg.size)) {
Nick Kledzik1bebb282014-09-09 23:52:59 +0000502 _segInfo[&sg].sections.push_back(&s);
503 foundSegment = true;
504 break;
Nick Kledzike34182f2013-11-06 21:36:55 +0000505 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000506 }
507 }
Nick Kledzik1bebb282014-09-09 23:52:59 +0000508 if (!foundSegment) {
509 _ec = make_error_code(llvm::errc::executable_format_error);
510 return;
511 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000512 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000513
Nick Kledzike34182f2013-11-06 21:36:55 +0000514 // Assign file offsets.
515 uint32_t fileOffset = 0;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000516 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000517 llvm::dbgs() << "buildFileOffsets()\n");
518 for (const Segment &sg : _file.segments) {
Tim Northover08d6a7b2014-06-30 09:49:30 +0000519 _segInfo[&sg].fileOffset = fileOffset;
Nick Kledzike34182f2013-11-06 21:36:55 +0000520 if ((_seg1addr == INT64_MAX) && sg.access)
521 _seg1addr = sg.address;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000522 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000523 llvm::dbgs() << " segment=" << sg.name
524 << ", fileOffset=" << _segInfo[&sg].fileOffset << "\n");
Tim Northover08d6a7b2014-06-30 09:49:30 +0000525
526 uint32_t segFileSize = 0;
Nick Kledzik761d6542014-10-24 22:19:22 +0000527 // A segment that is not zero-fill must use a least one page of disk space.
528 if (sg.access)
529 segFileSize = _file.pageSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000530 for (const Section *s : _segInfo[&sg].sections) {
Tim Northover08d6a7b2014-06-30 09:49:30 +0000531 uint32_t sectOffset = s->address - sg.address;
532 uint32_t sectFileSize =
533 s->type == llvm::MachO::S_ZEROFILL ? 0 : s->content.size();
534 segFileSize = std::max(segFileSize, sectOffset + sectFileSize);
535
536 _sectInfo[s].fileOffset = _segInfo[&sg].fileOffset + sectOffset;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000537 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000538 llvm::dbgs() << " section=" << s->sectionName
539 << ", fileOffset=" << fileOffset << "\n");
540 }
Tim Northover08d6a7b2014-06-30 09:49:30 +0000541
Nick Kledzik1bebb282014-09-09 23:52:59 +0000542 _segInfo[&sg].fileSize = llvm::RoundUpToAlignment(segFileSize,
543 _file.pageSize);
544 fileOffset = llvm::RoundUpToAlignment(fileOffset + segFileSize,
545 _file.pageSize);
Nick Kledzike34182f2013-11-06 21:36:55 +0000546 _addressOfLinkEdit = sg.address + sg.size;
547 }
Tim Northover08d6a7b2014-06-30 09:49:30 +0000548 _startOfLinkEdit = fileOffset;
Nick Kledzike34182f2013-11-06 21:36:55 +0000549}
550
Nick Kledzike34182f2013-11-06 21:36:55 +0000551size_t MachOFileLayout::size() const {
552 return _endOfSymbolStrings;
553}
554
555void MachOFileLayout::writeMachHeader() {
556 mach_header *mh = reinterpret_cast<mach_header*>(_buffer);
557 mh->magic = _is64 ? llvm::MachO::MH_MAGIC_64 : llvm::MachO::MH_MAGIC;
558 mh->cputype = MachOLinkingContext::cpuTypeFromArch(_file.arch);
559 mh->cpusubtype = MachOLinkingContext::cpuSubtypeFromArch(_file.arch);
560 mh->filetype = _file.fileType;
561 mh->ncmds = _countOfLoadCommands;
562 mh->sizeofcmds = _endOfLoadCommands - _startOfLoadCommands;
563 mh->flags = _file.flags;
564 if (_swap)
565 swapStruct(*mh);
566}
567
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000568uint32_t MachOFileLayout::indirectSymbolIndex(const Section &sect,
Nick Kledzike34182f2013-11-06 21:36:55 +0000569 uint32_t &index) {
570 if (sect.indirectSymbols.empty())
571 return 0;
572 uint32_t result = index;
573 index += sect.indirectSymbols.size();
574 return result;
575}
576
577uint32_t MachOFileLayout::indirectSymbolElementSize(const Section &sect) {
578 if (sect.indirectSymbols.empty())
579 return 0;
580 if (sect.type != S_SYMBOL_STUBS)
581 return 0;
582 return sect.content.size() / sect.indirectSymbols.size();
583}
584
Nick Kledzik29f749e2013-11-09 00:07:28 +0000585template <typename T>
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000586std::error_code MachOFileLayout::writeSingleSegmentLoadCommand(uint8_t *&lc) {
Nick Kledzik29f749e2013-11-09 00:07:28 +0000587 typename T::command* seg = reinterpret_cast<typename T::command*>(lc);
588 seg->cmd = T::LC;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000589 seg->cmdsize = sizeof(typename T::command)
Nick Kledzik29f749e2013-11-09 00:07:28 +0000590 + _file.sections.size() * sizeof(typename T::section);
Nick Kledzike34182f2013-11-06 21:36:55 +0000591 uint8_t *next = lc + seg->cmdsize;
592 memset(seg->segname, 0, 16);
593 seg->vmaddr = 0;
Nick Kledzikb072c362014-11-18 00:30:29 +0000594 seg->vmsize = _file.sections.back().address
595 + _file.sections.back().content.size();
Nick Kledzike34182f2013-11-06 21:36:55 +0000596 seg->fileoff = _endOfLoadCommands;
597 seg->filesize = seg->vmsize;
598 seg->maxprot = VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE;
599 seg->initprot = VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE;
600 seg->nsects = _file.sections.size();
601 seg->flags = 0;
602 if (_swap)
603 swapStruct(*seg);
Nick Kledzik29f749e2013-11-09 00:07:28 +0000604 typename T::section *sout = reinterpret_cast<typename T::section*>
605 (lc+sizeof(typename T::command));
Nick Kledzike34182f2013-11-06 21:36:55 +0000606 uint32_t relOffset = _startOfRelocations;
Nick Kledzike34182f2013-11-06 21:36:55 +0000607 uint32_t indirectSymRunningIndex = 0;
608 for (const Section &sin : _file.sections) {
609 setString16(sin.sectionName, sout->sectname);
610 setString16(sin.segmentName, sout->segname);
611 sout->addr = sin.address;
612 sout->size = sin.content.size();
Nick Kledzikb072c362014-11-18 00:30:29 +0000613 sout->offset = _sectInfo[&sin].fileOffset;
Rui Ueyamaf217ef02015-03-26 02:03:44 +0000614 sout->align = llvm::Log2_32(sin.alignment);
Nick Kledzike34182f2013-11-06 21:36:55 +0000615 sout->reloff = sin.relocations.empty() ? 0 : relOffset;
616 sout->nreloc = sin.relocations.size();
617 sout->flags = sin.type | sin.attributes;
618 sout->reserved1 = indirectSymbolIndex(sin, indirectSymRunningIndex);
619 sout->reserved2 = indirectSymbolElementSize(sin);
620 relOffset += sin.relocations.size() * sizeof(any_relocation_info);
Nick Kledzike34182f2013-11-06 21:36:55 +0000621 if (_swap)
622 swapStruct(*sout);
623 ++sout;
624 }
625 lc = next;
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000626 return std::error_code();
Nick Kledzike34182f2013-11-06 21:36:55 +0000627}
628
Nick Kledzik29f749e2013-11-09 00:07:28 +0000629template <typename T>
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000630std::error_code MachOFileLayout::writeSegmentLoadCommands(uint8_t *&lc) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000631 uint32_t indirectSymRunningIndex = 0;
632 for (const Segment &seg : _file.segments) {
633 // Write segment command with trailing sections.
634 SegExtraInfo &segInfo = _segInfo[&seg];
Nick Kledzik29f749e2013-11-09 00:07:28 +0000635 typename T::command* cmd = reinterpret_cast<typename T::command*>(lc);
636 cmd->cmd = T::LC;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000637 cmd->cmdsize = sizeof(typename T::command)
Nick Kledzik29f749e2013-11-09 00:07:28 +0000638 + segInfo.sections.size() * sizeof(typename T::section);
Nick Kledzike34182f2013-11-06 21:36:55 +0000639 uint8_t *next = lc + cmd->cmdsize;
640 setString16(seg.name, cmd->segname);
641 cmd->vmaddr = seg.address;
642 cmd->vmsize = seg.size;
643 cmd->fileoff = segInfo.fileOffset;
Tim Northover08d6a7b2014-06-30 09:49:30 +0000644 cmd->filesize = segInfo.fileSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000645 cmd->maxprot = seg.access;
646 cmd->initprot = seg.access;
647 cmd->nsects = segInfo.sections.size();
648 cmd->flags = 0;
649 if (_swap)
650 swapStruct(*cmd);
Nick Kledzik29f749e2013-11-09 00:07:28 +0000651 typename T::section *sect = reinterpret_cast<typename T::section*>
652 (lc+sizeof(typename T::command));
Nick Kledzike34182f2013-11-06 21:36:55 +0000653 for (const Section *section : segInfo.sections) {
654 setString16(section->sectionName, sect->sectname);
655 setString16(section->segmentName, sect->segname);
656 sect->addr = section->address;
657 sect->size = section->content.size();
Nick Kledzikb072c362014-11-18 00:30:29 +0000658 if (section->type == llvm::MachO::S_ZEROFILL)
659 sect->offset = 0;
660 else
661 sect->offset = section->address - seg.address + segInfo.fileOffset;
Rui Ueyamaf217ef02015-03-26 02:03:44 +0000662 sect->align = llvm::Log2_32(section->alignment);
Nick Kledzike34182f2013-11-06 21:36:55 +0000663 sect->reloff = 0;
664 sect->nreloc = 0;
665 sect->flags = section->type | section->attributes;
666 sect->reserved1 = indirectSymbolIndex(*section, indirectSymRunningIndex);
667 sect->reserved2 = indirectSymbolElementSize(*section);
668 if (_swap)
669 swapStruct(*sect);
670 ++sect;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000671 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000672 lc = reinterpret_cast<uint8_t*>(next);
673 }
674 // Add implicit __LINKEDIT segment
Nick Kledzik1bebb282014-09-09 23:52:59 +0000675 size_t linkeditSize = _endOfLinkEdit - _startOfLinkEdit;
Nick Kledzik29f749e2013-11-09 00:07:28 +0000676 typename T::command* cmd = reinterpret_cast<typename T::command*>(lc);
677 cmd->cmd = T::LC;
678 cmd->cmdsize = sizeof(typename T::command);
Nick Kledzike34182f2013-11-06 21:36:55 +0000679 uint8_t *next = lc + cmd->cmdsize;
680 setString16("__LINKEDIT", cmd->segname);
681 cmd->vmaddr = _addressOfLinkEdit;
Nick Kledzik1bebb282014-09-09 23:52:59 +0000682 cmd->vmsize = llvm::RoundUpToAlignment(linkeditSize, _file.pageSize);
Nick Kledzike34182f2013-11-06 21:36:55 +0000683 cmd->fileoff = _startOfLinkEdit;
Nick Kledzik1bebb282014-09-09 23:52:59 +0000684 cmd->filesize = linkeditSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000685 cmd->maxprot = VM_PROT_READ;
686 cmd->initprot = VM_PROT_READ;
687 cmd->nsects = 0;
688 cmd->flags = 0;
689 if (_swap)
690 swapStruct(*cmd);
691 lc = next;
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000692 return std::error_code();
Nick Kledzike34182f2013-11-06 21:36:55 +0000693}
694
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000695std::error_code MachOFileLayout::writeLoadCommands() {
696 std::error_code ec;
Nick Kledzike34182f2013-11-06 21:36:55 +0000697 uint8_t *lc = &_buffer[_startOfLoadCommands];
698 if (_file.fileType == llvm::MachO::MH_OBJECT) {
699 // Object files have one unnamed segment which holds all sections.
700 if (_is64)
Nick Kledzik29f749e2013-11-09 00:07:28 +0000701 ec = writeSingleSegmentLoadCommand<MachO64Trait>(lc);
Nick Kledzike34182f2013-11-06 21:36:55 +0000702 else
Nick Kledzik29f749e2013-11-09 00:07:28 +0000703 ec = writeSingleSegmentLoadCommand<MachO32Trait>(lc);
Nick Kledzike34182f2013-11-06 21:36:55 +0000704 // Add LC_SYMTAB with symbol table info
705 symtab_command* st = reinterpret_cast<symtab_command*>(lc);
706 st->cmd = LC_SYMTAB;
707 st->cmdsize = sizeof(symtab_command);
708 st->symoff = _startOfSymbols;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000709 st->nsyms = _file.localSymbols.size() + _file.globalSymbols.size()
Nick Kledzike34182f2013-11-06 21:36:55 +0000710 + _file.undefinedSymbols.size();
711 st->stroff = _startOfSymbolStrings;
712 st->strsize = _endOfSymbolStrings - _startOfSymbolStrings;
713 if (_swap)
714 swapStruct(*st);
Nick Kledzik21921372014-07-24 23:06:56 +0000715 lc += sizeof(symtab_command);
716 // Add LC_DATA_IN_CODE if needed.
717 if (_dataInCodeSize != 0) {
718 linkedit_data_command* dl = reinterpret_cast<linkedit_data_command*>(lc);
719 dl->cmd = LC_DATA_IN_CODE;
720 dl->cmdsize = sizeof(linkedit_data_command);
721 dl->dataoff = _startOfDataInCode;
722 dl->datasize = _dataInCodeSize;
723 if (_swap)
724 swapStruct(*dl);
725 lc += sizeof(linkedit_data_command);
726 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000727 } else {
728 // Final linked images have sections under segments.
729 if (_is64)
Nick Kledzik29f749e2013-11-09 00:07:28 +0000730 ec = writeSegmentLoadCommands<MachO64Trait>(lc);
Nick Kledzike34182f2013-11-06 21:36:55 +0000731 else
Nick Kledzik29f749e2013-11-09 00:07:28 +0000732 ec = writeSegmentLoadCommands<MachO32Trait>(lc);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000733
Tim Northover301c4e62014-07-01 08:15:41 +0000734 // Add LC_ID_DYLIB command for dynamic libraries.
735 if (_file.fileType == llvm::MachO::MH_DYLIB) {
736 dylib_command *dc = reinterpret_cast<dylib_command*>(lc);
737 StringRef path = _file.installName;
738 uint32_t size = sizeof(dylib_command) + pointerAlign(path.size() + 1);
739 dc->cmd = LC_ID_DYLIB;
740 dc->cmdsize = size;
741 dc->dylib.name = sizeof(dylib_command); // offset
Jean-Daniel Dupasedefccc2014-12-20 09:22:56 +0000742 // needs to be some constant value different than the one in LC_LOAD_DYLIB
743 dc->dylib.timestamp = 1;
Nick Kledzik5b9e48b2014-11-19 02:21:53 +0000744 dc->dylib.current_version = _file.currentVersion;
745 dc->dylib.compatibility_version = _file.compatVersion;
Tim Northover301c4e62014-07-01 08:15:41 +0000746 if (_swap)
747 swapStruct(*dc);
748 memcpy(lc + sizeof(dylib_command), path.begin(), path.size());
749 lc[sizeof(dylib_command) + path.size()] = '\0';
750 lc += size;
751 }
752
Nick Kledzike34182f2013-11-06 21:36:55 +0000753 // Add LC_DYLD_INFO_ONLY.
754 dyld_info_command* di = reinterpret_cast<dyld_info_command*>(lc);
755 di->cmd = LC_DYLD_INFO_ONLY;
756 di->cmdsize = sizeof(dyld_info_command);
757 di->rebase_off = _rebaseInfo.size() ? _startOfRebaseInfo : 0;
758 di->rebase_size = _rebaseInfo.size();
759 di->bind_off = _bindingInfo.size() ? _startOfBindingInfo : 0;
760 di->bind_size = _bindingInfo.size();
761 di->weak_bind_off = 0;
762 di->weak_bind_size = 0;
763 di->lazy_bind_off = _lazyBindingInfo.size() ? _startOfLazyBindingInfo : 0;
764 di->lazy_bind_size = _lazyBindingInfo.size();
Nick Kledzik141330a2014-09-03 19:52:50 +0000765 di->export_off = _exportTrie.size() ? _startOfExportTrie : 0;
766 di->export_size = _exportTrie.size();
Nick Kledzike34182f2013-11-06 21:36:55 +0000767 if (_swap)
768 swapStruct(*di);
769 lc += sizeof(dyld_info_command);
770
771 // Add LC_SYMTAB with symbol table info.
772 symtab_command* st = reinterpret_cast<symtab_command*>(lc);
773 st->cmd = LC_SYMTAB;
774 st->cmdsize = sizeof(symtab_command);
775 st->symoff = _startOfSymbols;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000776 st->nsyms = _file.localSymbols.size() + _file.globalSymbols.size()
Nick Kledzike34182f2013-11-06 21:36:55 +0000777 + _file.undefinedSymbols.size();
778 st->stroff = _startOfSymbolStrings;
779 st->strsize = _endOfSymbolStrings - _startOfSymbolStrings;
780 if (_swap)
781 swapStruct(*st);
782 lc += sizeof(symtab_command);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000783
Nick Kledzike34182f2013-11-06 21:36:55 +0000784 // Add LC_DYSYMTAB
785 if (_file.fileType != llvm::MachO::MH_PRELOAD) {
786 dysymtab_command* dst = reinterpret_cast<dysymtab_command*>(lc);
787 dst->cmd = LC_DYSYMTAB;
788 dst->cmdsize = sizeof(dysymtab_command);
789 dst->ilocalsym = _symbolTableLocalsStartIndex;
790 dst->nlocalsym = _file.localSymbols.size();
791 dst->iextdefsym = _symbolTableGlobalsStartIndex;
792 dst->nextdefsym = _file.globalSymbols.size();
793 dst->iundefsym = _symbolTableUndefinesStartIndex;
794 dst->nundefsym = _file.undefinedSymbols.size();
795 dst->tocoff = 0;
796 dst->ntoc = 0;
797 dst->modtaboff = 0;
798 dst->nmodtab = 0;
799 dst->extrefsymoff = 0;
800 dst->nextrefsyms = 0;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000801 dst->indirectsymoff = _startOfIndirectSymbols;
Nick Kledzike34182f2013-11-06 21:36:55 +0000802 dst->nindirectsyms = _indirectSymbolTableCount;
803 dst->extreloff = 0;
804 dst->nextrel = 0;
805 dst->locreloff = 0;
806 dst->nlocrel = 0;
807 if (_swap)
808 swapStruct(*dst);
809 lc += sizeof(dysymtab_command);
810 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000811
Nick Kledzike34182f2013-11-06 21:36:55 +0000812 // If main executable, add LC_LOAD_DYLINKER and LC_MAIN.
813 if (_file.fileType == llvm::MachO::MH_EXECUTE) {
814 // Build LC_LOAD_DYLINKER load command.
815 uint32_t size=pointerAlign(sizeof(dylinker_command)+dyldPath().size()+1);
816 dylinker_command* dl = reinterpret_cast<dylinker_command*>(lc);
817 dl->cmd = LC_LOAD_DYLINKER;
818 dl->cmdsize = size;
819 dl->name = sizeof(dylinker_command); // offset
820 if (_swap)
821 swapStruct(*dl);
822 memcpy(lc+sizeof(dylinker_command), dyldPath().data(), dyldPath().size());
823 lc[sizeof(dylinker_command)+dyldPath().size()] = '\0';
824 lc += size;
825 // Build LC_MAIN load command.
826 entry_point_command* ep = reinterpret_cast<entry_point_command*>(lc);
827 ep->cmd = LC_MAIN;
828 ep->cmdsize = sizeof(entry_point_command);
829 ep->entryoff = _file.entryAddress - _seg1addr;
Lang Hames65a64c92015-05-20 22:10:50 +0000830 ep->stacksize = _file.stackSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000831 if (_swap)
832 swapStruct(*ep);
833 lc += sizeof(entry_point_command);
834 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000835
Nick Kledzike34182f2013-11-06 21:36:55 +0000836 // Add LC_LOAD_DYLIB commands
837 for (const DependentDylib &dep : _file.dependentDylibs) {
838 dylib_command* dc = reinterpret_cast<dylib_command*>(lc);
839 uint32_t size = sizeof(dylib_command) + pointerAlign(dep.path.size()+1);
Nick Kledzik51720672014-10-16 19:31:28 +0000840 dc->cmd = dep.kind;
Nick Kledzike34182f2013-11-06 21:36:55 +0000841 dc->cmdsize = size;
842 dc->dylib.name = sizeof(dylib_command); // offset
Jean-Daniel Dupasedefccc2014-12-20 09:22:56 +0000843 // needs to be some constant value different than the one in LC_ID_DYLIB
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);
Lang Hames2ed3bf92015-10-29 16:50:26 +0000857 uint32_t size = pointerAlign(sizeof(rpath_command) + path.size() + 1);
Jean-Daniel Dupas23dd15e2014-12-18 21:33:38 +0000858 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
Nick Kledzike34182f2013-11-06 21:36:55 +0000883void MachOFileLayout::writeSectionContent() {
884 for (const Section &s : _file.sections) {
885 // Copy all section content to output buffer.
Nick Kledzik61fdef62014-05-15 20:59:23 +0000886 if (s.type == llvm::MachO::S_ZEROFILL)
887 continue;
Nick Kledzik1bebb282014-09-09 23:52:59 +0000888 if (s.content.empty())
889 continue;
Nick Kledzike34182f2013-11-06 21:36:55 +0000890 uint32_t offset = _sectInfo[&s].fileOffset;
891 uint8_t *p = &_buffer[offset];
892 memcpy(p, &s.content[0], s.content.size());
893 p += s.content.size();
894 }
895}
896
897void MachOFileLayout::writeRelocations() {
898 uint32_t relOffset = _startOfRelocations;
899 for (Section sect : _file.sections) {
900 for (Relocation r : sect.relocations) {
901 any_relocation_info* rb = reinterpret_cast<any_relocation_info*>(
902 &_buffer[relOffset]);
903 *rb = packRelocation(r, _swap, _bigEndianArch);
904 relOffset += sizeof(any_relocation_info);
905 }
906 }
907}
908
Nick Kledzike34182f2013-11-06 21:36:55 +0000909void MachOFileLayout::appendSymbols(const std::vector<Symbol> &symbols,
910 uint32_t &symOffset, uint32_t &strOffset) {
911 for (const Symbol &sym : symbols) {
912 if (_is64) {
913 nlist_64* nb = reinterpret_cast<nlist_64*>(&_buffer[symOffset]);
914 nb->n_strx = strOffset - _startOfSymbolStrings;
915 nb->n_type = sym.type | sym.scope;
916 nb->n_sect = sym.sect;
917 nb->n_desc = sym.desc;
918 nb->n_value = sym.value;
919 if (_swap)
920 swapStruct(*nb);
921 symOffset += sizeof(nlist_64);
922 } else {
923 nlist* nb = reinterpret_cast<nlist*>(&_buffer[symOffset]);
924 nb->n_strx = strOffset - _startOfSymbolStrings;
925 nb->n_type = sym.type | sym.scope;
926 nb->n_sect = sym.sect;
927 nb->n_desc = sym.desc;
928 nb->n_value = sym.value;
929 if (_swap)
930 swapStruct(*nb);
931 symOffset += sizeof(nlist);
932 }
933 memcpy(&_buffer[strOffset], sym.name.begin(), sym.name.size());
934 strOffset += sym.name.size();
935 _buffer[strOffset++] ='\0'; // Strings in table have nul terminator.
936 }
937}
938
Nick Kledzik21921372014-07-24 23:06:56 +0000939void MachOFileLayout::writeDataInCodeInfo() {
940 uint32_t offset = _startOfDataInCode;
941 for (const DataInCode &entry : _file.dataInCode) {
942 data_in_code_entry *dst = reinterpret_cast<data_in_code_entry*>(
943 &_buffer[offset]);
944 dst->offset = entry.offset;
945 dst->length = entry.length;
946 dst->kind = entry.kind;
947 if (_swap)
948 swapStruct(*dst);
949 offset += sizeof(data_in_code_entry);
950 }
951}
952
Nick Kledzike34182f2013-11-06 21:36:55 +0000953void MachOFileLayout::writeSymbolTable() {
954 // Write symbol table and symbol strings in parallel.
955 uint32_t symOffset = _startOfSymbols;
956 uint32_t strOffset = _startOfSymbolStrings;
957 _buffer[strOffset++] = '\0'; // Reserve n_strx offset of zero to mean no name.
958 appendSymbols(_file.localSymbols, symOffset, strOffset);
959 appendSymbols(_file.globalSymbols, symOffset, strOffset);
960 appendSymbols(_file.undefinedSymbols, symOffset, strOffset);
961 // Write indirect symbol table array.
962 uint32_t *indirects = reinterpret_cast<uint32_t*>
963 (&_buffer[_startOfIndirectSymbols]);
964 if (_file.fileType == llvm::MachO::MH_OBJECT) {
965 // Object files have sections in same order as input normalized file.
966 for (const Section &section : _file.sections) {
967 for (uint32_t index : section.indirectSymbols) {
968 if (_swap)
Artyom Skrobov17587fb2014-06-14 12:40:04 +0000969 *indirects++ = llvm::sys::getSwappedBytes(index);
Nick Kledzike34182f2013-11-06 21:36:55 +0000970 else
971 *indirects++ = index;
972 }
973 }
974 } else {
975 // Final linked images must sort sections from normalized file.
976 for (const Segment &seg : _file.segments) {
977 SegExtraInfo &segInfo = _segInfo[&seg];
978 for (const Section *section : segInfo.sections) {
979 for (uint32_t index : section->indirectSymbols) {
980 if (_swap)
Artyom Skrobov17587fb2014-06-14 12:40:04 +0000981 *indirects++ = llvm::sys::getSwappedBytes(index);
Nick Kledzike34182f2013-11-06 21:36:55 +0000982 else
983 *indirects++ = index;
984 }
985 }
986 }
987 }
988}
989
990void MachOFileLayout::writeRebaseInfo() {
991 memcpy(&_buffer[_startOfRebaseInfo], _rebaseInfo.bytes(), _rebaseInfo.size());
992}
993
994void MachOFileLayout::writeBindingInfo() {
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000995 memcpy(&_buffer[_startOfBindingInfo],
Nick Kledzike34182f2013-11-06 21:36:55 +0000996 _bindingInfo.bytes(), _bindingInfo.size());
997}
998
999void MachOFileLayout::writeLazyBindingInfo() {
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001000 memcpy(&_buffer[_startOfLazyBindingInfo],
Nick Kledzike34182f2013-11-06 21:36:55 +00001001 _lazyBindingInfo.bytes(), _lazyBindingInfo.size());
1002}
1003
Nick Kledzik141330a2014-09-03 19:52:50 +00001004void MachOFileLayout::writeExportInfo() {
1005 memcpy(&_buffer[_startOfExportTrie], _exportTrie.bytes(), _exportTrie.size());
1006}
1007
Nick Kledzike34182f2013-11-06 21:36:55 +00001008void MachOFileLayout::buildLinkEditInfo() {
1009 buildRebaseInfo();
1010 buildBindInfo();
1011 buildLazyBindInfo();
Nick Kledzik141330a2014-09-03 19:52:50 +00001012 buildExportTrie();
Nick Kledzike34182f2013-11-06 21:36:55 +00001013 computeSymbolTableSizes();
Nick Kledzik21921372014-07-24 23:06:56 +00001014 computeDataInCodeSize();
Nick Kledzike34182f2013-11-06 21:36:55 +00001015}
1016
1017void MachOFileLayout::buildSectionRelocations() {
1018
1019}
1020
1021void MachOFileLayout::buildRebaseInfo() {
1022 // TODO: compress rebasing info.
1023 for (const RebaseLocation& entry : _file.rebasingInfo) {
1024 _rebaseInfo.append_byte(REBASE_OPCODE_SET_TYPE_IMM | entry.kind);
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001025 _rebaseInfo.append_byte(REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
Nick Kledzike34182f2013-11-06 21:36:55 +00001026 | entry.segIndex);
1027 _rebaseInfo.append_uleb128(entry.segOffset);
1028 _rebaseInfo.append_uleb128(REBASE_OPCODE_DO_REBASE_IMM_TIMES | 1);
1029 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001030 _rebaseInfo.append_byte(REBASE_OPCODE_DONE);
Nick Kledzike34182f2013-11-06 21:36:55 +00001031 _rebaseInfo.align(_is64 ? 8 : 4);
1032}
1033
1034void MachOFileLayout::buildBindInfo() {
1035 // TODO: compress bind info.
Nick Kledzikf373c772014-11-11 01:31:18 +00001036 uint64_t lastAddend = 0;
Nick Kledzike34182f2013-11-06 21:36:55 +00001037 for (const BindLocation& entry : _file.bindingInfo) {
1038 _bindingInfo.append_byte(BIND_OPCODE_SET_TYPE_IMM | entry.kind);
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001039 _bindingInfo.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
Nick Kledzike34182f2013-11-06 21:36:55 +00001040 | entry.segIndex);
1041 _bindingInfo.append_uleb128(entry.segOffset);
Lang Hames5c692002015-09-28 20:25:14 +00001042 if (entry.ordinal > 0)
1043 _bindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM |
1044 (entry.ordinal & 0xF));
1045 else
1046 _bindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_SPECIAL_IMM |
1047 (entry.ordinal & 0xF));
Nick Kledzike34182f2013-11-06 21:36:55 +00001048 _bindingInfo.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM);
1049 _bindingInfo.append_string(entry.symbolName);
Nick Kledzikf373c772014-11-11 01:31:18 +00001050 if (entry.addend != lastAddend) {
Nick Kledzike34182f2013-11-06 21:36:55 +00001051 _bindingInfo.append_byte(BIND_OPCODE_SET_ADDEND_SLEB);
1052 _bindingInfo.append_sleb128(entry.addend);
Nick Kledzikf373c772014-11-11 01:31:18 +00001053 lastAddend = entry.addend;
Nick Kledzike34182f2013-11-06 21:36:55 +00001054 }
1055 _bindingInfo.append_byte(BIND_OPCODE_DO_BIND);
1056 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001057 _bindingInfo.append_byte(BIND_OPCODE_DONE);
Nick Kledzike34182f2013-11-06 21:36:55 +00001058 _bindingInfo.align(_is64 ? 8 : 4);
1059}
1060
1061void MachOFileLayout::buildLazyBindInfo() {
1062 for (const BindLocation& entry : _file.lazyBindingInfo) {
1063 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_TYPE_IMM | entry.kind);
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001064 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
Nick Kledzike34182f2013-11-06 21:36:55 +00001065 | entry.segIndex);
Nick Kledzikf373c772014-11-11 01:31:18 +00001066 _lazyBindingInfo.append_uleb128Fixed(entry.segOffset, 5);
Lang Hames5c692002015-09-28 20:25:14 +00001067 if (entry.ordinal > 0)
1068 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM |
1069 (entry.ordinal & 0xF));
1070 else
1071 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_SPECIAL_IMM |
1072 (entry.ordinal & 0xF));
Nick Kledzike34182f2013-11-06 21:36:55 +00001073 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM);
1074 _lazyBindingInfo.append_string(entry.symbolName);
1075 _lazyBindingInfo.append_byte(BIND_OPCODE_DO_BIND);
Nick Kledzikf373c772014-11-11 01:31:18 +00001076 _lazyBindingInfo.append_byte(BIND_OPCODE_DONE);
Nick Kledzike34182f2013-11-06 21:36:55 +00001077 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001078 _lazyBindingInfo.append_byte(BIND_OPCODE_DONE);
Nick Kledzike34182f2013-11-06 21:36:55 +00001079 _lazyBindingInfo.align(_is64 ? 8 : 4);
1080}
1081
Nick Kledzik141330a2014-09-03 19:52:50 +00001082void MachOFileLayout::TrieNode::addSymbol(const Export& entry,
1083 BumpPtrAllocator &allocator,
1084 std::vector<TrieNode*> &allNodes) {
1085 StringRef partialStr = entry.name.drop_front(_cummulativeString.size());
1086 for (TrieEdge &edge : _children) {
1087 StringRef edgeStr = edge._subString;
1088 if (partialStr.startswith(edgeStr)) {
1089 // Already have matching edge, go down that path.
1090 edge._child->addSymbol(entry, allocator, allNodes);
1091 return;
1092 }
1093 // See if string has commmon prefix with existing edge.
1094 for (int n=edgeStr.size()-1; n > 0; --n) {
1095 if (partialStr.substr(0, n).equals(edgeStr.substr(0, n))) {
1096 // Splice in new node: was A -> C, now A -> B -> C
1097 StringRef bNodeStr = edge._child->_cummulativeString;
1098 bNodeStr = bNodeStr.drop_back(edgeStr.size()-n).copy(allocator);
Eugene Zelenko41547942015-11-10 22:37:38 +00001099 auto *bNode = new (allocator) TrieNode(bNodeStr);
Nick Kledzik141330a2014-09-03 19:52:50 +00001100 allNodes.push_back(bNode);
1101 TrieNode* cNode = edge._child;
1102 StringRef abEdgeStr = edgeStr.substr(0,n).copy(allocator);
1103 StringRef bcEdgeStr = edgeStr.substr(n).copy(allocator);
1104 DEBUG_WITH_TYPE("trie-builder", llvm::dbgs()
1105 << "splice in TrieNode('" << bNodeStr
1106 << "') between edge '"
1107 << abEdgeStr << "' and edge='"
1108 << bcEdgeStr<< "'\n");
1109 TrieEdge& abEdge = edge;
1110 abEdge._subString = abEdgeStr;
1111 abEdge._child = bNode;
Eugene Zelenko41547942015-11-10 22:37:38 +00001112 auto *bcEdge = new (allocator) TrieEdge(bcEdgeStr, cNode);
Nick Kledzik07ba5122014-12-02 01:50:44 +00001113 bNode->_children.push_back(std::move(*bcEdge));
Nick Kledzik141330a2014-09-03 19:52:50 +00001114 bNode->addSymbol(entry, allocator, allNodes);
1115 return;
1116 }
1117 }
1118 }
1119 if (entry.flags & EXPORT_SYMBOL_FLAGS_REEXPORT) {
1120 assert(entry.otherOffset != 0);
1121 }
1122 if (entry.flags & EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER) {
1123 assert(entry.otherOffset != 0);
1124 }
1125 // No commonality with any existing child, make a new edge.
Eugene Zelenko41547942015-11-10 22:37:38 +00001126 auto *newNode = new (allocator) TrieNode(entry.name.copy(allocator));
1127 auto *newEdge = new (allocator) TrieEdge(partialStr, newNode);
Nick Kledzik07ba5122014-12-02 01:50:44 +00001128 _children.push_back(std::move(*newEdge));
Nick Kledzik141330a2014-09-03 19:52:50 +00001129 DEBUG_WITH_TYPE("trie-builder", llvm::dbgs()
1130 << "new TrieNode('" << entry.name << "') with edge '"
1131 << partialStr << "' from node='"
1132 << _cummulativeString << "'\n");
1133 newNode->_address = entry.offset;
1134 newNode->_flags = entry.flags | entry.kind;
1135 newNode->_other = entry.otherOffset;
1136 if ((entry.flags & EXPORT_SYMBOL_FLAGS_REEXPORT) && !entry.otherName.empty())
1137 newNode->_importedName = entry.otherName.copy(allocator);
1138 newNode->_hasExportInfo = true;
1139 allNodes.push_back(newNode);
1140}
1141
1142bool MachOFileLayout::TrieNode::updateOffset(uint32_t& offset) {
1143 uint32_t nodeSize = 1; // Length when no export info
1144 if (_hasExportInfo) {
1145 if (_flags & EXPORT_SYMBOL_FLAGS_REEXPORT) {
1146 nodeSize = llvm::getULEB128Size(_flags);
1147 nodeSize += llvm::getULEB128Size(_other); // Other contains ordinal.
1148 nodeSize += _importedName.size();
1149 ++nodeSize; // Trailing zero in imported name.
1150 } else {
1151 nodeSize = llvm::getULEB128Size(_flags) + llvm::getULEB128Size(_address);
1152 if (_flags & EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1153 nodeSize += llvm::getULEB128Size(_other);
1154 }
1155 // Overall node size so far is uleb128 of export info + actual export info.
1156 nodeSize += llvm::getULEB128Size(nodeSize);
1157 }
1158 // Compute size of all child edges.
1159 ++nodeSize; // Byte for number of chidren.
1160 for (TrieEdge &edge : _children) {
1161 nodeSize += edge._subString.size() + 1 // String length.
1162 + llvm::getULEB128Size(edge._child->_trieOffset); // Offset len.
1163 }
1164 // On input, 'offset' is new prefered location for this node.
1165 bool result = (_trieOffset != offset);
1166 // Store new location in node object for use by parents.
1167 _trieOffset = offset;
1168 // Update offset for next iteration.
1169 offset += nodeSize;
1170 // Return true if _trieOffset was changed.
1171 return result;
1172}
1173
1174void MachOFileLayout::TrieNode::appendToByteBuffer(ByteBuffer &out) {
1175 if (_hasExportInfo) {
1176 if (_flags & EXPORT_SYMBOL_FLAGS_REEXPORT) {
1177 if (!_importedName.empty()) {
1178 // nodes with re-export info: size, flags, ordinal, import-name
1179 uint32_t nodeSize = llvm::getULEB128Size(_flags)
1180 + llvm::getULEB128Size(_other)
1181 + _importedName.size() + 1;
1182 assert(nodeSize < 256);
1183 out.append_byte(nodeSize);
1184 out.append_uleb128(_flags);
1185 out.append_uleb128(_other);
1186 out.append_string(_importedName);
1187 } else {
1188 // nodes without re-export info: size, flags, ordinal, empty-string
1189 uint32_t nodeSize = llvm::getULEB128Size(_flags)
1190 + llvm::getULEB128Size(_other) + 1;
1191 assert(nodeSize < 256);
1192 out.append_byte(nodeSize);
1193 out.append_uleb128(_flags);
1194 out.append_uleb128(_other);
1195 out.append_byte(0);
1196 }
1197 } else if ( _flags & EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER ) {
1198 // Nodes with export info: size, flags, address, other
1199 uint32_t nodeSize = llvm::getULEB128Size(_flags)
1200 + llvm::getULEB128Size(_address)
1201 + llvm::getULEB128Size(_other);
1202 assert(nodeSize < 256);
1203 out.append_byte(nodeSize);
1204 out.append_uleb128(_flags);
1205 out.append_uleb128(_address);
1206 out.append_uleb128(_other);
1207 } else {
1208 // Nodes with export info: size, flags, address
1209 uint32_t nodeSize = llvm::getULEB128Size(_flags)
1210 + llvm::getULEB128Size(_address);
1211 assert(nodeSize < 256);
1212 out.append_byte(nodeSize);
1213 out.append_uleb128(_flags);
1214 out.append_uleb128(_address);
1215 }
1216 } else {
1217 // Node with no export info.
1218 uint32_t nodeSize = 0;
1219 out.append_byte(nodeSize);
1220 }
1221 // Add number of children.
1222 assert(_children.size() < 256);
1223 out.append_byte(_children.size());
1224 // Append each child edge substring and node offset.
1225 for (TrieEdge &edge : _children) {
1226 out.append_string(edge._subString);
1227 out.append_uleb128(edge._child->_trieOffset);
1228 }
1229}
1230
1231void MachOFileLayout::buildExportTrie() {
1232 if (_file.exportInfo.empty())
1233 return;
1234
1235 // For all temporary strings and objects used building trie.
1236 BumpPtrAllocator allocator;
1237
1238 // Build trie of all exported symbols.
Eugene Zelenko41547942015-11-10 22:37:38 +00001239 auto *rootNode = new (allocator) TrieNode(StringRef());
Nick Kledzik141330a2014-09-03 19:52:50 +00001240 std::vector<TrieNode*> allNodes;
1241 allNodes.reserve(_file.exportInfo.size()*2);
1242 allNodes.push_back(rootNode);
1243 for (const Export& entry : _file.exportInfo) {
1244 rootNode->addSymbol(entry, allocator, allNodes);
1245 }
1246
1247 // Assign each node in the vector an offset in the trie stream, iterating
1248 // until all uleb128 sizes have stabilized.
1249 bool more;
1250 do {
1251 uint32_t offset = 0;
1252 more = false;
1253 for (TrieNode* node : allNodes) {
1254 if (node->updateOffset(offset))
1255 more = true;
1256 }
1257 } while (more);
1258
1259 // Serialize trie to ByteBuffer.
1260 for (TrieNode* node : allNodes) {
1261 node->appendToByteBuffer(_exportTrie);
1262 }
1263 _exportTrie.align(_is64 ? 8 : 4);
1264}
1265
Nick Kledzike34182f2013-11-06 21:36:55 +00001266void MachOFileLayout::computeSymbolTableSizes() {
1267 // MachO symbol tables have three ranges: locals, globals, and undefines
1268 const size_t nlistSize = (_is64 ? sizeof(nlist_64) : sizeof(nlist));
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001269 _symbolTableSize = nlistSize * (_file.localSymbols.size()
Nick Kledzike34182f2013-11-06 21:36:55 +00001270 + _file.globalSymbols.size()
1271 + _file.undefinedSymbols.size());
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001272 _symbolStringPoolSize = 0;
Nick Kledzike34182f2013-11-06 21:36:55 +00001273 for (const Symbol &sym : _file.localSymbols) {
1274 _symbolStringPoolSize += (sym.name.size()+1);
1275 }
1276 for (const Symbol &sym : _file.globalSymbols) {
1277 _symbolStringPoolSize += (sym.name.size()+1);
1278 }
1279 for (const Symbol &sym : _file.undefinedSymbols) {
1280 _symbolStringPoolSize += (sym.name.size()+1);
1281 }
1282 _symbolTableLocalsStartIndex = 0;
1283 _symbolTableGlobalsStartIndex = _file.localSymbols.size();
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001284 _symbolTableUndefinesStartIndex = _symbolTableGlobalsStartIndex
Nick Kledzike34182f2013-11-06 21:36:55 +00001285 + _file.globalSymbols.size();
1286
1287 _indirectSymbolTableCount = 0;
1288 for (const Section &sect : _file.sections) {
1289 _indirectSymbolTableCount += sect.indirectSymbols.size();
1290 }
1291}
1292
Nick Kledzik21921372014-07-24 23:06:56 +00001293void MachOFileLayout::computeDataInCodeSize() {
1294 _dataInCodeSize = _file.dataInCode.size() * sizeof(data_in_code_entry);
1295}
Nick Kledzike34182f2013-11-06 21:36:55 +00001296
1297void MachOFileLayout::writeLinkEditContent() {
1298 if (_file.fileType == llvm::MachO::MH_OBJECT) {
1299 writeRelocations();
Nick Kledzik21921372014-07-24 23:06:56 +00001300 writeDataInCodeInfo();
Nick Kledzike34182f2013-11-06 21:36:55 +00001301 writeSymbolTable();
1302 } else {
1303 writeRebaseInfo();
1304 writeBindingInfo();
1305 writeLazyBindingInfo();
1306 // TODO: add weak binding info
Nick Kledzik141330a2014-09-03 19:52:50 +00001307 writeExportInfo();
Nick Kledzik54ce29582014-10-28 22:21:10 +00001308 writeDataInCodeInfo();
Nick Kledzike34182f2013-11-06 21:36:55 +00001309 writeSymbolTable();
1310 }
1311}
1312
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +00001313std::error_code MachOFileLayout::writeBinary(StringRef path) {
Nick Kledzike34182f2013-11-06 21:36:55 +00001314 // Check for pending error from constructor.
1315 if (_ec)
1316 return _ec;
1317 // Create FileOutputBuffer with calculated size.
Nick Kledzike34182f2013-11-06 21:36:55 +00001318 unsigned flags = 0;
1319 if (_file.fileType != llvm::MachO::MH_OBJECT)
1320 flags = llvm::FileOutputBuffer::F_executable;
Rafael Espindolabdc8f2f2015-08-13 00:31:46 +00001321 ErrorOr<std::unique_ptr<llvm::FileOutputBuffer>> fobOrErr =
1322 llvm::FileOutputBuffer::create(path, size(), flags);
1323 if (std::error_code ec = fobOrErr.getError())
Nick Kledzike34182f2013-11-06 21:36:55 +00001324 return ec;
Rafael Espindolabdc8f2f2015-08-13 00:31:46 +00001325 std::unique_ptr<llvm::FileOutputBuffer> &fob = *fobOrErr;
Nick Kledzike34182f2013-11-06 21:36:55 +00001326 // Write content.
1327 _buffer = fob->getBufferStart();
1328 writeMachHeader();
Rafael Espindolabdc8f2f2015-08-13 00:31:46 +00001329 std::error_code ec = writeLoadCommands();
Nick Kledzike34182f2013-11-06 21:36:55 +00001330 if (ec)
1331 return ec;
1332 writeSectionContent();
1333 writeLinkEditContent();
1334 fob->commit();
1335
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +00001336 return std::error_code();
Nick Kledzike34182f2013-11-06 21:36:55 +00001337}
1338
Nick Kledzike34182f2013-11-06 21:36:55 +00001339/// Takes in-memory normalized view and writes a mach-o object file.
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +00001340std::error_code writeBinary(const NormalizedFile &file, StringRef path) {
Nick Kledzike34182f2013-11-06 21:36:55 +00001341 MachOFileLayout layout(file);
1342 return layout.writeBinary(path);
1343}
1344
Nick Kledzike34182f2013-11-06 21:36:55 +00001345} // namespace normalized
1346} // namespace mach_o
1347} // namespace lld