blob: 7246e4c263fab6d8eb50de4cd4e7b0469abd3af8 [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"
Pete Coopere420dd42016-01-25 21:50:54 +000028#include "llvm/ADT/ilist.h"
29#include "llvm/ADT/ilist_node.h"
Nick Kledzike34182f2013-11-06 21:36:55 +000030#include "llvm/ADT/SmallString.h"
31#include "llvm/ADT/SmallVector.h"
32#include "llvm/ADT/StringRef.h"
33#include "llvm/Support/Casting.h"
34#include "llvm/Support/Debug.h"
Shankar Easwaran2b67fca2014-10-18 05:33:55 +000035#include "llvm/Support/Errc.h"
Nick Kledzike34182f2013-11-06 21:36:55 +000036#include "llvm/Support/ErrorHandling.h"
37#include "llvm/Support/FileOutputBuffer.h"
Nick Kledzik141330a2014-09-03 19:52:50 +000038#include "llvm/Support/Format.h"
Nick Kledzike34182f2013-11-06 21:36:55 +000039#include "llvm/Support/Host.h"
40#include "llvm/Support/MachO.h"
41#include "llvm/Support/MemoryBuffer.h"
42#include "llvm/Support/raw_ostream.h"
Nick Kledzike34182f2013-11-06 21:36:55 +000043#include <functional>
Nick Kledzik07ba5122014-12-02 01:50:44 +000044#include <list>
Nick Kledzike34182f2013-11-06 21:36:55 +000045#include <map>
Rafael Espindola54427cc2014-06-12 17:15:58 +000046#include <system_error>
Nick Kledzike34182f2013-11-06 21:36:55 +000047
48using namespace llvm::MachO;
49
50namespace lld {
51namespace mach_o {
52namespace normalized {
53
Pete Coopere420dd42016-01-25 21:50:54 +000054struct TrieNode; // Forward declaration.
55
56struct TrieEdge : public llvm::ilist_node<TrieEdge> {
57 TrieEdge(StringRef s, TrieNode *node) : _subString(s), _child(node) {}
58
59 StringRef _subString;
60 struct TrieNode *_child;
61};
62
63} // namespace normalized
64} // namespace mach_o
65} // namespace lld
66
67
68namespace llvm {
69 using lld::mach_o::normalized::TrieEdge;
70 template <>
Duncan P. N. Exon Smith623c4c12016-08-12 16:25:04 +000071 struct ilist_traits<TrieEdge> : public ilist_default_traits<TrieEdge> {
Pete Coopere420dd42016-01-25 21:50:54 +000072 void deleteNode(TrieEdge *N) {}
73
74 private:
75 void createNode(const TrieEdge &);
76 };
77} // namespace llvm
78
79
80namespace lld {
81namespace mach_o {
82namespace normalized {
83
84struct TrieNode {
85 typedef llvm::ilist<TrieEdge> TrieEdgeList;
86
87 TrieNode(StringRef s)
88 : _cummulativeString(s), _address(0), _flags(0), _other(0),
89 _trieOffset(0), _hasExportInfo(false) {}
90 ~TrieNode() = default;
91
92 void addSymbol(const Export &entry, BumpPtrAllocator &allocator,
93 std::vector<TrieNode *> &allNodes);
Pete Cooperd0de3682016-08-05 21:37:12 +000094
95 void addOrderedNodes(const Export &entry,
96 std::vector<TrieNode *> &allNodes);
Pete Coopere420dd42016-01-25 21:50:54 +000097 bool updateOffset(uint32_t &offset);
98 void appendToByteBuffer(ByteBuffer &out);
99
100private:
101 StringRef _cummulativeString;
102 TrieEdgeList _children;
103 uint64_t _address;
104 uint64_t _flags;
105 uint64_t _other;
106 StringRef _importedName;
107 uint32_t _trieOffset;
108 bool _hasExportInfo;
Pete Cooperd0de3682016-08-05 21:37:12 +0000109 bool _ordered = false;
Pete Coopere420dd42016-01-25 21:50:54 +0000110};
111
Nick Kledzike34182f2013-11-06 21:36:55 +0000112/// Utility class for writing a mach-o binary file given an in-memory
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000113/// normalized file.
Nick Kledzike34182f2013-11-06 21:36:55 +0000114class MachOFileLayout {
115public:
Joey Goulyb275d7f2013-12-23 23:29:50 +0000116 /// All layout computation is done in the constructor.
117 MachOFileLayout(const NormalizedFile &file);
118
Nick Kledzike34182f2013-11-06 21:36:55 +0000119 /// Returns the final file size as computed in the constructor.
120 size_t size() const;
121
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000122 // Returns size of the mach_header and load commands.
123 size_t headerAndLoadCommandsSize() const;
124
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000125 /// Writes the normalized file as a binary mach-o file to the specified
Nick Kledzike34182f2013-11-06 21:36:55 +0000126 /// path. This does not have a stream interface because the generated
127 /// file may need the 'x' bit set.
Pete Cooperfefbd222016-03-30 23:10:39 +0000128 llvm::Error writeBinary(StringRef path);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000129
Nick Kledzike34182f2013-11-06 21:36:55 +0000130private:
131 uint32_t loadCommandsSize(uint32_t &count);
132 void buildFileOffsets();
133 void writeMachHeader();
Pete Cooper514594b2016-03-31 00:08:16 +0000134 llvm::Error writeLoadCommands();
Nick Kledzike34182f2013-11-06 21:36:55 +0000135 void writeSectionContent();
136 void writeRelocations();
137 void writeSymbolTable();
138 void writeRebaseInfo();
139 void writeBindingInfo();
140 void writeLazyBindingInfo();
Nick Kledzik141330a2014-09-03 19:52:50 +0000141 void writeExportInfo();
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000142 void writeFunctionStartsInfo();
Nick Kledzik21921372014-07-24 23:06:56 +0000143 void writeDataInCodeInfo();
Nick Kledzike34182f2013-11-06 21:36:55 +0000144 void writeLinkEditContent();
145 void buildLinkEditInfo();
146 void buildRebaseInfo();
147 void buildBindInfo();
148 void buildLazyBindInfo();
Nick Kledzik141330a2014-09-03 19:52:50 +0000149 void buildExportTrie();
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000150 void computeFunctionStartsSize();
Nick Kledzik21921372014-07-24 23:06:56 +0000151 void computeDataInCodeSize();
Nick Kledzike34182f2013-11-06 21:36:55 +0000152 void computeSymbolTableSizes();
153 void buildSectionRelocations();
154 void appendSymbols(const std::vector<Symbol> &symbols,
155 uint32_t &symOffset, uint32_t &strOffset);
156 uint32_t indirectSymbolIndex(const Section &sect, uint32_t &index);
157 uint32_t indirectSymbolElementSize(const Section &sect);
158
Nick Kledzik29f749e2013-11-09 00:07:28 +0000159 // For use as template parameter to load command methods.
160 struct MachO64Trait {
161 typedef llvm::MachO::segment_command_64 command;
162 typedef llvm::MachO::section_64 section;
163 enum { LC = llvm::MachO::LC_SEGMENT_64 };
164 };
165
166 // For use as template parameter to load command methods.
167 struct MachO32Trait {
168 typedef llvm::MachO::segment_command command;
169 typedef llvm::MachO::section section;
170 enum { LC = llvm::MachO::LC_SEGMENT };
171 };
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000172
Nick Kledzik29f749e2013-11-09 00:07:28 +0000173 template <typename T>
Pete Cooper514594b2016-03-31 00:08:16 +0000174 llvm::Error writeSingleSegmentLoadCommand(uint8_t *&lc);
175 template <typename T> llvm::Error writeSegmentLoadCommands(uint8_t *&lc);
Nick Kledzik29f749e2013-11-09 00:07:28 +0000176
Nick Kledzike34182f2013-11-06 21:36:55 +0000177 uint32_t pointerAlign(uint32_t value);
178 static StringRef dyldPath();
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000179
Nick Kledzike34182f2013-11-06 21:36:55 +0000180 struct SegExtraInfo {
181 uint32_t fileOffset;
Tim Northover08d6a7b2014-06-30 09:49:30 +0000182 uint32_t fileSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000183 std::vector<const Section*> sections;
184 };
185 typedef std::map<const Segment*, SegExtraInfo> SegMap;
186 struct SectionExtraInfo {
187 uint32_t fileOffset;
188 };
189 typedef std::map<const Section*, SectionExtraInfo> SectionMap;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000190
Nick Kledzike34182f2013-11-06 21:36:55 +0000191 const NormalizedFile &_file;
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000192 std::error_code _ec;
Nick Kledzike34182f2013-11-06 21:36:55 +0000193 uint8_t *_buffer;
194 const bool _is64;
195 const bool _swap;
196 const bool _bigEndianArch;
197 uint64_t _seg1addr;
198 uint32_t _startOfLoadCommands;
199 uint32_t _countOfLoadCommands;
200 uint32_t _endOfLoadCommands;
201 uint32_t _startOfRelocations;
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000202 uint32_t _startOfFunctionStarts;
Nick Kledzik21921372014-07-24 23:06:56 +0000203 uint32_t _startOfDataInCode;
Nick Kledzike34182f2013-11-06 21:36:55 +0000204 uint32_t _startOfSymbols;
205 uint32_t _startOfIndirectSymbols;
206 uint32_t _startOfSymbolStrings;
207 uint32_t _endOfSymbolStrings;
208 uint32_t _symbolTableLocalsStartIndex;
209 uint32_t _symbolTableGlobalsStartIndex;
210 uint32_t _symbolTableUndefinesStartIndex;
211 uint32_t _symbolStringPoolSize;
212 uint32_t _symbolTableSize;
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000213 uint32_t _functionStartsSize;
Nick Kledzik21921372014-07-24 23:06:56 +0000214 uint32_t _dataInCodeSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000215 uint32_t _indirectSymbolTableCount;
216 // Used in object file creation only
217 uint32_t _startOfSectionsContent;
218 uint32_t _endOfSectionsContent;
219 // Used in final linked image only
220 uint32_t _startOfLinkEdit;
221 uint32_t _startOfRebaseInfo;
222 uint32_t _endOfRebaseInfo;
223 uint32_t _startOfBindingInfo;
224 uint32_t _endOfBindingInfo;
225 uint32_t _startOfLazyBindingInfo;
226 uint32_t _endOfLazyBindingInfo;
Nick Kledzik141330a2014-09-03 19:52:50 +0000227 uint32_t _startOfExportTrie;
228 uint32_t _endOfExportTrie;
Nick Kledzike34182f2013-11-06 21:36:55 +0000229 uint32_t _endOfLinkEdit;
230 uint64_t _addressOfLinkEdit;
231 SegMap _segInfo;
232 SectionMap _sectInfo;
233 ByteBuffer _rebaseInfo;
234 ByteBuffer _bindingInfo;
235 ByteBuffer _lazyBindingInfo;
236 ByteBuffer _weakBindingInfo;
Nick Kledzik141330a2014-09-03 19:52:50 +0000237 ByteBuffer _exportTrie;
Nick Kledzike34182f2013-11-06 21:36:55 +0000238};
239
240size_t headerAndLoadCommandsSize(const NormalizedFile &file) {
241 MachOFileLayout layout(file);
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000242 return layout.headerAndLoadCommandsSize();
Nick Kledzike34182f2013-11-06 21:36:55 +0000243}
244
245StringRef MachOFileLayout::dyldPath() {
246 return "/usr/lib/dyld";
247}
248
249uint32_t MachOFileLayout::pointerAlign(uint32_t value) {
Rui Ueyama489a8062016-01-14 20:53:50 +0000250 return llvm::alignTo(value, _is64 ? 8 : 4);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000251}
Nick Kledzike34182f2013-11-06 21:36:55 +0000252
253
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000254size_t MachOFileLayout::headerAndLoadCommandsSize() const {
255 return _endOfLoadCommands;
256}
Nick Kledzike34182f2013-11-06 21:36:55 +0000257
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000258MachOFileLayout::MachOFileLayout(const NormalizedFile &file)
Nick Kledzike34182f2013-11-06 21:36:55 +0000259 : _file(file),
260 _is64(MachOLinkingContext::is64Bit(file.arch)),
261 _swap(!MachOLinkingContext::isHostEndian(file.arch)),
262 _bigEndianArch(MachOLinkingContext::isBigEndian(file.arch)),
263 _seg1addr(INT64_MAX) {
264 _startOfLoadCommands = _is64 ? sizeof(mach_header_64) : sizeof(mach_header);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000265 const size_t segCommandBaseSize =
Nick Kledzike34182f2013-11-06 21:36:55 +0000266 (_is64 ? sizeof(segment_command_64) : sizeof(segment_command));
267 const size_t sectsSize = (_is64 ? sizeof(section_64) : sizeof(section));
268 if (file.fileType == llvm::MachO::MH_OBJECT) {
269 // object files have just one segment load command containing all sections
270 _endOfLoadCommands = _startOfLoadCommands
271 + segCommandBaseSize
272 + file.sections.size() * sectsSize
273 + sizeof(symtab_command);
274 _countOfLoadCommands = 2;
Pete Cooperceee5de2016-02-04 02:16:08 +0000275 if (file.hasMinVersionLoadCommand) {
276 _endOfLoadCommands += sizeof(version_min_command);
277 _countOfLoadCommands++;
278 }
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000279 if (!_file.functionStarts.empty()) {
280 _endOfLoadCommands += sizeof(linkedit_data_command);
281 _countOfLoadCommands++;
282 }
Pete Cooper9b28a452016-02-09 02:10:39 +0000283 if (_file.generateDataInCodeLoadCommand) {
Nick Kledzik21921372014-07-24 23:06:56 +0000284 _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) {
Lang Hamesac2adce2015-12-11 23:25:09 +0000292 if (isZeroFillSection(sect.type))
293 _sectInfo[&sect].fileOffset = 0;
294 else {
Rui Ueyama489a8062016-01-14 20:53:50 +0000295 offset = llvm::alignTo(offset, sect.alignment);
Nick Kledzikb072c362014-11-18 00:30:29 +0000296 _sectInfo[&sect].fileOffset = offset;
297 offset += sect.content.size();
Nick Kledzikb072c362014-11-18 00:30:29 +0000298 }
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();
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000304 computeFunctionStartsSize();
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);
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000309 _startOfFunctionStarts = _startOfRelocations + relocCount * 8;
310 _startOfDataInCode = _startOfFunctionStarts + _functionStartsSize;
Nick Kledzik21921372014-07-24 23:06:56 +0000311 _startOfSymbols = _startOfDataInCode + _dataInCodeSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000312 // Add Indirect symbol table.
313 _startOfIndirectSymbols = _startOfSymbols + _symbolTableSize;
314 // Align start of symbol table and symbol strings.
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000315 _startOfSymbolStrings = _startOfIndirectSymbols
Nick Kledzike34182f2013-11-06 21:36:55 +0000316 + pointerAlign(_indirectSymbolTableCount * sizeof(uint32_t));
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000317 _endOfSymbolStrings = _startOfSymbolStrings
Nick Kledzike34182f2013-11-06 21:36:55 +0000318 + pointerAlign(_symbolStringPoolSize);
319 _endOfLinkEdit = _endOfSymbolStrings;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000320 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000321 llvm::dbgs() << "MachOFileLayout()\n"
322 << " startOfLoadCommands=" << _startOfLoadCommands << "\n"
323 << " countOfLoadCommands=" << _countOfLoadCommands << "\n"
324 << " endOfLoadCommands=" << _endOfLoadCommands << "\n"
325 << " startOfRelocations=" << _startOfRelocations << "\n"
326 << " startOfSymbols=" << _startOfSymbols << "\n"
327 << " startOfSymbolStrings=" << _startOfSymbolStrings << "\n"
328 << " endOfSymbolStrings=" << _endOfSymbolStrings << "\n"
329 << " startOfSectionsContent=" << _startOfSectionsContent << "\n"
330 << " endOfSectionsContent=" << _endOfSectionsContent << "\n");
331 } else {
332 // Final linked images have one load command per segment.
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000333 _endOfLoadCommands = _startOfLoadCommands
Nick Kledzike34182f2013-11-06 21:36:55 +0000334 + loadCommandsSize(_countOfLoadCommands);
335
336 // Assign section file offsets.
337 buildFileOffsets();
338 buildLinkEditInfo();
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000339
Nick Kledzike34182f2013-11-06 21:36:55 +0000340 // LINKEDIT of final linked images has in order:
341 // rebase info, binding info, lazy binding info, weak binding info,
Nick Kledzik21921372014-07-24 23:06:56 +0000342 // data-in-code, symbol table, indirect symbol table, symbol table strings.
Nick Kledzike34182f2013-11-06 21:36:55 +0000343 _startOfRebaseInfo = _startOfLinkEdit;
344 _endOfRebaseInfo = _startOfRebaseInfo + _rebaseInfo.size();
345 _startOfBindingInfo = _endOfRebaseInfo;
346 _endOfBindingInfo = _startOfBindingInfo + _bindingInfo.size();
347 _startOfLazyBindingInfo = _endOfBindingInfo;
348 _endOfLazyBindingInfo = _startOfLazyBindingInfo + _lazyBindingInfo.size();
Nick Kledzik141330a2014-09-03 19:52:50 +0000349 _startOfExportTrie = _endOfLazyBindingInfo;
350 _endOfExportTrie = _startOfExportTrie + _exportTrie.size();
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000351 _startOfFunctionStarts = _endOfExportTrie;
352 _startOfDataInCode = _startOfFunctionStarts + _functionStartsSize;
Nick Kledzik21921372014-07-24 23:06:56 +0000353 _startOfSymbols = _startOfDataInCode + _dataInCodeSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000354 _startOfIndirectSymbols = _startOfSymbols + _symbolTableSize;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000355 _startOfSymbolStrings = _startOfIndirectSymbols
Nick Kledzike34182f2013-11-06 21:36:55 +0000356 + pointerAlign(_indirectSymbolTableCount * sizeof(uint32_t));
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000357 _endOfSymbolStrings = _startOfSymbolStrings
Nick Kledzike34182f2013-11-06 21:36:55 +0000358 + pointerAlign(_symbolStringPoolSize);
359 _endOfLinkEdit = _endOfSymbolStrings;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000360 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000361 llvm::dbgs() << "MachOFileLayout()\n"
362 << " startOfLoadCommands=" << _startOfLoadCommands << "\n"
363 << " countOfLoadCommands=" << _countOfLoadCommands << "\n"
364 << " endOfLoadCommands=" << _endOfLoadCommands << "\n"
365 << " startOfLinkEdit=" << _startOfLinkEdit << "\n"
366 << " startOfRebaseInfo=" << _startOfRebaseInfo << "\n"
367 << " endOfRebaseInfo=" << _endOfRebaseInfo << "\n"
368 << " startOfBindingInfo=" << _startOfBindingInfo << "\n"
369 << " endOfBindingInfo=" << _endOfBindingInfo << "\n"
370 << " startOfLazyBindingInfo=" << _startOfLazyBindingInfo << "\n"
371 << " endOfLazyBindingInfo=" << _endOfLazyBindingInfo << "\n"
Nick Kledzik141330a2014-09-03 19:52:50 +0000372 << " startOfExportTrie=" << _startOfExportTrie << "\n"
373 << " endOfExportTrie=" << _endOfExportTrie << "\n"
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000374 << " startOfFunctionStarts=" << _startOfFunctionStarts << "\n"
Nick Kledzik21921372014-07-24 23:06:56 +0000375 << " startOfDataInCode=" << _startOfDataInCode << "\n"
Nick Kledzike34182f2013-11-06 21:36:55 +0000376 << " startOfSymbols=" << _startOfSymbols << "\n"
377 << " startOfSymbolStrings=" << _startOfSymbolStrings << "\n"
378 << " endOfSymbolStrings=" << _endOfSymbolStrings << "\n"
379 << " addressOfLinkEdit=" << _addressOfLinkEdit << "\n");
380 }
381}
382
383uint32_t MachOFileLayout::loadCommandsSize(uint32_t &count) {
384 uint32_t size = 0;
385 count = 0;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000386
387 const size_t segCommandSize =
Nick Kledzike34182f2013-11-06 21:36:55 +0000388 (_is64 ? sizeof(segment_command_64) : sizeof(segment_command));
389 const size_t sectionSize = (_is64 ? sizeof(section_64) : sizeof(section));
390
391 // Add LC_SEGMENT for each segment.
392 size += _file.segments.size() * segCommandSize;
393 count += _file.segments.size();
394 // Add section record for each section.
395 size += _file.sections.size() * sectionSize;
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
Pete Cooper354809e2016-02-03 22:28:29 +0000417 // If main executable add LC_LOAD_DYLINKER
Nick Kledzike34182f2013-11-06 21:36:55 +0000418 if (_file.fileType == llvm::MachO::MH_EXECUTE) {
419 size += pointerAlign(sizeof(dylinker_command) + dyldPath().size()+1);
420 ++count;
Pete Cooper354809e2016-02-03 22:28:29 +0000421 }
422
423 // Add LC_VERSION_MIN_MACOSX, LC_VERSION_MIN_IPHONEOS, LC_VERSION_MIN_WATCHOS,
424 // LC_VERSION_MIN_TVOS
425 if (_file.hasMinVersionLoadCommand) {
426 size += sizeof(version_min_command);
427 ++count;
428 }
429
Pete Cooper40576fa2016-02-04 02:45:23 +0000430 // Add LC_SOURCE_VERSION
431 size += sizeof(source_version_command);
432 ++count;
433
Pete Cooper354809e2016-02-03 22:28:29 +0000434 // If main executable add LC_MAIN
435 if (_file.fileType == llvm::MachO::MH_EXECUTE) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000436 size += sizeof(entry_point_command);
437 ++count;
438 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000439
Nick Kledzike34182f2013-11-06 21:36:55 +0000440 // Add LC_LOAD_DYLIB for each dependent dylib.
441 for (const DependentDylib &dep : _file.dependentDylibs) {
442 size += sizeof(dylib_command) + pointerAlign(dep.path.size()+1);
443 ++count;
444 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000445
Jean-Daniel Dupas23dd15e2014-12-18 21:33:38 +0000446 // Add LC_RPATH
447 for (const StringRef &path : _file.rpaths) {
Lang Hames2ed3bf92015-10-29 16:50:26 +0000448 size += pointerAlign(sizeof(rpath_command) + path.size() + 1);
Jean-Daniel Dupas23dd15e2014-12-18 21:33:38 +0000449 ++count;
450 }
451
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000452 // Add LC_FUNCTION_STARTS if needed
453 if (!_file.functionStarts.empty()) {
454 size += sizeof(linkedit_data_command);
455 ++count;
456 }
457
Pete Cooper9b28a452016-02-09 02:10:39 +0000458 // Add LC_DATA_IN_CODE if requested. Note, we do encode zero length entries.
459 // FIXME: Zero length entries is only to match ld64. Should we change this?
460 if (_file.generateDataInCodeLoadCommand) {
Nick Kledzik54ce29582014-10-28 22:21:10 +0000461 size += sizeof(linkedit_data_command);
462 ++count;
463 }
464
Nick Kledzike34182f2013-11-06 21:36:55 +0000465 return size;
466}
467
468static bool overlaps(const Segment &s1, const Segment &s2) {
469 if (s2.address >= s1.address+s1.size)
470 return false;
471 if (s1.address >= s2.address+s2.size)
472 return false;
473 return true;
474}
475
476static bool overlaps(const Section &s1, const Section &s2) {
477 if (s2.address >= s1.address+s1.content.size())
478 return false;
479 if (s1.address >= s2.address+s2.content.size())
480 return false;
481 return true;
482}
483
484void MachOFileLayout::buildFileOffsets() {
485 // Verify no segments overlap
486 for (const Segment &sg1 : _file.segments) {
487 for (const Segment &sg2 : _file.segments) {
488 if (&sg1 == &sg2)
489 continue;
490 if (overlaps(sg1,sg2)) {
Rafael Espindola372bc702014-06-13 17:20:48 +0000491 _ec = make_error_code(llvm::errc::executable_format_error);
Nick Kledzike34182f2013-11-06 21:36:55 +0000492 return;
493 }
494 }
495 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000496
497 // Verify no sections overlap
Nick Kledzike34182f2013-11-06 21:36:55 +0000498 for (const Section &s1 : _file.sections) {
499 for (const Section &s2 : _file.sections) {
500 if (&s1 == &s2)
501 continue;
502 if (overlaps(s1,s2)) {
Rafael Espindola372bc702014-06-13 17:20:48 +0000503 _ec = make_error_code(llvm::errc::executable_format_error);
Nick Kledzike34182f2013-11-06 21:36:55 +0000504 return;
505 }
506 }
507 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000508
Nick Kledzike34182f2013-11-06 21:36:55 +0000509 // Build side table of extra info about segments and sections.
510 SegExtraInfo t;
511 t.fileOffset = 0;
512 for (const Segment &sg : _file.segments) {
513 _segInfo[&sg] = t;
514 }
515 SectionExtraInfo t2;
516 t2.fileOffset = 0;
517 // Assign sections to segments.
518 for (const Section &s : _file.sections) {
519 _sectInfo[&s] = t2;
Nick Kledzik1bebb282014-09-09 23:52:59 +0000520 bool foundSegment = false;
Nick Kledzike34182f2013-11-06 21:36:55 +0000521 for (const Segment &sg : _file.segments) {
Nick Kledzik1bebb282014-09-09 23:52:59 +0000522 if (sg.name.equals(s.segmentName)) {
523 if ((s.address >= sg.address)
Nick Kledzike34182f2013-11-06 21:36:55 +0000524 && (s.address+s.content.size() <= sg.address+sg.size)) {
Nick Kledzik1bebb282014-09-09 23:52:59 +0000525 _segInfo[&sg].sections.push_back(&s);
526 foundSegment = true;
527 break;
Nick Kledzike34182f2013-11-06 21:36:55 +0000528 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000529 }
530 }
Nick Kledzik1bebb282014-09-09 23:52:59 +0000531 if (!foundSegment) {
532 _ec = make_error_code(llvm::errc::executable_format_error);
533 return;
534 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000535 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000536
Nick Kledzike34182f2013-11-06 21:36:55 +0000537 // Assign file offsets.
538 uint32_t fileOffset = 0;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000539 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000540 llvm::dbgs() << "buildFileOffsets()\n");
541 for (const Segment &sg : _file.segments) {
Tim Northover08d6a7b2014-06-30 09:49:30 +0000542 _segInfo[&sg].fileOffset = fileOffset;
Pete Cooperb8fec3e2016-02-06 00:51:16 +0000543 if ((_seg1addr == INT64_MAX) && sg.init_access)
Nick Kledzike34182f2013-11-06 21:36:55 +0000544 _seg1addr = sg.address;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000545 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000546 llvm::dbgs() << " segment=" << sg.name
547 << ", fileOffset=" << _segInfo[&sg].fileOffset << "\n");
Tim Northover08d6a7b2014-06-30 09:49:30 +0000548
549 uint32_t segFileSize = 0;
Nick Kledzik761d6542014-10-24 22:19:22 +0000550 // A segment that is not zero-fill must use a least one page of disk space.
Pete Cooperb8fec3e2016-02-06 00:51:16 +0000551 if (sg.init_access)
Nick Kledzik761d6542014-10-24 22:19:22 +0000552 segFileSize = _file.pageSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000553 for (const Section *s : _segInfo[&sg].sections) {
Tim Northover08d6a7b2014-06-30 09:49:30 +0000554 uint32_t sectOffset = s->address - sg.address;
555 uint32_t sectFileSize =
Lang Hamesac2adce2015-12-11 23:25:09 +0000556 isZeroFillSection(s->type) ? 0 : s->content.size();
Tim Northover08d6a7b2014-06-30 09:49:30 +0000557 segFileSize = std::max(segFileSize, sectOffset + sectFileSize);
558
559 _sectInfo[s].fileOffset = _segInfo[&sg].fileOffset + sectOffset;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000560 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000561 llvm::dbgs() << " section=" << s->sectionName
562 << ", fileOffset=" << fileOffset << "\n");
563 }
Tim Northover08d6a7b2014-06-30 09:49:30 +0000564
Pete Cooper353652f2016-02-06 00:14:15 +0000565 // round up all segments to page aligned, except __LINKEDIT
566 if (!sg.name.equals("__LINKEDIT")) {
567 _segInfo[&sg].fileSize = llvm::alignTo(segFileSize, _file.pageSize);
568 fileOffset = llvm::alignTo(fileOffset + segFileSize, _file.pageSize);
569 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000570 _addressOfLinkEdit = sg.address + sg.size;
571 }
Tim Northover08d6a7b2014-06-30 09:49:30 +0000572 _startOfLinkEdit = fileOffset;
Nick Kledzike34182f2013-11-06 21:36:55 +0000573}
574
Nick Kledzike34182f2013-11-06 21:36:55 +0000575size_t MachOFileLayout::size() const {
576 return _endOfSymbolStrings;
577}
578
579void MachOFileLayout::writeMachHeader() {
Pete Cooper8563e5a2016-02-04 20:43:43 +0000580 auto cpusubtype = MachOLinkingContext::cpuSubtypeFromArch(_file.arch);
581 // dynamic x86 executables on newer OS version should also set the
582 // CPU_SUBTYPE_LIB64 mask in the CPU subtype.
583 // FIXME: Check that this is a dynamic executable, not a static one.
584 if (_file.fileType == llvm::MachO::MH_EXECUTE &&
585 cpusubtype == CPU_SUBTYPE_X86_64_ALL &&
586 _file.os == MachOLinkingContext::OS::macOSX) {
587 uint32_t version;
588 bool failed = MachOLinkingContext::parsePackedVersion("10.5", version);
589 if (!failed && _file.minOSverson >= version)
590 cpusubtype |= CPU_SUBTYPE_LIB64;
591 }
592
Nick Kledzike34182f2013-11-06 21:36:55 +0000593 mach_header *mh = reinterpret_cast<mach_header*>(_buffer);
594 mh->magic = _is64 ? llvm::MachO::MH_MAGIC_64 : llvm::MachO::MH_MAGIC;
595 mh->cputype = MachOLinkingContext::cpuTypeFromArch(_file.arch);
Pete Cooper8563e5a2016-02-04 20:43:43 +0000596 mh->cpusubtype = cpusubtype;
Nick Kledzike34182f2013-11-06 21:36:55 +0000597 mh->filetype = _file.fileType;
598 mh->ncmds = _countOfLoadCommands;
599 mh->sizeofcmds = _endOfLoadCommands - _startOfLoadCommands;
600 mh->flags = _file.flags;
601 if (_swap)
602 swapStruct(*mh);
603}
604
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000605uint32_t MachOFileLayout::indirectSymbolIndex(const Section &sect,
Nick Kledzike34182f2013-11-06 21:36:55 +0000606 uint32_t &index) {
607 if (sect.indirectSymbols.empty())
608 return 0;
609 uint32_t result = index;
610 index += sect.indirectSymbols.size();
611 return result;
612}
613
614uint32_t MachOFileLayout::indirectSymbolElementSize(const Section &sect) {
615 if (sect.indirectSymbols.empty())
616 return 0;
617 if (sect.type != S_SYMBOL_STUBS)
618 return 0;
619 return sect.content.size() / sect.indirectSymbols.size();
620}
621
Nick Kledzik29f749e2013-11-09 00:07:28 +0000622template <typename T>
Pete Cooper514594b2016-03-31 00:08:16 +0000623llvm::Error MachOFileLayout::writeSingleSegmentLoadCommand(uint8_t *&lc) {
Nick Kledzik29f749e2013-11-09 00:07:28 +0000624 typename T::command* seg = reinterpret_cast<typename T::command*>(lc);
625 seg->cmd = T::LC;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000626 seg->cmdsize = sizeof(typename T::command)
Nick Kledzik29f749e2013-11-09 00:07:28 +0000627 + _file.sections.size() * sizeof(typename T::section);
Nick Kledzike34182f2013-11-06 21:36:55 +0000628 uint8_t *next = lc + seg->cmdsize;
629 memset(seg->segname, 0, 16);
630 seg->vmaddr = 0;
Nick Kledzikb072c362014-11-18 00:30:29 +0000631 seg->vmsize = _file.sections.back().address
632 + _file.sections.back().content.size();
Nick Kledzike34182f2013-11-06 21:36:55 +0000633 seg->fileoff = _endOfLoadCommands;
Lang Hames8c2406b2016-08-10 22:15:09 +0000634 seg->filesize = _sectInfo[&_file.sections.back()].fileOffset +
635 _file.sections.back().content.size() -
636 _sectInfo[&_file.sections.front()].fileOffset;
Nick Kledzike34182f2013-11-06 21:36:55 +0000637 seg->maxprot = VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE;
638 seg->initprot = VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE;
639 seg->nsects = _file.sections.size();
640 seg->flags = 0;
641 if (_swap)
642 swapStruct(*seg);
Nick Kledzik29f749e2013-11-09 00:07:28 +0000643 typename T::section *sout = reinterpret_cast<typename T::section*>
644 (lc+sizeof(typename T::command));
Nick Kledzike34182f2013-11-06 21:36:55 +0000645 uint32_t relOffset = _startOfRelocations;
Nick Kledzike34182f2013-11-06 21:36:55 +0000646 uint32_t indirectSymRunningIndex = 0;
647 for (const Section &sin : _file.sections) {
648 setString16(sin.sectionName, sout->sectname);
649 setString16(sin.segmentName, sout->segname);
650 sout->addr = sin.address;
651 sout->size = sin.content.size();
Nick Kledzikb072c362014-11-18 00:30:29 +0000652 sout->offset = _sectInfo[&sin].fileOffset;
Rui Ueyamaf217ef02015-03-26 02:03:44 +0000653 sout->align = llvm::Log2_32(sin.alignment);
Nick Kledzike34182f2013-11-06 21:36:55 +0000654 sout->reloff = sin.relocations.empty() ? 0 : relOffset;
655 sout->nreloc = sin.relocations.size();
656 sout->flags = sin.type | sin.attributes;
657 sout->reserved1 = indirectSymbolIndex(sin, indirectSymRunningIndex);
658 sout->reserved2 = indirectSymbolElementSize(sin);
659 relOffset += sin.relocations.size() * sizeof(any_relocation_info);
Nick Kledzike34182f2013-11-06 21:36:55 +0000660 if (_swap)
661 swapStruct(*sout);
662 ++sout;
663 }
664 lc = next;
Pete Cooper514594b2016-03-31 00:08:16 +0000665 return llvm::Error();
Nick Kledzike34182f2013-11-06 21:36:55 +0000666}
667
Nick Kledzik29f749e2013-11-09 00:07:28 +0000668template <typename T>
Pete Cooper514594b2016-03-31 00:08:16 +0000669llvm::Error MachOFileLayout::writeSegmentLoadCommands(uint8_t *&lc) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000670 uint32_t indirectSymRunningIndex = 0;
671 for (const Segment &seg : _file.segments) {
Pete Cooper353652f2016-02-06 00:14:15 +0000672 // Link edit has no sections and a custom range of address, so handle it
673 // specially.
Nick Kledzike34182f2013-11-06 21:36:55 +0000674 SegExtraInfo &segInfo = _segInfo[&seg];
Pete Cooper353652f2016-02-06 00:14:15 +0000675 if (seg.name.equals("__LINKEDIT")) {
676 size_t linkeditSize = _endOfLinkEdit - _startOfLinkEdit;
677 typename T::command* cmd = reinterpret_cast<typename T::command*>(lc);
678 cmd->cmd = T::LC;
679 cmd->cmdsize = sizeof(typename T::command);
680 uint8_t *next = lc + cmd->cmdsize;
681 setString16("__LINKEDIT", cmd->segname);
682 cmd->vmaddr = _addressOfLinkEdit;
683 cmd->vmsize = llvm::alignTo(linkeditSize, _file.pageSize);
684 cmd->fileoff = _startOfLinkEdit;
685 cmd->filesize = linkeditSize;
Pete Cooperb8fec3e2016-02-06 00:51:16 +0000686 cmd->initprot = seg.init_access;
687 cmd->maxprot = seg.max_access;
Pete Cooper353652f2016-02-06 00:14:15 +0000688 cmd->nsects = 0;
689 cmd->flags = 0;
690 if (_swap)
691 swapStruct(*cmd);
692 lc = next;
693 continue;
694 }
695 // Write segment command with trailing sections.
Nick Kledzik29f749e2013-11-09 00:07:28 +0000696 typename T::command* cmd = reinterpret_cast<typename T::command*>(lc);
697 cmd->cmd = T::LC;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000698 cmd->cmdsize = sizeof(typename T::command)
Nick Kledzik29f749e2013-11-09 00:07:28 +0000699 + segInfo.sections.size() * sizeof(typename T::section);
Nick Kledzike34182f2013-11-06 21:36:55 +0000700 uint8_t *next = lc + cmd->cmdsize;
701 setString16(seg.name, cmd->segname);
702 cmd->vmaddr = seg.address;
703 cmd->vmsize = seg.size;
704 cmd->fileoff = segInfo.fileOffset;
Tim Northover08d6a7b2014-06-30 09:49:30 +0000705 cmd->filesize = segInfo.fileSize;
Pete Cooperb8fec3e2016-02-06 00:51:16 +0000706 cmd->initprot = seg.init_access;
707 cmd->maxprot = seg.max_access;
Nick Kledzike34182f2013-11-06 21:36:55 +0000708 cmd->nsects = segInfo.sections.size();
709 cmd->flags = 0;
710 if (_swap)
711 swapStruct(*cmd);
Nick Kledzik29f749e2013-11-09 00:07:28 +0000712 typename T::section *sect = reinterpret_cast<typename T::section*>
713 (lc+sizeof(typename T::command));
Nick Kledzike34182f2013-11-06 21:36:55 +0000714 for (const Section *section : segInfo.sections) {
715 setString16(section->sectionName, sect->sectname);
716 setString16(section->segmentName, sect->segname);
717 sect->addr = section->address;
718 sect->size = section->content.size();
Lang Hamesac2adce2015-12-11 23:25:09 +0000719 if (isZeroFillSection(section->type))
Nick Kledzikb072c362014-11-18 00:30:29 +0000720 sect->offset = 0;
721 else
722 sect->offset = section->address - seg.address + segInfo.fileOffset;
Rui Ueyamaf217ef02015-03-26 02:03:44 +0000723 sect->align = llvm::Log2_32(section->alignment);
Nick Kledzike34182f2013-11-06 21:36:55 +0000724 sect->reloff = 0;
725 sect->nreloc = 0;
726 sect->flags = section->type | section->attributes;
727 sect->reserved1 = indirectSymbolIndex(*section, indirectSymRunningIndex);
728 sect->reserved2 = indirectSymbolElementSize(*section);
729 if (_swap)
730 swapStruct(*sect);
731 ++sect;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000732 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000733 lc = reinterpret_cast<uint8_t*>(next);
734 }
Pete Cooper514594b2016-03-31 00:08:16 +0000735 return llvm::Error();
Nick Kledzike34182f2013-11-06 21:36:55 +0000736}
737
Pete Cooperceee5de2016-02-04 02:16:08 +0000738static void writeVersionMinLoadCommand(const NormalizedFile &_file,
739 bool _swap,
740 uint8_t *&lc) {
741 if (!_file.hasMinVersionLoadCommand)
742 return;
743 version_min_command *vm = reinterpret_cast<version_min_command*>(lc);
744 switch (_file.os) {
745 case MachOLinkingContext::OS::unknown:
746 vm->cmd = _file.minOSVersionKind;
747 vm->cmdsize = sizeof(version_min_command);
748 vm->version = _file.minOSverson;
749 vm->sdk = 0;
750 break;
751 case MachOLinkingContext::OS::macOSX:
752 vm->cmd = LC_VERSION_MIN_MACOSX;
753 vm->cmdsize = sizeof(version_min_command);
754 vm->version = _file.minOSverson;
755 vm->sdk = _file.sdkVersion;
756 break;
757 case MachOLinkingContext::OS::iOS:
758 case MachOLinkingContext::OS::iOS_simulator:
759 vm->cmd = LC_VERSION_MIN_IPHONEOS;
760 vm->cmdsize = sizeof(version_min_command);
761 vm->version = _file.minOSverson;
762 vm->sdk = _file.sdkVersion;
763 break;
764 }
765 if (_swap)
766 swapStruct(*vm);
767 lc += sizeof(version_min_command);
768}
769
Pete Cooper514594b2016-03-31 00:08:16 +0000770llvm::Error MachOFileLayout::writeLoadCommands() {
Nick Kledzike34182f2013-11-06 21:36:55 +0000771 uint8_t *lc = &_buffer[_startOfLoadCommands];
772 if (_file.fileType == llvm::MachO::MH_OBJECT) {
773 // Object files have one unnamed segment which holds all sections.
Pete Cooper514594b2016-03-31 00:08:16 +0000774 if (_is64) {
775 if (auto ec = writeSingleSegmentLoadCommand<MachO64Trait>(lc))
Pete Coopere487da12016-03-31 00:35:50 +0000776 return ec;
Pete Cooper514594b2016-03-31 00:08:16 +0000777 } else {
778 if (auto ec = writeSingleSegmentLoadCommand<MachO32Trait>(lc))
Pete Cooperdc59c792016-03-31 00:38:02 +0000779 return ec;
Pete Cooper514594b2016-03-31 00:08:16 +0000780 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000781 // Add LC_SYMTAB with symbol table info
782 symtab_command* st = reinterpret_cast<symtab_command*>(lc);
783 st->cmd = LC_SYMTAB;
784 st->cmdsize = sizeof(symtab_command);
785 st->symoff = _startOfSymbols;
Lang Hames436f7d62016-07-27 22:55:30 +0000786 st->nsyms = _file.stabsSymbols.size() + _file.localSymbols.size() +
787 _file.globalSymbols.size() + _file.undefinedSymbols.size();
Nick Kledzike34182f2013-11-06 21:36:55 +0000788 st->stroff = _startOfSymbolStrings;
789 st->strsize = _endOfSymbolStrings - _startOfSymbolStrings;
790 if (_swap)
791 swapStruct(*st);
Nick Kledzik21921372014-07-24 23:06:56 +0000792 lc += sizeof(symtab_command);
Pete Cooperceee5de2016-02-04 02:16:08 +0000793
794 // Add LC_VERSION_MIN_MACOSX, LC_VERSION_MIN_IPHONEOS,
795 // LC_VERSION_MIN_WATCHOS, LC_VERSION_MIN_TVOS
796 writeVersionMinLoadCommand(_file, _swap, lc);
797
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000798 // Add LC_FUNCTION_STARTS if needed.
799 if (_functionStartsSize != 0) {
800 linkedit_data_command* dl = reinterpret_cast<linkedit_data_command*>(lc);
801 dl->cmd = LC_FUNCTION_STARTS;
802 dl->cmdsize = sizeof(linkedit_data_command);
803 dl->dataoff = _startOfFunctionStarts;
804 dl->datasize = _functionStartsSize;
805 if (_swap)
806 swapStruct(*dl);
807 lc += sizeof(linkedit_data_command);
808 }
809
Pete Cooper9b28a452016-02-09 02:10:39 +0000810 // Add LC_DATA_IN_CODE if requested.
811 if (_file.generateDataInCodeLoadCommand) {
Nick Kledzik21921372014-07-24 23:06:56 +0000812 linkedit_data_command* dl = reinterpret_cast<linkedit_data_command*>(lc);
813 dl->cmd = LC_DATA_IN_CODE;
814 dl->cmdsize = sizeof(linkedit_data_command);
815 dl->dataoff = _startOfDataInCode;
816 dl->datasize = _dataInCodeSize;
817 if (_swap)
818 swapStruct(*dl);
819 lc += sizeof(linkedit_data_command);
820 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000821 } else {
822 // Final linked images have sections under segments.
Pete Cooper514594b2016-03-31 00:08:16 +0000823 if (_is64) {
824 if (auto ec = writeSegmentLoadCommands<MachO64Trait>(lc))
Pete Cooperdc59c792016-03-31 00:38:02 +0000825 return ec;
Pete Cooper514594b2016-03-31 00:08:16 +0000826 } else {
827 if (auto ec = writeSegmentLoadCommands<MachO32Trait>(lc))
Pete Cooperdc59c792016-03-31 00:38:02 +0000828 return ec;
Pete Cooper514594b2016-03-31 00:08:16 +0000829 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000830
Tim Northover301c4e62014-07-01 08:15:41 +0000831 // Add LC_ID_DYLIB command for dynamic libraries.
832 if (_file.fileType == llvm::MachO::MH_DYLIB) {
833 dylib_command *dc = reinterpret_cast<dylib_command*>(lc);
834 StringRef path = _file.installName;
835 uint32_t size = sizeof(dylib_command) + pointerAlign(path.size() + 1);
836 dc->cmd = LC_ID_DYLIB;
837 dc->cmdsize = size;
838 dc->dylib.name = sizeof(dylib_command); // offset
Jean-Daniel Dupasedefccc2014-12-20 09:22:56 +0000839 // needs to be some constant value different than the one in LC_LOAD_DYLIB
840 dc->dylib.timestamp = 1;
Nick Kledzik5b9e48b2014-11-19 02:21:53 +0000841 dc->dylib.current_version = _file.currentVersion;
842 dc->dylib.compatibility_version = _file.compatVersion;
Tim Northover301c4e62014-07-01 08:15:41 +0000843 if (_swap)
844 swapStruct(*dc);
845 memcpy(lc + sizeof(dylib_command), path.begin(), path.size());
846 lc[sizeof(dylib_command) + path.size()] = '\0';
847 lc += size;
848 }
849
Nick Kledzike34182f2013-11-06 21:36:55 +0000850 // Add LC_DYLD_INFO_ONLY.
851 dyld_info_command* di = reinterpret_cast<dyld_info_command*>(lc);
852 di->cmd = LC_DYLD_INFO_ONLY;
853 di->cmdsize = sizeof(dyld_info_command);
854 di->rebase_off = _rebaseInfo.size() ? _startOfRebaseInfo : 0;
855 di->rebase_size = _rebaseInfo.size();
856 di->bind_off = _bindingInfo.size() ? _startOfBindingInfo : 0;
857 di->bind_size = _bindingInfo.size();
858 di->weak_bind_off = 0;
859 di->weak_bind_size = 0;
860 di->lazy_bind_off = _lazyBindingInfo.size() ? _startOfLazyBindingInfo : 0;
861 di->lazy_bind_size = _lazyBindingInfo.size();
Nick Kledzik141330a2014-09-03 19:52:50 +0000862 di->export_off = _exportTrie.size() ? _startOfExportTrie : 0;
863 di->export_size = _exportTrie.size();
Nick Kledzike34182f2013-11-06 21:36:55 +0000864 if (_swap)
865 swapStruct(*di);
866 lc += sizeof(dyld_info_command);
867
868 // Add LC_SYMTAB with symbol table info.
869 symtab_command* st = reinterpret_cast<symtab_command*>(lc);
870 st->cmd = LC_SYMTAB;
871 st->cmdsize = sizeof(symtab_command);
872 st->symoff = _startOfSymbols;
Lang Hames436f7d62016-07-27 22:55:30 +0000873 st->nsyms = _file.stabsSymbols.size() + _file.localSymbols.size() +
874 _file.globalSymbols.size() + _file.undefinedSymbols.size();
Nick Kledzike34182f2013-11-06 21:36:55 +0000875 st->stroff = _startOfSymbolStrings;
876 st->strsize = _endOfSymbolStrings - _startOfSymbolStrings;
877 if (_swap)
878 swapStruct(*st);
879 lc += sizeof(symtab_command);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000880
Nick Kledzike34182f2013-11-06 21:36:55 +0000881 // Add LC_DYSYMTAB
882 if (_file.fileType != llvm::MachO::MH_PRELOAD) {
883 dysymtab_command* dst = reinterpret_cast<dysymtab_command*>(lc);
884 dst->cmd = LC_DYSYMTAB;
885 dst->cmdsize = sizeof(dysymtab_command);
886 dst->ilocalsym = _symbolTableLocalsStartIndex;
Lang Hames436f7d62016-07-27 22:55:30 +0000887 dst->nlocalsym = _file.stabsSymbols.size() +
888 _file.localSymbols.size();
Nick Kledzike34182f2013-11-06 21:36:55 +0000889 dst->iextdefsym = _symbolTableGlobalsStartIndex;
890 dst->nextdefsym = _file.globalSymbols.size();
891 dst->iundefsym = _symbolTableUndefinesStartIndex;
892 dst->nundefsym = _file.undefinedSymbols.size();
893 dst->tocoff = 0;
894 dst->ntoc = 0;
895 dst->modtaboff = 0;
896 dst->nmodtab = 0;
897 dst->extrefsymoff = 0;
898 dst->nextrefsyms = 0;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000899 dst->indirectsymoff = _startOfIndirectSymbols;
Nick Kledzike34182f2013-11-06 21:36:55 +0000900 dst->nindirectsyms = _indirectSymbolTableCount;
901 dst->extreloff = 0;
902 dst->nextrel = 0;
903 dst->locreloff = 0;
904 dst->nlocrel = 0;
905 if (_swap)
906 swapStruct(*dst);
907 lc += sizeof(dysymtab_command);
908 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000909
Pete Cooper354809e2016-02-03 22:28:29 +0000910 // If main executable, add LC_LOAD_DYLINKER
Nick Kledzike34182f2013-11-06 21:36:55 +0000911 if (_file.fileType == llvm::MachO::MH_EXECUTE) {
912 // Build LC_LOAD_DYLINKER load command.
913 uint32_t size=pointerAlign(sizeof(dylinker_command)+dyldPath().size()+1);
914 dylinker_command* dl = reinterpret_cast<dylinker_command*>(lc);
915 dl->cmd = LC_LOAD_DYLINKER;
916 dl->cmdsize = size;
917 dl->name = sizeof(dylinker_command); // offset
918 if (_swap)
919 swapStruct(*dl);
920 memcpy(lc+sizeof(dylinker_command), dyldPath().data(), dyldPath().size());
921 lc[sizeof(dylinker_command)+dyldPath().size()] = '\0';
922 lc += size;
Pete Cooper354809e2016-02-03 22:28:29 +0000923 }
924
925 // Add LC_VERSION_MIN_MACOSX, LC_VERSION_MIN_IPHONEOS, LC_VERSION_MIN_WATCHOS,
926 // LC_VERSION_MIN_TVOS
Pete Cooperceee5de2016-02-04 02:16:08 +0000927 writeVersionMinLoadCommand(_file, _swap, lc);
Pete Cooper354809e2016-02-03 22:28:29 +0000928
Pete Cooper40576fa2016-02-04 02:45:23 +0000929 // Add LC_SOURCE_VERSION
930 {
Pete Cooperb565bdf2016-03-23 22:00:09 +0000931 // Note, using a temporary here to appease UB as we may not be aligned
932 // enough for a struct containing a uint64_t when emitting a 32-bit binary
933 source_version_command sv;
934 sv.cmd = LC_SOURCE_VERSION;
935 sv.cmdsize = sizeof(source_version_command);
936 sv.version = _file.sourceVersion;
Pete Cooper40576fa2016-02-04 02:45:23 +0000937 if (_swap)
Pete Cooperb565bdf2016-03-23 22:00:09 +0000938 swapStruct(sv);
939 memcpy(lc, &sv, sizeof(source_version_command));
Pete Cooper40576fa2016-02-04 02:45:23 +0000940 lc += sizeof(source_version_command);
941 }
942
Pete Cooper354809e2016-02-03 22:28:29 +0000943 // If main executable, add LC_MAIN.
944 if (_file.fileType == llvm::MachO::MH_EXECUTE) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000945 // Build LC_MAIN load command.
Pete Cooper07601d32016-03-24 01:05:17 +0000946 // Note, using a temporary here to appease UB as we may not be aligned
947 // enough for a struct containing a uint64_t when emitting a 32-bit binary
948 entry_point_command ep;
949 ep.cmd = LC_MAIN;
950 ep.cmdsize = sizeof(entry_point_command);
951 ep.entryoff = _file.entryAddress - _seg1addr;
952 ep.stacksize = _file.stackSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000953 if (_swap)
Pete Cooper07601d32016-03-24 01:05:17 +0000954 swapStruct(ep);
955 memcpy(lc, &ep, sizeof(entry_point_command));
Nick Kledzike34182f2013-11-06 21:36:55 +0000956 lc += sizeof(entry_point_command);
957 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000958
Nick Kledzike34182f2013-11-06 21:36:55 +0000959 // Add LC_LOAD_DYLIB commands
960 for (const DependentDylib &dep : _file.dependentDylibs) {
961 dylib_command* dc = reinterpret_cast<dylib_command*>(lc);
962 uint32_t size = sizeof(dylib_command) + pointerAlign(dep.path.size()+1);
Nick Kledzik51720672014-10-16 19:31:28 +0000963 dc->cmd = dep.kind;
Nick Kledzike34182f2013-11-06 21:36:55 +0000964 dc->cmdsize = size;
965 dc->dylib.name = sizeof(dylib_command); // offset
Jean-Daniel Dupasedefccc2014-12-20 09:22:56 +0000966 // needs to be some constant value different than the one in LC_ID_DYLIB
Nick Kledzik5b9e48b2014-11-19 02:21:53 +0000967 dc->dylib.timestamp = 2;
968 dc->dylib.current_version = dep.currentVersion;
969 dc->dylib.compatibility_version = dep.compatVersion;
Nick Kledzike34182f2013-11-06 21:36:55 +0000970 if (_swap)
971 swapStruct(*dc);
972 memcpy(lc+sizeof(dylib_command), dep.path.begin(), dep.path.size());
973 lc[sizeof(dylib_command)+dep.path.size()] = '\0';
974 lc += size;
975 }
Jean-Daniel Dupas23dd15e2014-12-18 21:33:38 +0000976
977 // Add LC_RPATH
978 for (const StringRef &path : _file.rpaths) {
979 rpath_command *rpc = reinterpret_cast<rpath_command *>(lc);
Lang Hames2ed3bf92015-10-29 16:50:26 +0000980 uint32_t size = pointerAlign(sizeof(rpath_command) + path.size() + 1);
Jean-Daniel Dupas23dd15e2014-12-18 21:33:38 +0000981 rpc->cmd = LC_RPATH;
982 rpc->cmdsize = size;
983 rpc->path = sizeof(rpath_command); // offset
984 if (_swap)
985 swapStruct(*rpc);
986 memcpy(lc+sizeof(rpath_command), path.begin(), path.size());
987 lc[sizeof(rpath_command)+path.size()] = '\0';
988 lc += size;
989 }
990
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000991 // Add LC_FUNCTION_STARTS if needed.
992 if (_functionStartsSize != 0) {
993 linkedit_data_command* dl = reinterpret_cast<linkedit_data_command*>(lc);
994 dl->cmd = LC_FUNCTION_STARTS;
995 dl->cmdsize = sizeof(linkedit_data_command);
996 dl->dataoff = _startOfFunctionStarts;
997 dl->datasize = _functionStartsSize;
998 if (_swap)
999 swapStruct(*dl);
1000 lc += sizeof(linkedit_data_command);
1001 }
1002
Pete Cooper9b28a452016-02-09 02:10:39 +00001003 // Add LC_DATA_IN_CODE if requested.
1004 if (_file.generateDataInCodeLoadCommand) {
Nick Kledzik54ce29582014-10-28 22:21:10 +00001005 linkedit_data_command* dl = reinterpret_cast<linkedit_data_command*>(lc);
1006 dl->cmd = LC_DATA_IN_CODE;
1007 dl->cmdsize = sizeof(linkedit_data_command);
1008 dl->dataoff = _startOfDataInCode;
1009 dl->datasize = _dataInCodeSize;
1010 if (_swap)
1011 swapStruct(*dl);
1012 lc += sizeof(linkedit_data_command);
1013 }
Nick Kledzike34182f2013-11-06 21:36:55 +00001014 }
Pete Cooper514594b2016-03-31 00:08:16 +00001015 return llvm::Error();
Nick Kledzike34182f2013-11-06 21:36:55 +00001016}
1017
Nick Kledzike34182f2013-11-06 21:36:55 +00001018void MachOFileLayout::writeSectionContent() {
1019 for (const Section &s : _file.sections) {
1020 // Copy all section content to output buffer.
Lang Hamesac2adce2015-12-11 23:25:09 +00001021 if (isZeroFillSection(s.type))
Nick Kledzik61fdef62014-05-15 20:59:23 +00001022 continue;
Nick Kledzik1bebb282014-09-09 23:52:59 +00001023 if (s.content.empty())
1024 continue;
Nick Kledzike34182f2013-11-06 21:36:55 +00001025 uint32_t offset = _sectInfo[&s].fileOffset;
1026 uint8_t *p = &_buffer[offset];
1027 memcpy(p, &s.content[0], s.content.size());
1028 p += s.content.size();
1029 }
1030}
1031
1032void MachOFileLayout::writeRelocations() {
1033 uint32_t relOffset = _startOfRelocations;
1034 for (Section sect : _file.sections) {
1035 for (Relocation r : sect.relocations) {
1036 any_relocation_info* rb = reinterpret_cast<any_relocation_info*>(
1037 &_buffer[relOffset]);
1038 *rb = packRelocation(r, _swap, _bigEndianArch);
1039 relOffset += sizeof(any_relocation_info);
1040 }
1041 }
1042}
1043
Nick Kledzike34182f2013-11-06 21:36:55 +00001044void MachOFileLayout::appendSymbols(const std::vector<Symbol> &symbols,
1045 uint32_t &symOffset, uint32_t &strOffset) {
1046 for (const Symbol &sym : symbols) {
1047 if (_is64) {
1048 nlist_64* nb = reinterpret_cast<nlist_64*>(&_buffer[symOffset]);
1049 nb->n_strx = strOffset - _startOfSymbolStrings;
1050 nb->n_type = sym.type | sym.scope;
1051 nb->n_sect = sym.sect;
1052 nb->n_desc = sym.desc;
1053 nb->n_value = sym.value;
1054 if (_swap)
1055 swapStruct(*nb);
1056 symOffset += sizeof(nlist_64);
1057 } else {
1058 nlist* nb = reinterpret_cast<nlist*>(&_buffer[symOffset]);
1059 nb->n_strx = strOffset - _startOfSymbolStrings;
1060 nb->n_type = sym.type | sym.scope;
1061 nb->n_sect = sym.sect;
1062 nb->n_desc = sym.desc;
1063 nb->n_value = sym.value;
1064 if (_swap)
1065 swapStruct(*nb);
1066 symOffset += sizeof(nlist);
1067 }
1068 memcpy(&_buffer[strOffset], sym.name.begin(), sym.name.size());
1069 strOffset += sym.name.size();
1070 _buffer[strOffset++] ='\0'; // Strings in table have nul terminator.
1071 }
1072}
1073
Pete Cooper41f3e8e2016-02-09 01:38:13 +00001074void MachOFileLayout::writeFunctionStartsInfo() {
Pete Cooper8e1b9a12016-03-22 22:51:03 +00001075 if (!_functionStartsSize)
1076 return;
Pete Cooper41f3e8e2016-02-09 01:38:13 +00001077 memcpy(&_buffer[_startOfFunctionStarts], _file.functionStarts.data(),
1078 _functionStartsSize);
1079}
1080
Nick Kledzik21921372014-07-24 23:06:56 +00001081void MachOFileLayout::writeDataInCodeInfo() {
1082 uint32_t offset = _startOfDataInCode;
1083 for (const DataInCode &entry : _file.dataInCode) {
1084 data_in_code_entry *dst = reinterpret_cast<data_in_code_entry*>(
1085 &_buffer[offset]);
1086 dst->offset = entry.offset;
1087 dst->length = entry.length;
1088 dst->kind = entry.kind;
1089 if (_swap)
1090 swapStruct(*dst);
1091 offset += sizeof(data_in_code_entry);
1092 }
1093}
1094
Nick Kledzike34182f2013-11-06 21:36:55 +00001095void MachOFileLayout::writeSymbolTable() {
1096 // Write symbol table and symbol strings in parallel.
1097 uint32_t symOffset = _startOfSymbols;
1098 uint32_t strOffset = _startOfSymbolStrings;
Pete Cooper5559b242016-08-08 23:20:04 +00001099 // Reserve n_strx offset of zero to mean no name.
1100 _buffer[strOffset++] = ' ';
1101 _buffer[strOffset++] = '\0';
Lang Hames436f7d62016-07-27 22:55:30 +00001102 appendSymbols(_file.stabsSymbols, symOffset, strOffset);
Nick Kledzike34182f2013-11-06 21:36:55 +00001103 appendSymbols(_file.localSymbols, symOffset, strOffset);
1104 appendSymbols(_file.globalSymbols, symOffset, strOffset);
1105 appendSymbols(_file.undefinedSymbols, symOffset, strOffset);
1106 // Write indirect symbol table array.
1107 uint32_t *indirects = reinterpret_cast<uint32_t*>
1108 (&_buffer[_startOfIndirectSymbols]);
1109 if (_file.fileType == llvm::MachO::MH_OBJECT) {
1110 // Object files have sections in same order as input normalized file.
1111 for (const Section &section : _file.sections) {
1112 for (uint32_t index : section.indirectSymbols) {
1113 if (_swap)
Artyom Skrobov17587fb2014-06-14 12:40:04 +00001114 *indirects++ = llvm::sys::getSwappedBytes(index);
Nick Kledzike34182f2013-11-06 21:36:55 +00001115 else
1116 *indirects++ = index;
1117 }
1118 }
1119 } else {
1120 // Final linked images must sort sections from normalized file.
1121 for (const Segment &seg : _file.segments) {
1122 SegExtraInfo &segInfo = _segInfo[&seg];
1123 for (const Section *section : segInfo.sections) {
1124 for (uint32_t index : section->indirectSymbols) {
1125 if (_swap)
Artyom Skrobov17587fb2014-06-14 12:40:04 +00001126 *indirects++ = llvm::sys::getSwappedBytes(index);
Nick Kledzike34182f2013-11-06 21:36:55 +00001127 else
1128 *indirects++ = index;
1129 }
1130 }
1131 }
1132 }
1133}
1134
1135void MachOFileLayout::writeRebaseInfo() {
1136 memcpy(&_buffer[_startOfRebaseInfo], _rebaseInfo.bytes(), _rebaseInfo.size());
1137}
1138
1139void MachOFileLayout::writeBindingInfo() {
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001140 memcpy(&_buffer[_startOfBindingInfo],
Nick Kledzike34182f2013-11-06 21:36:55 +00001141 _bindingInfo.bytes(), _bindingInfo.size());
1142}
1143
1144void MachOFileLayout::writeLazyBindingInfo() {
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001145 memcpy(&_buffer[_startOfLazyBindingInfo],
Nick Kledzike34182f2013-11-06 21:36:55 +00001146 _lazyBindingInfo.bytes(), _lazyBindingInfo.size());
1147}
1148
Nick Kledzik141330a2014-09-03 19:52:50 +00001149void MachOFileLayout::writeExportInfo() {
1150 memcpy(&_buffer[_startOfExportTrie], _exportTrie.bytes(), _exportTrie.size());
1151}
1152
Nick Kledzike34182f2013-11-06 21:36:55 +00001153void MachOFileLayout::buildLinkEditInfo() {
1154 buildRebaseInfo();
1155 buildBindInfo();
1156 buildLazyBindInfo();
Nick Kledzik141330a2014-09-03 19:52:50 +00001157 buildExportTrie();
Nick Kledzike34182f2013-11-06 21:36:55 +00001158 computeSymbolTableSizes();
Pete Cooper41f3e8e2016-02-09 01:38:13 +00001159 computeFunctionStartsSize();
Nick Kledzik21921372014-07-24 23:06:56 +00001160 computeDataInCodeSize();
Nick Kledzike34182f2013-11-06 21:36:55 +00001161}
1162
1163void MachOFileLayout::buildSectionRelocations() {
1164
1165}
1166
1167void MachOFileLayout::buildRebaseInfo() {
1168 // TODO: compress rebasing info.
1169 for (const RebaseLocation& entry : _file.rebasingInfo) {
1170 _rebaseInfo.append_byte(REBASE_OPCODE_SET_TYPE_IMM | entry.kind);
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001171 _rebaseInfo.append_byte(REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
Nick Kledzike34182f2013-11-06 21:36:55 +00001172 | entry.segIndex);
1173 _rebaseInfo.append_uleb128(entry.segOffset);
1174 _rebaseInfo.append_uleb128(REBASE_OPCODE_DO_REBASE_IMM_TIMES | 1);
1175 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001176 _rebaseInfo.append_byte(REBASE_OPCODE_DONE);
Nick Kledzike34182f2013-11-06 21:36:55 +00001177 _rebaseInfo.align(_is64 ? 8 : 4);
1178}
1179
1180void MachOFileLayout::buildBindInfo() {
1181 // TODO: compress bind info.
Nick Kledzikf373c772014-11-11 01:31:18 +00001182 uint64_t lastAddend = 0;
Pete Cooper21f475e2016-08-11 20:37:02 +00001183 int lastOrdinal = 0x80000000;
1184 StringRef lastSymbolName;
1185 BindType lastType = (BindType)0;
1186 Hex32 lastSegOffset = ~0U;
1187 uint8_t lastSegIndex = (uint8_t)~0U;
Nick Kledzike34182f2013-11-06 21:36:55 +00001188 for (const BindLocation& entry : _file.bindingInfo) {
Pete Cooper21f475e2016-08-11 20:37:02 +00001189 if (entry.ordinal != lastOrdinal) {
1190 if (entry.ordinal <= 0)
1191 _bindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_SPECIAL_IMM |
1192 (entry.ordinal & BIND_IMMEDIATE_MASK));
1193 else if (entry.ordinal <= BIND_IMMEDIATE_MASK)
1194 _bindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM |
1195 entry.ordinal);
1196 else {
1197 _bindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB);
1198 _bindingInfo.append_uleb128(entry.ordinal);
1199 }
1200 lastOrdinal = entry.ordinal;
1201 }
1202
1203 if (lastSymbolName != entry.symbolName) {
1204 _bindingInfo.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM);
1205 _bindingInfo.append_string(entry.symbolName);
1206 lastSymbolName = entry.symbolName;
1207 }
1208
1209 if (lastType != entry.kind) {
1210 _bindingInfo.append_byte(BIND_OPCODE_SET_TYPE_IMM | entry.kind);
1211 lastType = entry.kind;
1212 }
1213
1214 if (lastSegIndex != entry.segIndex || lastSegOffset != entry.segOffset) {
1215 _bindingInfo.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
1216 | entry.segIndex);
1217 _bindingInfo.append_uleb128(entry.segOffset);
1218 lastSegIndex = entry.segIndex;
1219 lastSegOffset = entry.segOffset;
1220 }
Nick Kledzikf373c772014-11-11 01:31:18 +00001221 if (entry.addend != lastAddend) {
Nick Kledzike34182f2013-11-06 21:36:55 +00001222 _bindingInfo.append_byte(BIND_OPCODE_SET_ADDEND_SLEB);
1223 _bindingInfo.append_sleb128(entry.addend);
Nick Kledzikf373c772014-11-11 01:31:18 +00001224 lastAddend = entry.addend;
Nick Kledzike34182f2013-11-06 21:36:55 +00001225 }
1226 _bindingInfo.append_byte(BIND_OPCODE_DO_BIND);
1227 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001228 _bindingInfo.append_byte(BIND_OPCODE_DONE);
Nick Kledzike34182f2013-11-06 21:36:55 +00001229 _bindingInfo.align(_is64 ? 8 : 4);
1230}
1231
1232void MachOFileLayout::buildLazyBindInfo() {
1233 for (const BindLocation& entry : _file.lazyBindingInfo) {
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001234 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
Nick Kledzike34182f2013-11-06 21:36:55 +00001235 | entry.segIndex);
Pete Cooper1ed8f1f2016-08-11 20:59:27 +00001236 _lazyBindingInfo.append_uleb128(entry.segOffset);
1237 if (entry.ordinal <= 0)
Lang Hames5c692002015-09-28 20:25:14 +00001238 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_SPECIAL_IMM |
Pete Cooper1ed8f1f2016-08-11 20:59:27 +00001239 (entry.ordinal & BIND_IMMEDIATE_MASK));
1240 else if (entry.ordinal <= BIND_IMMEDIATE_MASK)
1241 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM |
1242 entry.ordinal);
1243 else {
1244 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB);
1245 _lazyBindingInfo.append_uleb128(entry.ordinal);
1246 }
1247 // FIXME: We need to | the opcode here with flags.
Nick Kledzike34182f2013-11-06 21:36:55 +00001248 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM);
1249 _lazyBindingInfo.append_string(entry.symbolName);
1250 _lazyBindingInfo.append_byte(BIND_OPCODE_DO_BIND);
Nick Kledzikf373c772014-11-11 01:31:18 +00001251 _lazyBindingInfo.append_byte(BIND_OPCODE_DONE);
Nick Kledzike34182f2013-11-06 21:36:55 +00001252 }
Nick Kledzike34182f2013-11-06 21:36:55 +00001253 _lazyBindingInfo.align(_is64 ? 8 : 4);
1254}
1255
Pete Coopere420dd42016-01-25 21:50:54 +00001256void TrieNode::addSymbol(const Export& entry,
1257 BumpPtrAllocator &allocator,
1258 std::vector<TrieNode*> &allNodes) {
Nick Kledzik141330a2014-09-03 19:52:50 +00001259 StringRef partialStr = entry.name.drop_front(_cummulativeString.size());
1260 for (TrieEdge &edge : _children) {
1261 StringRef edgeStr = edge._subString;
1262 if (partialStr.startswith(edgeStr)) {
1263 // Already have matching edge, go down that path.
1264 edge._child->addSymbol(entry, allocator, allNodes);
1265 return;
1266 }
1267 // See if string has commmon prefix with existing edge.
1268 for (int n=edgeStr.size()-1; n > 0; --n) {
1269 if (partialStr.substr(0, n).equals(edgeStr.substr(0, n))) {
1270 // Splice in new node: was A -> C, now A -> B -> C
1271 StringRef bNodeStr = edge._child->_cummulativeString;
1272 bNodeStr = bNodeStr.drop_back(edgeStr.size()-n).copy(allocator);
Eugene Zelenko41547942015-11-10 22:37:38 +00001273 auto *bNode = new (allocator) TrieNode(bNodeStr);
Nick Kledzik141330a2014-09-03 19:52:50 +00001274 allNodes.push_back(bNode);
1275 TrieNode* cNode = edge._child;
1276 StringRef abEdgeStr = edgeStr.substr(0,n).copy(allocator);
1277 StringRef bcEdgeStr = edgeStr.substr(n).copy(allocator);
1278 DEBUG_WITH_TYPE("trie-builder", llvm::dbgs()
1279 << "splice in TrieNode('" << bNodeStr
1280 << "') between edge '"
1281 << abEdgeStr << "' and edge='"
1282 << bcEdgeStr<< "'\n");
1283 TrieEdge& abEdge = edge;
1284 abEdge._subString = abEdgeStr;
1285 abEdge._child = bNode;
Eugene Zelenko41547942015-11-10 22:37:38 +00001286 auto *bcEdge = new (allocator) TrieEdge(bcEdgeStr, cNode);
Pete Coopere420dd42016-01-25 21:50:54 +00001287 bNode->_children.insert(bNode->_children.end(), bcEdge);
Nick Kledzik141330a2014-09-03 19:52:50 +00001288 bNode->addSymbol(entry, allocator, allNodes);
1289 return;
1290 }
1291 }
1292 }
1293 if (entry.flags & EXPORT_SYMBOL_FLAGS_REEXPORT) {
1294 assert(entry.otherOffset != 0);
1295 }
1296 if (entry.flags & EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER) {
1297 assert(entry.otherOffset != 0);
1298 }
1299 // No commonality with any existing child, make a new edge.
Eugene Zelenko41547942015-11-10 22:37:38 +00001300 auto *newNode = new (allocator) TrieNode(entry.name.copy(allocator));
1301 auto *newEdge = new (allocator) TrieEdge(partialStr, newNode);
Pete Coopere420dd42016-01-25 21:50:54 +00001302 _children.insert(_children.end(), newEdge);
Nick Kledzik141330a2014-09-03 19:52:50 +00001303 DEBUG_WITH_TYPE("trie-builder", llvm::dbgs()
1304 << "new TrieNode('" << entry.name << "') with edge '"
1305 << partialStr << "' from node='"
1306 << _cummulativeString << "'\n");
1307 newNode->_address = entry.offset;
1308 newNode->_flags = entry.flags | entry.kind;
1309 newNode->_other = entry.otherOffset;
1310 if ((entry.flags & EXPORT_SYMBOL_FLAGS_REEXPORT) && !entry.otherName.empty())
1311 newNode->_importedName = entry.otherName.copy(allocator);
1312 newNode->_hasExportInfo = true;
1313 allNodes.push_back(newNode);
1314}
1315
Pete Cooperd0de3682016-08-05 21:37:12 +00001316void TrieNode::addOrderedNodes(const Export& entry,
1317 std::vector<TrieNode*> &orderedNodes) {
1318 if (!_ordered) {
1319 orderedNodes.push_back(this);
1320 _ordered = true;
1321 }
1322
1323 StringRef partialStr = entry.name.drop_front(_cummulativeString.size());
1324 for (TrieEdge &edge : _children) {
1325 StringRef edgeStr = edge._subString;
1326 if (partialStr.startswith(edgeStr)) {
1327 // Already have matching edge, go down that path.
1328 edge._child->addOrderedNodes(entry, orderedNodes);
1329 return;
1330 }
1331 }
1332}
1333
Pete Coopere420dd42016-01-25 21:50:54 +00001334bool TrieNode::updateOffset(uint32_t& offset) {
Nick Kledzik141330a2014-09-03 19:52:50 +00001335 uint32_t nodeSize = 1; // Length when no export info
1336 if (_hasExportInfo) {
1337 if (_flags & EXPORT_SYMBOL_FLAGS_REEXPORT) {
1338 nodeSize = llvm::getULEB128Size(_flags);
1339 nodeSize += llvm::getULEB128Size(_other); // Other contains ordinal.
1340 nodeSize += _importedName.size();
1341 ++nodeSize; // Trailing zero in imported name.
1342 } else {
1343 nodeSize = llvm::getULEB128Size(_flags) + llvm::getULEB128Size(_address);
1344 if (_flags & EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1345 nodeSize += llvm::getULEB128Size(_other);
1346 }
1347 // Overall node size so far is uleb128 of export info + actual export info.
1348 nodeSize += llvm::getULEB128Size(nodeSize);
1349 }
1350 // Compute size of all child edges.
1351 ++nodeSize; // Byte for number of chidren.
1352 for (TrieEdge &edge : _children) {
1353 nodeSize += edge._subString.size() + 1 // String length.
1354 + llvm::getULEB128Size(edge._child->_trieOffset); // Offset len.
1355 }
1356 // On input, 'offset' is new prefered location for this node.
1357 bool result = (_trieOffset != offset);
1358 // Store new location in node object for use by parents.
1359 _trieOffset = offset;
1360 // Update offset for next iteration.
1361 offset += nodeSize;
1362 // Return true if _trieOffset was changed.
1363 return result;
1364}
1365
Pete Coopere420dd42016-01-25 21:50:54 +00001366void TrieNode::appendToByteBuffer(ByteBuffer &out) {
Nick Kledzik141330a2014-09-03 19:52:50 +00001367 if (_hasExportInfo) {
1368 if (_flags & EXPORT_SYMBOL_FLAGS_REEXPORT) {
1369 if (!_importedName.empty()) {
1370 // nodes with re-export info: size, flags, ordinal, import-name
1371 uint32_t nodeSize = llvm::getULEB128Size(_flags)
1372 + llvm::getULEB128Size(_other)
1373 + _importedName.size() + 1;
1374 assert(nodeSize < 256);
1375 out.append_byte(nodeSize);
1376 out.append_uleb128(_flags);
1377 out.append_uleb128(_other);
1378 out.append_string(_importedName);
1379 } else {
1380 // nodes without re-export info: size, flags, ordinal, empty-string
1381 uint32_t nodeSize = llvm::getULEB128Size(_flags)
1382 + llvm::getULEB128Size(_other) + 1;
1383 assert(nodeSize < 256);
1384 out.append_byte(nodeSize);
1385 out.append_uleb128(_flags);
1386 out.append_uleb128(_other);
1387 out.append_byte(0);
1388 }
1389 } else if ( _flags & EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER ) {
1390 // Nodes with export info: size, flags, address, other
1391 uint32_t nodeSize = llvm::getULEB128Size(_flags)
1392 + llvm::getULEB128Size(_address)
1393 + llvm::getULEB128Size(_other);
1394 assert(nodeSize < 256);
1395 out.append_byte(nodeSize);
1396 out.append_uleb128(_flags);
1397 out.append_uleb128(_address);
1398 out.append_uleb128(_other);
1399 } else {
1400 // Nodes with export info: size, flags, address
1401 uint32_t nodeSize = llvm::getULEB128Size(_flags)
1402 + llvm::getULEB128Size(_address);
1403 assert(nodeSize < 256);
1404 out.append_byte(nodeSize);
1405 out.append_uleb128(_flags);
1406 out.append_uleb128(_address);
1407 }
1408 } else {
1409 // Node with no export info.
1410 uint32_t nodeSize = 0;
1411 out.append_byte(nodeSize);
1412 }
1413 // Add number of children.
1414 assert(_children.size() < 256);
1415 out.append_byte(_children.size());
1416 // Append each child edge substring and node offset.
1417 for (TrieEdge &edge : _children) {
1418 out.append_string(edge._subString);
1419 out.append_uleb128(edge._child->_trieOffset);
1420 }
1421}
1422
1423void MachOFileLayout::buildExportTrie() {
1424 if (_file.exportInfo.empty())
1425 return;
1426
1427 // For all temporary strings and objects used building trie.
1428 BumpPtrAllocator allocator;
1429
1430 // Build trie of all exported symbols.
Eugene Zelenko41547942015-11-10 22:37:38 +00001431 auto *rootNode = new (allocator) TrieNode(StringRef());
Nick Kledzik141330a2014-09-03 19:52:50 +00001432 std::vector<TrieNode*> allNodes;
1433 allNodes.reserve(_file.exportInfo.size()*2);
1434 allNodes.push_back(rootNode);
1435 for (const Export& entry : _file.exportInfo) {
1436 rootNode->addSymbol(entry, allocator, allNodes);
1437 }
1438
Pete Cooperd0de3682016-08-05 21:37:12 +00001439 std::vector<TrieNode*> orderedNodes;
1440 orderedNodes.reserve(allNodes.size());
1441
1442 for (const Export& entry : _file.exportInfo)
1443 rootNode->addOrderedNodes(entry, orderedNodes);
1444
Nick Kledzik141330a2014-09-03 19:52:50 +00001445 // Assign each node in the vector an offset in the trie stream, iterating
1446 // until all uleb128 sizes have stabilized.
1447 bool more;
1448 do {
1449 uint32_t offset = 0;
1450 more = false;
Pete Cooperd0de3682016-08-05 21:37:12 +00001451 for (TrieNode* node : orderedNodes) {
Nick Kledzik141330a2014-09-03 19:52:50 +00001452 if (node->updateOffset(offset))
1453 more = true;
1454 }
1455 } while (more);
1456
1457 // Serialize trie to ByteBuffer.
Pete Cooperd0de3682016-08-05 21:37:12 +00001458 for (TrieNode* node : orderedNodes) {
Nick Kledzik141330a2014-09-03 19:52:50 +00001459 node->appendToByteBuffer(_exportTrie);
1460 }
1461 _exportTrie.align(_is64 ? 8 : 4);
1462}
1463
Nick Kledzike34182f2013-11-06 21:36:55 +00001464void MachOFileLayout::computeSymbolTableSizes() {
1465 // MachO symbol tables have three ranges: locals, globals, and undefines
1466 const size_t nlistSize = (_is64 ? sizeof(nlist_64) : sizeof(nlist));
Lang Hames436f7d62016-07-27 22:55:30 +00001467 _symbolTableSize = nlistSize * (_file.stabsSymbols.size()
1468 + _file.localSymbols.size()
Nick Kledzike34182f2013-11-06 21:36:55 +00001469 + _file.globalSymbols.size()
1470 + _file.undefinedSymbols.size());
Pete Cooper5559b242016-08-08 23:20:04 +00001471 // Always reserve 1-byte for the empty string and 1-byte for its terminator.
1472 _symbolStringPoolSize = 2;
Lang Hames436f7d62016-07-27 22:55:30 +00001473 for (const Symbol &sym : _file.stabsSymbols) {
1474 _symbolStringPoolSize += (sym.name.size()+1);
1475 }
Nick Kledzike34182f2013-11-06 21:36:55 +00001476 for (const Symbol &sym : _file.localSymbols) {
1477 _symbolStringPoolSize += (sym.name.size()+1);
1478 }
1479 for (const Symbol &sym : _file.globalSymbols) {
1480 _symbolStringPoolSize += (sym.name.size()+1);
1481 }
1482 for (const Symbol &sym : _file.undefinedSymbols) {
1483 _symbolStringPoolSize += (sym.name.size()+1);
1484 }
1485 _symbolTableLocalsStartIndex = 0;
Lang Hames436f7d62016-07-27 22:55:30 +00001486 _symbolTableGlobalsStartIndex = _file.stabsSymbols.size() +
1487 _file.localSymbols.size();
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001488 _symbolTableUndefinesStartIndex = _symbolTableGlobalsStartIndex
Nick Kledzike34182f2013-11-06 21:36:55 +00001489 + _file.globalSymbols.size();
1490
1491 _indirectSymbolTableCount = 0;
1492 for (const Section &sect : _file.sections) {
1493 _indirectSymbolTableCount += sect.indirectSymbols.size();
1494 }
1495}
1496
Pete Cooper41f3e8e2016-02-09 01:38:13 +00001497void MachOFileLayout::computeFunctionStartsSize() {
1498 _functionStartsSize = _file.functionStarts.size();
1499}
1500
Nick Kledzik21921372014-07-24 23:06:56 +00001501void MachOFileLayout::computeDataInCodeSize() {
1502 _dataInCodeSize = _file.dataInCode.size() * sizeof(data_in_code_entry);
1503}
Nick Kledzike34182f2013-11-06 21:36:55 +00001504
1505void MachOFileLayout::writeLinkEditContent() {
1506 if (_file.fileType == llvm::MachO::MH_OBJECT) {
1507 writeRelocations();
Pete Cooper41f3e8e2016-02-09 01:38:13 +00001508 writeFunctionStartsInfo();
Nick Kledzik21921372014-07-24 23:06:56 +00001509 writeDataInCodeInfo();
Nick Kledzike34182f2013-11-06 21:36:55 +00001510 writeSymbolTable();
1511 } else {
1512 writeRebaseInfo();
1513 writeBindingInfo();
1514 writeLazyBindingInfo();
1515 // TODO: add weak binding info
Nick Kledzik141330a2014-09-03 19:52:50 +00001516 writeExportInfo();
Pete Cooper41f3e8e2016-02-09 01:38:13 +00001517 writeFunctionStartsInfo();
Nick Kledzik54ce29582014-10-28 22:21:10 +00001518 writeDataInCodeInfo();
Nick Kledzike34182f2013-11-06 21:36:55 +00001519 writeSymbolTable();
1520 }
1521}
1522
Pete Cooperfefbd222016-03-30 23:10:39 +00001523llvm::Error MachOFileLayout::writeBinary(StringRef path) {
Nick Kledzike34182f2013-11-06 21:36:55 +00001524 // Check for pending error from constructor.
1525 if (_ec)
Pete Cooperfefbd222016-03-30 23:10:39 +00001526 return llvm::errorCodeToError(_ec);
Nick Kledzike34182f2013-11-06 21:36:55 +00001527 // Create FileOutputBuffer with calculated size.
Nick Kledzike34182f2013-11-06 21:36:55 +00001528 unsigned flags = 0;
1529 if (_file.fileType != llvm::MachO::MH_OBJECT)
1530 flags = llvm::FileOutputBuffer::F_executable;
Rafael Espindolabdc8f2f2015-08-13 00:31:46 +00001531 ErrorOr<std::unique_ptr<llvm::FileOutputBuffer>> fobOrErr =
1532 llvm::FileOutputBuffer::create(path, size(), flags);
1533 if (std::error_code ec = fobOrErr.getError())
Pete Cooperfefbd222016-03-30 23:10:39 +00001534 return llvm::errorCodeToError(ec);
Rafael Espindolabdc8f2f2015-08-13 00:31:46 +00001535 std::unique_ptr<llvm::FileOutputBuffer> &fob = *fobOrErr;
Nick Kledzike34182f2013-11-06 21:36:55 +00001536 // Write content.
1537 _buffer = fob->getBufferStart();
1538 writeMachHeader();
Pete Cooper514594b2016-03-31 00:08:16 +00001539 if (auto ec = writeLoadCommands())
Pete Cooperdc59c792016-03-31 00:38:02 +00001540 return ec;
Nick Kledzike34182f2013-11-06 21:36:55 +00001541 writeSectionContent();
1542 writeLinkEditContent();
1543 fob->commit();
1544
Pete Cooperfefbd222016-03-30 23:10:39 +00001545 return llvm::Error();
Nick Kledzike34182f2013-11-06 21:36:55 +00001546}
1547
Nick Kledzike34182f2013-11-06 21:36:55 +00001548/// Takes in-memory normalized view and writes a mach-o object file.
Pete Cooperfefbd222016-03-30 23:10:39 +00001549llvm::Error writeBinary(const NormalizedFile &file, StringRef path) {
Nick Kledzike34182f2013-11-06 21:36:55 +00001550 MachOFileLayout layout(file);
1551 return layout.writeBinary(path);
1552}
1553
Nick Kledzike34182f2013-11-06 21:36:55 +00001554} // namespace normalized
1555} // namespace mach_o
1556} // namespace lld