blob: 5716556268c90cda572fdbb437a98b7b22d6001f [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_sentinel_traits<TrieEdge>
72 : public ilist_half_embedded_sentinel_traits<TrieEdge> {};
Pete Coopere420dd42016-01-25 21:50:54 +000073
Duncan P. N. Exon Smith623c4c12016-08-12 16:25:04 +000074 template <>
75 struct ilist_traits<TrieEdge> : public ilist_default_traits<TrieEdge> {
Pete Coopere420dd42016-01-25 21:50:54 +000076 void deleteNode(TrieEdge *N) {}
77
78 private:
79 void createNode(const TrieEdge &);
80 };
81} // namespace llvm
82
83
84namespace lld {
85namespace mach_o {
86namespace normalized {
87
88struct TrieNode {
89 typedef llvm::ilist<TrieEdge> TrieEdgeList;
90
91 TrieNode(StringRef s)
92 : _cummulativeString(s), _address(0), _flags(0), _other(0),
93 _trieOffset(0), _hasExportInfo(false) {}
94 ~TrieNode() = default;
95
96 void addSymbol(const Export &entry, BumpPtrAllocator &allocator,
97 std::vector<TrieNode *> &allNodes);
Pete Cooperd0de3682016-08-05 21:37:12 +000098
99 void addOrderedNodes(const Export &entry,
100 std::vector<TrieNode *> &allNodes);
Pete Coopere420dd42016-01-25 21:50:54 +0000101 bool updateOffset(uint32_t &offset);
102 void appendToByteBuffer(ByteBuffer &out);
103
104private:
105 StringRef _cummulativeString;
106 TrieEdgeList _children;
107 uint64_t _address;
108 uint64_t _flags;
109 uint64_t _other;
110 StringRef _importedName;
111 uint32_t _trieOffset;
112 bool _hasExportInfo;
Pete Cooperd0de3682016-08-05 21:37:12 +0000113 bool _ordered = false;
Pete Coopere420dd42016-01-25 21:50:54 +0000114};
115
Nick Kledzike34182f2013-11-06 21:36:55 +0000116/// Utility class for writing a mach-o binary file given an in-memory
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000117/// normalized file.
Nick Kledzike34182f2013-11-06 21:36:55 +0000118class MachOFileLayout {
119public:
Joey Goulyb275d7f2013-12-23 23:29:50 +0000120 /// All layout computation is done in the constructor.
121 MachOFileLayout(const NormalizedFile &file);
122
Nick Kledzike34182f2013-11-06 21:36:55 +0000123 /// Returns the final file size as computed in the constructor.
124 size_t size() const;
125
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000126 // Returns size of the mach_header and load commands.
127 size_t headerAndLoadCommandsSize() const;
128
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000129 /// Writes the normalized file as a binary mach-o file to the specified
Nick Kledzike34182f2013-11-06 21:36:55 +0000130 /// path. This does not have a stream interface because the generated
131 /// file may need the 'x' bit set.
Pete Cooperfefbd222016-03-30 23:10:39 +0000132 llvm::Error writeBinary(StringRef path);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000133
Nick Kledzike34182f2013-11-06 21:36:55 +0000134private:
135 uint32_t loadCommandsSize(uint32_t &count);
136 void buildFileOffsets();
137 void writeMachHeader();
Pete Cooper514594b2016-03-31 00:08:16 +0000138 llvm::Error writeLoadCommands();
Nick Kledzike34182f2013-11-06 21:36:55 +0000139 void writeSectionContent();
140 void writeRelocations();
141 void writeSymbolTable();
142 void writeRebaseInfo();
143 void writeBindingInfo();
144 void writeLazyBindingInfo();
Nick Kledzik141330a2014-09-03 19:52:50 +0000145 void writeExportInfo();
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000146 void writeFunctionStartsInfo();
Nick Kledzik21921372014-07-24 23:06:56 +0000147 void writeDataInCodeInfo();
Nick Kledzike34182f2013-11-06 21:36:55 +0000148 void writeLinkEditContent();
149 void buildLinkEditInfo();
150 void buildRebaseInfo();
151 void buildBindInfo();
152 void buildLazyBindInfo();
Nick Kledzik141330a2014-09-03 19:52:50 +0000153 void buildExportTrie();
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000154 void computeFunctionStartsSize();
Nick Kledzik21921372014-07-24 23:06:56 +0000155 void computeDataInCodeSize();
Nick Kledzike34182f2013-11-06 21:36:55 +0000156 void computeSymbolTableSizes();
157 void buildSectionRelocations();
158 void appendSymbols(const std::vector<Symbol> &symbols,
159 uint32_t &symOffset, uint32_t &strOffset);
160 uint32_t indirectSymbolIndex(const Section &sect, uint32_t &index);
161 uint32_t indirectSymbolElementSize(const Section &sect);
162
Nick Kledzik29f749e2013-11-09 00:07:28 +0000163 // For use as template parameter to load command methods.
164 struct MachO64Trait {
165 typedef llvm::MachO::segment_command_64 command;
166 typedef llvm::MachO::section_64 section;
167 enum { LC = llvm::MachO::LC_SEGMENT_64 };
168 };
169
170 // For use as template parameter to load command methods.
171 struct MachO32Trait {
172 typedef llvm::MachO::segment_command command;
173 typedef llvm::MachO::section section;
174 enum { LC = llvm::MachO::LC_SEGMENT };
175 };
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000176
Nick Kledzik29f749e2013-11-09 00:07:28 +0000177 template <typename T>
Pete Cooper514594b2016-03-31 00:08:16 +0000178 llvm::Error writeSingleSegmentLoadCommand(uint8_t *&lc);
179 template <typename T> llvm::Error writeSegmentLoadCommands(uint8_t *&lc);
Nick Kledzik29f749e2013-11-09 00:07:28 +0000180
Nick Kledzike34182f2013-11-06 21:36:55 +0000181 uint32_t pointerAlign(uint32_t value);
182 static StringRef dyldPath();
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000183
Nick Kledzike34182f2013-11-06 21:36:55 +0000184 struct SegExtraInfo {
185 uint32_t fileOffset;
Tim Northover08d6a7b2014-06-30 09:49:30 +0000186 uint32_t fileSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000187 std::vector<const Section*> sections;
188 };
189 typedef std::map<const Segment*, SegExtraInfo> SegMap;
190 struct SectionExtraInfo {
191 uint32_t fileOffset;
192 };
193 typedef std::map<const Section*, SectionExtraInfo> SectionMap;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000194
Nick Kledzike34182f2013-11-06 21:36:55 +0000195 const NormalizedFile &_file;
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000196 std::error_code _ec;
Nick Kledzike34182f2013-11-06 21:36:55 +0000197 uint8_t *_buffer;
198 const bool _is64;
199 const bool _swap;
200 const bool _bigEndianArch;
201 uint64_t _seg1addr;
202 uint32_t _startOfLoadCommands;
203 uint32_t _countOfLoadCommands;
204 uint32_t _endOfLoadCommands;
205 uint32_t _startOfRelocations;
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000206 uint32_t _startOfFunctionStarts;
Nick Kledzik21921372014-07-24 23:06:56 +0000207 uint32_t _startOfDataInCode;
Nick Kledzike34182f2013-11-06 21:36:55 +0000208 uint32_t _startOfSymbols;
209 uint32_t _startOfIndirectSymbols;
210 uint32_t _startOfSymbolStrings;
211 uint32_t _endOfSymbolStrings;
212 uint32_t _symbolTableLocalsStartIndex;
213 uint32_t _symbolTableGlobalsStartIndex;
214 uint32_t _symbolTableUndefinesStartIndex;
215 uint32_t _symbolStringPoolSize;
216 uint32_t _symbolTableSize;
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000217 uint32_t _functionStartsSize;
Nick Kledzik21921372014-07-24 23:06:56 +0000218 uint32_t _dataInCodeSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000219 uint32_t _indirectSymbolTableCount;
220 // Used in object file creation only
221 uint32_t _startOfSectionsContent;
222 uint32_t _endOfSectionsContent;
223 // Used in final linked image only
224 uint32_t _startOfLinkEdit;
225 uint32_t _startOfRebaseInfo;
226 uint32_t _endOfRebaseInfo;
227 uint32_t _startOfBindingInfo;
228 uint32_t _endOfBindingInfo;
229 uint32_t _startOfLazyBindingInfo;
230 uint32_t _endOfLazyBindingInfo;
Nick Kledzik141330a2014-09-03 19:52:50 +0000231 uint32_t _startOfExportTrie;
232 uint32_t _endOfExportTrie;
Nick Kledzike34182f2013-11-06 21:36:55 +0000233 uint32_t _endOfLinkEdit;
234 uint64_t _addressOfLinkEdit;
235 SegMap _segInfo;
236 SectionMap _sectInfo;
237 ByteBuffer _rebaseInfo;
238 ByteBuffer _bindingInfo;
239 ByteBuffer _lazyBindingInfo;
240 ByteBuffer _weakBindingInfo;
Nick Kledzik141330a2014-09-03 19:52:50 +0000241 ByteBuffer _exportTrie;
Nick Kledzike34182f2013-11-06 21:36:55 +0000242};
243
244size_t headerAndLoadCommandsSize(const NormalizedFile &file) {
245 MachOFileLayout layout(file);
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000246 return layout.headerAndLoadCommandsSize();
Nick Kledzike34182f2013-11-06 21:36:55 +0000247}
248
249StringRef MachOFileLayout::dyldPath() {
250 return "/usr/lib/dyld";
251}
252
253uint32_t MachOFileLayout::pointerAlign(uint32_t value) {
Rui Ueyama489a8062016-01-14 20:53:50 +0000254 return llvm::alignTo(value, _is64 ? 8 : 4);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000255}
Nick Kledzike34182f2013-11-06 21:36:55 +0000256
257
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000258size_t MachOFileLayout::headerAndLoadCommandsSize() const {
259 return _endOfLoadCommands;
260}
Nick Kledzike34182f2013-11-06 21:36:55 +0000261
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000262MachOFileLayout::MachOFileLayout(const NormalizedFile &file)
Nick Kledzike34182f2013-11-06 21:36:55 +0000263 : _file(file),
264 _is64(MachOLinkingContext::is64Bit(file.arch)),
265 _swap(!MachOLinkingContext::isHostEndian(file.arch)),
266 _bigEndianArch(MachOLinkingContext::isBigEndian(file.arch)),
267 _seg1addr(INT64_MAX) {
268 _startOfLoadCommands = _is64 ? sizeof(mach_header_64) : sizeof(mach_header);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000269 const size_t segCommandBaseSize =
Nick Kledzike34182f2013-11-06 21:36:55 +0000270 (_is64 ? sizeof(segment_command_64) : sizeof(segment_command));
271 const size_t sectsSize = (_is64 ? sizeof(section_64) : sizeof(section));
272 if (file.fileType == llvm::MachO::MH_OBJECT) {
273 // object files have just one segment load command containing all sections
274 _endOfLoadCommands = _startOfLoadCommands
275 + segCommandBaseSize
276 + file.sections.size() * sectsSize
277 + sizeof(symtab_command);
278 _countOfLoadCommands = 2;
Pete Cooperceee5de2016-02-04 02:16:08 +0000279 if (file.hasMinVersionLoadCommand) {
280 _endOfLoadCommands += sizeof(version_min_command);
281 _countOfLoadCommands++;
282 }
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000283 if (!_file.functionStarts.empty()) {
284 _endOfLoadCommands += sizeof(linkedit_data_command);
285 _countOfLoadCommands++;
286 }
Pete Cooper9b28a452016-02-09 02:10:39 +0000287 if (_file.generateDataInCodeLoadCommand) {
Nick Kledzik21921372014-07-24 23:06:56 +0000288 _endOfLoadCommands += sizeof(linkedit_data_command);
289 _countOfLoadCommands++;
290 }
Nick Kledzikb072c362014-11-18 00:30:29 +0000291 // Assign file offsets to each section.
Nick Kledzike34182f2013-11-06 21:36:55 +0000292 _startOfSectionsContent = _endOfLoadCommands;
Nick Kledzike34182f2013-11-06 21:36:55 +0000293 unsigned relocCount = 0;
Nick Kledzikb072c362014-11-18 00:30:29 +0000294 uint64_t offset = _startOfSectionsContent;
Nick Kledzike34182f2013-11-06 21:36:55 +0000295 for (const Section &sect : file.sections) {
Lang Hamesac2adce2015-12-11 23:25:09 +0000296 if (isZeroFillSection(sect.type))
297 _sectInfo[&sect].fileOffset = 0;
298 else {
Rui Ueyama489a8062016-01-14 20:53:50 +0000299 offset = llvm::alignTo(offset, sect.alignment);
Nick Kledzikb072c362014-11-18 00:30:29 +0000300 _sectInfo[&sect].fileOffset = offset;
301 offset += sect.content.size();
Nick Kledzikb072c362014-11-18 00:30:29 +0000302 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000303 relocCount += sect.relocations.size();
304 }
Nick Kledzikb072c362014-11-18 00:30:29 +0000305 _endOfSectionsContent = offset;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000306
Nick Kledzike34182f2013-11-06 21:36:55 +0000307 computeSymbolTableSizes();
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000308 computeFunctionStartsSize();
Nick Kledzik21921372014-07-24 23:06:56 +0000309 computeDataInCodeSize();
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000310
Nick Kledzike34182f2013-11-06 21:36:55 +0000311 // Align start of relocations.
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000312 _startOfRelocations = pointerAlign(_endOfSectionsContent);
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000313 _startOfFunctionStarts = _startOfRelocations + relocCount * 8;
314 _startOfDataInCode = _startOfFunctionStarts + _functionStartsSize;
Nick Kledzik21921372014-07-24 23:06:56 +0000315 _startOfSymbols = _startOfDataInCode + _dataInCodeSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000316 // Add Indirect symbol table.
317 _startOfIndirectSymbols = _startOfSymbols + _symbolTableSize;
318 // Align start of symbol table and symbol strings.
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000319 _startOfSymbolStrings = _startOfIndirectSymbols
Nick Kledzike34182f2013-11-06 21:36:55 +0000320 + pointerAlign(_indirectSymbolTableCount * sizeof(uint32_t));
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000321 _endOfSymbolStrings = _startOfSymbolStrings
Nick Kledzike34182f2013-11-06 21:36:55 +0000322 + pointerAlign(_symbolStringPoolSize);
323 _endOfLinkEdit = _endOfSymbolStrings;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000324 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000325 llvm::dbgs() << "MachOFileLayout()\n"
326 << " startOfLoadCommands=" << _startOfLoadCommands << "\n"
327 << " countOfLoadCommands=" << _countOfLoadCommands << "\n"
328 << " endOfLoadCommands=" << _endOfLoadCommands << "\n"
329 << " startOfRelocations=" << _startOfRelocations << "\n"
330 << " startOfSymbols=" << _startOfSymbols << "\n"
331 << " startOfSymbolStrings=" << _startOfSymbolStrings << "\n"
332 << " endOfSymbolStrings=" << _endOfSymbolStrings << "\n"
333 << " startOfSectionsContent=" << _startOfSectionsContent << "\n"
334 << " endOfSectionsContent=" << _endOfSectionsContent << "\n");
335 } else {
336 // Final linked images have one load command per segment.
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000337 _endOfLoadCommands = _startOfLoadCommands
Nick Kledzike34182f2013-11-06 21:36:55 +0000338 + loadCommandsSize(_countOfLoadCommands);
339
340 // Assign section file offsets.
341 buildFileOffsets();
342 buildLinkEditInfo();
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000343
Nick Kledzike34182f2013-11-06 21:36:55 +0000344 // LINKEDIT of final linked images has in order:
345 // rebase info, binding info, lazy binding info, weak binding info,
Nick Kledzik21921372014-07-24 23:06:56 +0000346 // data-in-code, symbol table, indirect symbol table, symbol table strings.
Nick Kledzike34182f2013-11-06 21:36:55 +0000347 _startOfRebaseInfo = _startOfLinkEdit;
348 _endOfRebaseInfo = _startOfRebaseInfo + _rebaseInfo.size();
349 _startOfBindingInfo = _endOfRebaseInfo;
350 _endOfBindingInfo = _startOfBindingInfo + _bindingInfo.size();
351 _startOfLazyBindingInfo = _endOfBindingInfo;
352 _endOfLazyBindingInfo = _startOfLazyBindingInfo + _lazyBindingInfo.size();
Nick Kledzik141330a2014-09-03 19:52:50 +0000353 _startOfExportTrie = _endOfLazyBindingInfo;
354 _endOfExportTrie = _startOfExportTrie + _exportTrie.size();
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000355 _startOfFunctionStarts = _endOfExportTrie;
356 _startOfDataInCode = _startOfFunctionStarts + _functionStartsSize;
Nick Kledzik21921372014-07-24 23:06:56 +0000357 _startOfSymbols = _startOfDataInCode + _dataInCodeSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000358 _startOfIndirectSymbols = _startOfSymbols + _symbolTableSize;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000359 _startOfSymbolStrings = _startOfIndirectSymbols
Nick Kledzike34182f2013-11-06 21:36:55 +0000360 + pointerAlign(_indirectSymbolTableCount * sizeof(uint32_t));
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000361 _endOfSymbolStrings = _startOfSymbolStrings
Nick Kledzike34182f2013-11-06 21:36:55 +0000362 + pointerAlign(_symbolStringPoolSize);
363 _endOfLinkEdit = _endOfSymbolStrings;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000364 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000365 llvm::dbgs() << "MachOFileLayout()\n"
366 << " startOfLoadCommands=" << _startOfLoadCommands << "\n"
367 << " countOfLoadCommands=" << _countOfLoadCommands << "\n"
368 << " endOfLoadCommands=" << _endOfLoadCommands << "\n"
369 << " startOfLinkEdit=" << _startOfLinkEdit << "\n"
370 << " startOfRebaseInfo=" << _startOfRebaseInfo << "\n"
371 << " endOfRebaseInfo=" << _endOfRebaseInfo << "\n"
372 << " startOfBindingInfo=" << _startOfBindingInfo << "\n"
373 << " endOfBindingInfo=" << _endOfBindingInfo << "\n"
374 << " startOfLazyBindingInfo=" << _startOfLazyBindingInfo << "\n"
375 << " endOfLazyBindingInfo=" << _endOfLazyBindingInfo << "\n"
Nick Kledzik141330a2014-09-03 19:52:50 +0000376 << " startOfExportTrie=" << _startOfExportTrie << "\n"
377 << " endOfExportTrie=" << _endOfExportTrie << "\n"
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000378 << " startOfFunctionStarts=" << _startOfFunctionStarts << "\n"
Nick Kledzik21921372014-07-24 23:06:56 +0000379 << " startOfDataInCode=" << _startOfDataInCode << "\n"
Nick Kledzike34182f2013-11-06 21:36:55 +0000380 << " startOfSymbols=" << _startOfSymbols << "\n"
381 << " startOfSymbolStrings=" << _startOfSymbolStrings << "\n"
382 << " endOfSymbolStrings=" << _endOfSymbolStrings << "\n"
383 << " addressOfLinkEdit=" << _addressOfLinkEdit << "\n");
384 }
385}
386
387uint32_t MachOFileLayout::loadCommandsSize(uint32_t &count) {
388 uint32_t size = 0;
389 count = 0;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000390
391 const size_t segCommandSize =
Nick Kledzike34182f2013-11-06 21:36:55 +0000392 (_is64 ? sizeof(segment_command_64) : sizeof(segment_command));
393 const size_t sectionSize = (_is64 ? sizeof(section_64) : sizeof(section));
394
395 // Add LC_SEGMENT for each segment.
396 size += _file.segments.size() * segCommandSize;
397 count += _file.segments.size();
398 // Add section record for each section.
399 size += _file.sections.size() * sectionSize;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000400
Tim Northover301c4e62014-07-01 08:15:41 +0000401 // If creating a dylib, add LC_ID_DYLIB.
402 if (_file.fileType == llvm::MachO::MH_DYLIB) {
403 size += sizeof(dylib_command) + pointerAlign(_file.installName.size() + 1);
404 ++count;
405 }
406
Nick Kledzike34182f2013-11-06 21:36:55 +0000407 // Add LC_DYLD_INFO
408 size += sizeof(dyld_info_command);
409 ++count;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000410
Nick Kledzike34182f2013-11-06 21:36:55 +0000411 // Add LC_SYMTAB
412 size += sizeof(symtab_command);
413 ++count;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000414
Nick Kledzike34182f2013-11-06 21:36:55 +0000415 // Add LC_DYSYMTAB
416 if (_file.fileType != llvm::MachO::MH_PRELOAD) {
417 size += sizeof(dysymtab_command);
418 ++count;
419 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000420
Pete Cooper354809e2016-02-03 22:28:29 +0000421 // If main executable add LC_LOAD_DYLINKER
Nick Kledzike34182f2013-11-06 21:36:55 +0000422 if (_file.fileType == llvm::MachO::MH_EXECUTE) {
423 size += pointerAlign(sizeof(dylinker_command) + dyldPath().size()+1);
424 ++count;
Pete Cooper354809e2016-02-03 22:28:29 +0000425 }
426
427 // Add LC_VERSION_MIN_MACOSX, LC_VERSION_MIN_IPHONEOS, LC_VERSION_MIN_WATCHOS,
428 // LC_VERSION_MIN_TVOS
429 if (_file.hasMinVersionLoadCommand) {
430 size += sizeof(version_min_command);
431 ++count;
432 }
433
Pete Cooper40576fa2016-02-04 02:45:23 +0000434 // Add LC_SOURCE_VERSION
435 size += sizeof(source_version_command);
436 ++count;
437
Pete Cooper354809e2016-02-03 22:28:29 +0000438 // If main executable add LC_MAIN
439 if (_file.fileType == llvm::MachO::MH_EXECUTE) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000440 size += sizeof(entry_point_command);
441 ++count;
442 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000443
Nick Kledzike34182f2013-11-06 21:36:55 +0000444 // Add LC_LOAD_DYLIB for each dependent dylib.
445 for (const DependentDylib &dep : _file.dependentDylibs) {
446 size += sizeof(dylib_command) + pointerAlign(dep.path.size()+1);
447 ++count;
448 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000449
Jean-Daniel Dupas23dd15e2014-12-18 21:33:38 +0000450 // Add LC_RPATH
451 for (const StringRef &path : _file.rpaths) {
Lang Hames2ed3bf92015-10-29 16:50:26 +0000452 size += pointerAlign(sizeof(rpath_command) + path.size() + 1);
Jean-Daniel Dupas23dd15e2014-12-18 21:33:38 +0000453 ++count;
454 }
455
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000456 // Add LC_FUNCTION_STARTS if needed
457 if (!_file.functionStarts.empty()) {
458 size += sizeof(linkedit_data_command);
459 ++count;
460 }
461
Pete Cooper9b28a452016-02-09 02:10:39 +0000462 // Add LC_DATA_IN_CODE if requested. Note, we do encode zero length entries.
463 // FIXME: Zero length entries is only to match ld64. Should we change this?
464 if (_file.generateDataInCodeLoadCommand) {
Nick Kledzik54ce29582014-10-28 22:21:10 +0000465 size += sizeof(linkedit_data_command);
466 ++count;
467 }
468
Nick Kledzike34182f2013-11-06 21:36:55 +0000469 return size;
470}
471
472static bool overlaps(const Segment &s1, const Segment &s2) {
473 if (s2.address >= s1.address+s1.size)
474 return false;
475 if (s1.address >= s2.address+s2.size)
476 return false;
477 return true;
478}
479
480static bool overlaps(const Section &s1, const Section &s2) {
481 if (s2.address >= s1.address+s1.content.size())
482 return false;
483 if (s1.address >= s2.address+s2.content.size())
484 return false;
485 return true;
486}
487
488void MachOFileLayout::buildFileOffsets() {
489 // Verify no segments overlap
490 for (const Segment &sg1 : _file.segments) {
491 for (const Segment &sg2 : _file.segments) {
492 if (&sg1 == &sg2)
493 continue;
494 if (overlaps(sg1,sg2)) {
Rafael Espindola372bc702014-06-13 17:20:48 +0000495 _ec = make_error_code(llvm::errc::executable_format_error);
Nick Kledzike34182f2013-11-06 21:36:55 +0000496 return;
497 }
498 }
499 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000500
501 // Verify no sections overlap
Nick Kledzike34182f2013-11-06 21:36:55 +0000502 for (const Section &s1 : _file.sections) {
503 for (const Section &s2 : _file.sections) {
504 if (&s1 == &s2)
505 continue;
506 if (overlaps(s1,s2)) {
Rafael Espindola372bc702014-06-13 17:20:48 +0000507 _ec = make_error_code(llvm::errc::executable_format_error);
Nick Kledzike34182f2013-11-06 21:36:55 +0000508 return;
509 }
510 }
511 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000512
Nick Kledzike34182f2013-11-06 21:36:55 +0000513 // Build side table of extra info about segments and sections.
514 SegExtraInfo t;
515 t.fileOffset = 0;
516 for (const Segment &sg : _file.segments) {
517 _segInfo[&sg] = t;
518 }
519 SectionExtraInfo t2;
520 t2.fileOffset = 0;
521 // Assign sections to segments.
522 for (const Section &s : _file.sections) {
523 _sectInfo[&s] = t2;
Nick Kledzik1bebb282014-09-09 23:52:59 +0000524 bool foundSegment = false;
Nick Kledzike34182f2013-11-06 21:36:55 +0000525 for (const Segment &sg : _file.segments) {
Nick Kledzik1bebb282014-09-09 23:52:59 +0000526 if (sg.name.equals(s.segmentName)) {
527 if ((s.address >= sg.address)
Nick Kledzike34182f2013-11-06 21:36:55 +0000528 && (s.address+s.content.size() <= sg.address+sg.size)) {
Nick Kledzik1bebb282014-09-09 23:52:59 +0000529 _segInfo[&sg].sections.push_back(&s);
530 foundSegment = true;
531 break;
Nick Kledzike34182f2013-11-06 21:36:55 +0000532 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000533 }
534 }
Nick Kledzik1bebb282014-09-09 23:52:59 +0000535 if (!foundSegment) {
536 _ec = make_error_code(llvm::errc::executable_format_error);
537 return;
538 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000539 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000540
Nick Kledzike34182f2013-11-06 21:36:55 +0000541 // Assign file offsets.
542 uint32_t fileOffset = 0;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000543 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000544 llvm::dbgs() << "buildFileOffsets()\n");
545 for (const Segment &sg : _file.segments) {
Tim Northover08d6a7b2014-06-30 09:49:30 +0000546 _segInfo[&sg].fileOffset = fileOffset;
Pete Cooperb8fec3e2016-02-06 00:51:16 +0000547 if ((_seg1addr == INT64_MAX) && sg.init_access)
Nick Kledzike34182f2013-11-06 21:36:55 +0000548 _seg1addr = sg.address;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000549 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000550 llvm::dbgs() << " segment=" << sg.name
551 << ", fileOffset=" << _segInfo[&sg].fileOffset << "\n");
Tim Northover08d6a7b2014-06-30 09:49:30 +0000552
553 uint32_t segFileSize = 0;
Nick Kledzik761d6542014-10-24 22:19:22 +0000554 // A segment that is not zero-fill must use a least one page of disk space.
Pete Cooperb8fec3e2016-02-06 00:51:16 +0000555 if (sg.init_access)
Nick Kledzik761d6542014-10-24 22:19:22 +0000556 segFileSize = _file.pageSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000557 for (const Section *s : _segInfo[&sg].sections) {
Tim Northover08d6a7b2014-06-30 09:49:30 +0000558 uint32_t sectOffset = s->address - sg.address;
559 uint32_t sectFileSize =
Lang Hamesac2adce2015-12-11 23:25:09 +0000560 isZeroFillSection(s->type) ? 0 : s->content.size();
Tim Northover08d6a7b2014-06-30 09:49:30 +0000561 segFileSize = std::max(segFileSize, sectOffset + sectFileSize);
562
563 _sectInfo[s].fileOffset = _segInfo[&sg].fileOffset + sectOffset;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000564 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000565 llvm::dbgs() << " section=" << s->sectionName
566 << ", fileOffset=" << fileOffset << "\n");
567 }
Tim Northover08d6a7b2014-06-30 09:49:30 +0000568
Pete Cooper353652f2016-02-06 00:14:15 +0000569 // round up all segments to page aligned, except __LINKEDIT
570 if (!sg.name.equals("__LINKEDIT")) {
571 _segInfo[&sg].fileSize = llvm::alignTo(segFileSize, _file.pageSize);
572 fileOffset = llvm::alignTo(fileOffset + segFileSize, _file.pageSize);
573 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000574 _addressOfLinkEdit = sg.address + sg.size;
575 }
Tim Northover08d6a7b2014-06-30 09:49:30 +0000576 _startOfLinkEdit = fileOffset;
Nick Kledzike34182f2013-11-06 21:36:55 +0000577}
578
Nick Kledzike34182f2013-11-06 21:36:55 +0000579size_t MachOFileLayout::size() const {
580 return _endOfSymbolStrings;
581}
582
583void MachOFileLayout::writeMachHeader() {
Pete Cooper8563e5a2016-02-04 20:43:43 +0000584 auto cpusubtype = MachOLinkingContext::cpuSubtypeFromArch(_file.arch);
585 // dynamic x86 executables on newer OS version should also set the
586 // CPU_SUBTYPE_LIB64 mask in the CPU subtype.
587 // FIXME: Check that this is a dynamic executable, not a static one.
588 if (_file.fileType == llvm::MachO::MH_EXECUTE &&
589 cpusubtype == CPU_SUBTYPE_X86_64_ALL &&
590 _file.os == MachOLinkingContext::OS::macOSX) {
591 uint32_t version;
592 bool failed = MachOLinkingContext::parsePackedVersion("10.5", version);
593 if (!failed && _file.minOSverson >= version)
594 cpusubtype |= CPU_SUBTYPE_LIB64;
595 }
596
Nick Kledzike34182f2013-11-06 21:36:55 +0000597 mach_header *mh = reinterpret_cast<mach_header*>(_buffer);
598 mh->magic = _is64 ? llvm::MachO::MH_MAGIC_64 : llvm::MachO::MH_MAGIC;
599 mh->cputype = MachOLinkingContext::cpuTypeFromArch(_file.arch);
Pete Cooper8563e5a2016-02-04 20:43:43 +0000600 mh->cpusubtype = cpusubtype;
Nick Kledzike34182f2013-11-06 21:36:55 +0000601 mh->filetype = _file.fileType;
602 mh->ncmds = _countOfLoadCommands;
603 mh->sizeofcmds = _endOfLoadCommands - _startOfLoadCommands;
604 mh->flags = _file.flags;
605 if (_swap)
606 swapStruct(*mh);
607}
608
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000609uint32_t MachOFileLayout::indirectSymbolIndex(const Section &sect,
Nick Kledzike34182f2013-11-06 21:36:55 +0000610 uint32_t &index) {
611 if (sect.indirectSymbols.empty())
612 return 0;
613 uint32_t result = index;
614 index += sect.indirectSymbols.size();
615 return result;
616}
617
618uint32_t MachOFileLayout::indirectSymbolElementSize(const Section &sect) {
619 if (sect.indirectSymbols.empty())
620 return 0;
621 if (sect.type != S_SYMBOL_STUBS)
622 return 0;
623 return sect.content.size() / sect.indirectSymbols.size();
624}
625
Nick Kledzik29f749e2013-11-09 00:07:28 +0000626template <typename T>
Pete Cooper514594b2016-03-31 00:08:16 +0000627llvm::Error MachOFileLayout::writeSingleSegmentLoadCommand(uint8_t *&lc) {
Nick Kledzik29f749e2013-11-09 00:07:28 +0000628 typename T::command* seg = reinterpret_cast<typename T::command*>(lc);
629 seg->cmd = T::LC;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000630 seg->cmdsize = sizeof(typename T::command)
Nick Kledzik29f749e2013-11-09 00:07:28 +0000631 + _file.sections.size() * sizeof(typename T::section);
Nick Kledzike34182f2013-11-06 21:36:55 +0000632 uint8_t *next = lc + seg->cmdsize;
633 memset(seg->segname, 0, 16);
634 seg->vmaddr = 0;
Nick Kledzikb072c362014-11-18 00:30:29 +0000635 seg->vmsize = _file.sections.back().address
636 + _file.sections.back().content.size();
Nick Kledzike34182f2013-11-06 21:36:55 +0000637 seg->fileoff = _endOfLoadCommands;
Lang Hames8c2406b2016-08-10 22:15:09 +0000638 seg->filesize = _sectInfo[&_file.sections.back()].fileOffset +
639 _file.sections.back().content.size() -
640 _sectInfo[&_file.sections.front()].fileOffset;
Nick Kledzike34182f2013-11-06 21:36:55 +0000641 seg->maxprot = VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE;
642 seg->initprot = VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE;
643 seg->nsects = _file.sections.size();
644 seg->flags = 0;
645 if (_swap)
646 swapStruct(*seg);
Nick Kledzik29f749e2013-11-09 00:07:28 +0000647 typename T::section *sout = reinterpret_cast<typename T::section*>
648 (lc+sizeof(typename T::command));
Nick Kledzike34182f2013-11-06 21:36:55 +0000649 uint32_t relOffset = _startOfRelocations;
Nick Kledzike34182f2013-11-06 21:36:55 +0000650 uint32_t indirectSymRunningIndex = 0;
651 for (const Section &sin : _file.sections) {
652 setString16(sin.sectionName, sout->sectname);
653 setString16(sin.segmentName, sout->segname);
654 sout->addr = sin.address;
655 sout->size = sin.content.size();
Nick Kledzikb072c362014-11-18 00:30:29 +0000656 sout->offset = _sectInfo[&sin].fileOffset;
Rui Ueyamaf217ef02015-03-26 02:03:44 +0000657 sout->align = llvm::Log2_32(sin.alignment);
Nick Kledzike34182f2013-11-06 21:36:55 +0000658 sout->reloff = sin.relocations.empty() ? 0 : relOffset;
659 sout->nreloc = sin.relocations.size();
660 sout->flags = sin.type | sin.attributes;
661 sout->reserved1 = indirectSymbolIndex(sin, indirectSymRunningIndex);
662 sout->reserved2 = indirectSymbolElementSize(sin);
663 relOffset += sin.relocations.size() * sizeof(any_relocation_info);
Nick Kledzike34182f2013-11-06 21:36:55 +0000664 if (_swap)
665 swapStruct(*sout);
666 ++sout;
667 }
668 lc = next;
Pete Cooper514594b2016-03-31 00:08:16 +0000669 return llvm::Error();
Nick Kledzike34182f2013-11-06 21:36:55 +0000670}
671
Nick Kledzik29f749e2013-11-09 00:07:28 +0000672template <typename T>
Pete Cooper514594b2016-03-31 00:08:16 +0000673llvm::Error MachOFileLayout::writeSegmentLoadCommands(uint8_t *&lc) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000674 uint32_t indirectSymRunningIndex = 0;
675 for (const Segment &seg : _file.segments) {
Pete Cooper353652f2016-02-06 00:14:15 +0000676 // Link edit has no sections and a custom range of address, so handle it
677 // specially.
Nick Kledzike34182f2013-11-06 21:36:55 +0000678 SegExtraInfo &segInfo = _segInfo[&seg];
Pete Cooper353652f2016-02-06 00:14:15 +0000679 if (seg.name.equals("__LINKEDIT")) {
680 size_t linkeditSize = _endOfLinkEdit - _startOfLinkEdit;
681 typename T::command* cmd = reinterpret_cast<typename T::command*>(lc);
682 cmd->cmd = T::LC;
683 cmd->cmdsize = sizeof(typename T::command);
684 uint8_t *next = lc + cmd->cmdsize;
685 setString16("__LINKEDIT", cmd->segname);
686 cmd->vmaddr = _addressOfLinkEdit;
687 cmd->vmsize = llvm::alignTo(linkeditSize, _file.pageSize);
688 cmd->fileoff = _startOfLinkEdit;
689 cmd->filesize = linkeditSize;
Pete Cooperb8fec3e2016-02-06 00:51:16 +0000690 cmd->initprot = seg.init_access;
691 cmd->maxprot = seg.max_access;
Pete Cooper353652f2016-02-06 00:14:15 +0000692 cmd->nsects = 0;
693 cmd->flags = 0;
694 if (_swap)
695 swapStruct(*cmd);
696 lc = next;
697 continue;
698 }
699 // Write segment command with trailing sections.
Nick Kledzik29f749e2013-11-09 00:07:28 +0000700 typename T::command* cmd = reinterpret_cast<typename T::command*>(lc);
701 cmd->cmd = T::LC;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000702 cmd->cmdsize = sizeof(typename T::command)
Nick Kledzik29f749e2013-11-09 00:07:28 +0000703 + segInfo.sections.size() * sizeof(typename T::section);
Nick Kledzike34182f2013-11-06 21:36:55 +0000704 uint8_t *next = lc + cmd->cmdsize;
705 setString16(seg.name, cmd->segname);
706 cmd->vmaddr = seg.address;
707 cmd->vmsize = seg.size;
708 cmd->fileoff = segInfo.fileOffset;
Tim Northover08d6a7b2014-06-30 09:49:30 +0000709 cmd->filesize = segInfo.fileSize;
Pete Cooperb8fec3e2016-02-06 00:51:16 +0000710 cmd->initprot = seg.init_access;
711 cmd->maxprot = seg.max_access;
Nick Kledzike34182f2013-11-06 21:36:55 +0000712 cmd->nsects = segInfo.sections.size();
713 cmd->flags = 0;
714 if (_swap)
715 swapStruct(*cmd);
Nick Kledzik29f749e2013-11-09 00:07:28 +0000716 typename T::section *sect = reinterpret_cast<typename T::section*>
717 (lc+sizeof(typename T::command));
Nick Kledzike34182f2013-11-06 21:36:55 +0000718 for (const Section *section : segInfo.sections) {
719 setString16(section->sectionName, sect->sectname);
720 setString16(section->segmentName, sect->segname);
721 sect->addr = section->address;
722 sect->size = section->content.size();
Lang Hamesac2adce2015-12-11 23:25:09 +0000723 if (isZeroFillSection(section->type))
Nick Kledzikb072c362014-11-18 00:30:29 +0000724 sect->offset = 0;
725 else
726 sect->offset = section->address - seg.address + segInfo.fileOffset;
Rui Ueyamaf217ef02015-03-26 02:03:44 +0000727 sect->align = llvm::Log2_32(section->alignment);
Nick Kledzike34182f2013-11-06 21:36:55 +0000728 sect->reloff = 0;
729 sect->nreloc = 0;
730 sect->flags = section->type | section->attributes;
731 sect->reserved1 = indirectSymbolIndex(*section, indirectSymRunningIndex);
732 sect->reserved2 = indirectSymbolElementSize(*section);
733 if (_swap)
734 swapStruct(*sect);
735 ++sect;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000736 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000737 lc = reinterpret_cast<uint8_t*>(next);
738 }
Pete Cooper514594b2016-03-31 00:08:16 +0000739 return llvm::Error();
Nick Kledzike34182f2013-11-06 21:36:55 +0000740}
741
Pete Cooperceee5de2016-02-04 02:16:08 +0000742static void writeVersionMinLoadCommand(const NormalizedFile &_file,
743 bool _swap,
744 uint8_t *&lc) {
745 if (!_file.hasMinVersionLoadCommand)
746 return;
747 version_min_command *vm = reinterpret_cast<version_min_command*>(lc);
748 switch (_file.os) {
749 case MachOLinkingContext::OS::unknown:
750 vm->cmd = _file.minOSVersionKind;
751 vm->cmdsize = sizeof(version_min_command);
752 vm->version = _file.minOSverson;
753 vm->sdk = 0;
754 break;
755 case MachOLinkingContext::OS::macOSX:
756 vm->cmd = LC_VERSION_MIN_MACOSX;
757 vm->cmdsize = sizeof(version_min_command);
758 vm->version = _file.minOSverson;
759 vm->sdk = _file.sdkVersion;
760 break;
761 case MachOLinkingContext::OS::iOS:
762 case MachOLinkingContext::OS::iOS_simulator:
763 vm->cmd = LC_VERSION_MIN_IPHONEOS;
764 vm->cmdsize = sizeof(version_min_command);
765 vm->version = _file.minOSverson;
766 vm->sdk = _file.sdkVersion;
767 break;
768 }
769 if (_swap)
770 swapStruct(*vm);
771 lc += sizeof(version_min_command);
772}
773
Pete Cooper514594b2016-03-31 00:08:16 +0000774llvm::Error MachOFileLayout::writeLoadCommands() {
Nick Kledzike34182f2013-11-06 21:36:55 +0000775 uint8_t *lc = &_buffer[_startOfLoadCommands];
776 if (_file.fileType == llvm::MachO::MH_OBJECT) {
777 // Object files have one unnamed segment which holds all sections.
Pete Cooper514594b2016-03-31 00:08:16 +0000778 if (_is64) {
779 if (auto ec = writeSingleSegmentLoadCommand<MachO64Trait>(lc))
Pete Coopere487da12016-03-31 00:35:50 +0000780 return ec;
Pete Cooper514594b2016-03-31 00:08:16 +0000781 } else {
782 if (auto ec = writeSingleSegmentLoadCommand<MachO32Trait>(lc))
Pete Cooperdc59c792016-03-31 00:38:02 +0000783 return ec;
Pete Cooper514594b2016-03-31 00:08:16 +0000784 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000785 // Add LC_SYMTAB with symbol table info
786 symtab_command* st = reinterpret_cast<symtab_command*>(lc);
787 st->cmd = LC_SYMTAB;
788 st->cmdsize = sizeof(symtab_command);
789 st->symoff = _startOfSymbols;
Lang Hames436f7d62016-07-27 22:55:30 +0000790 st->nsyms = _file.stabsSymbols.size() + _file.localSymbols.size() +
791 _file.globalSymbols.size() + _file.undefinedSymbols.size();
Nick Kledzike34182f2013-11-06 21:36:55 +0000792 st->stroff = _startOfSymbolStrings;
793 st->strsize = _endOfSymbolStrings - _startOfSymbolStrings;
794 if (_swap)
795 swapStruct(*st);
Nick Kledzik21921372014-07-24 23:06:56 +0000796 lc += sizeof(symtab_command);
Pete Cooperceee5de2016-02-04 02:16:08 +0000797
798 // Add LC_VERSION_MIN_MACOSX, LC_VERSION_MIN_IPHONEOS,
799 // LC_VERSION_MIN_WATCHOS, LC_VERSION_MIN_TVOS
800 writeVersionMinLoadCommand(_file, _swap, lc);
801
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000802 // Add LC_FUNCTION_STARTS if needed.
803 if (_functionStartsSize != 0) {
804 linkedit_data_command* dl = reinterpret_cast<linkedit_data_command*>(lc);
805 dl->cmd = LC_FUNCTION_STARTS;
806 dl->cmdsize = sizeof(linkedit_data_command);
807 dl->dataoff = _startOfFunctionStarts;
808 dl->datasize = _functionStartsSize;
809 if (_swap)
810 swapStruct(*dl);
811 lc += sizeof(linkedit_data_command);
812 }
813
Pete Cooper9b28a452016-02-09 02:10:39 +0000814 // Add LC_DATA_IN_CODE if requested.
815 if (_file.generateDataInCodeLoadCommand) {
Nick Kledzik21921372014-07-24 23:06:56 +0000816 linkedit_data_command* dl = reinterpret_cast<linkedit_data_command*>(lc);
817 dl->cmd = LC_DATA_IN_CODE;
818 dl->cmdsize = sizeof(linkedit_data_command);
819 dl->dataoff = _startOfDataInCode;
820 dl->datasize = _dataInCodeSize;
821 if (_swap)
822 swapStruct(*dl);
823 lc += sizeof(linkedit_data_command);
824 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000825 } else {
826 // Final linked images have sections under segments.
Pete Cooper514594b2016-03-31 00:08:16 +0000827 if (_is64) {
828 if (auto ec = writeSegmentLoadCommands<MachO64Trait>(lc))
Pete Cooperdc59c792016-03-31 00:38:02 +0000829 return ec;
Pete Cooper514594b2016-03-31 00:08:16 +0000830 } else {
831 if (auto ec = writeSegmentLoadCommands<MachO32Trait>(lc))
Pete Cooperdc59c792016-03-31 00:38:02 +0000832 return ec;
Pete Cooper514594b2016-03-31 00:08:16 +0000833 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000834
Tim Northover301c4e62014-07-01 08:15:41 +0000835 // Add LC_ID_DYLIB command for dynamic libraries.
836 if (_file.fileType == llvm::MachO::MH_DYLIB) {
837 dylib_command *dc = reinterpret_cast<dylib_command*>(lc);
838 StringRef path = _file.installName;
839 uint32_t size = sizeof(dylib_command) + pointerAlign(path.size() + 1);
840 dc->cmd = LC_ID_DYLIB;
841 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_LOAD_DYLIB
844 dc->dylib.timestamp = 1;
Nick Kledzik5b9e48b2014-11-19 02:21:53 +0000845 dc->dylib.current_version = _file.currentVersion;
846 dc->dylib.compatibility_version = _file.compatVersion;
Tim Northover301c4e62014-07-01 08:15:41 +0000847 if (_swap)
848 swapStruct(*dc);
849 memcpy(lc + sizeof(dylib_command), path.begin(), path.size());
850 lc[sizeof(dylib_command) + path.size()] = '\0';
851 lc += size;
852 }
853
Nick Kledzike34182f2013-11-06 21:36:55 +0000854 // Add LC_DYLD_INFO_ONLY.
855 dyld_info_command* di = reinterpret_cast<dyld_info_command*>(lc);
856 di->cmd = LC_DYLD_INFO_ONLY;
857 di->cmdsize = sizeof(dyld_info_command);
858 di->rebase_off = _rebaseInfo.size() ? _startOfRebaseInfo : 0;
859 di->rebase_size = _rebaseInfo.size();
860 di->bind_off = _bindingInfo.size() ? _startOfBindingInfo : 0;
861 di->bind_size = _bindingInfo.size();
862 di->weak_bind_off = 0;
863 di->weak_bind_size = 0;
864 di->lazy_bind_off = _lazyBindingInfo.size() ? _startOfLazyBindingInfo : 0;
865 di->lazy_bind_size = _lazyBindingInfo.size();
Nick Kledzik141330a2014-09-03 19:52:50 +0000866 di->export_off = _exportTrie.size() ? _startOfExportTrie : 0;
867 di->export_size = _exportTrie.size();
Nick Kledzike34182f2013-11-06 21:36:55 +0000868 if (_swap)
869 swapStruct(*di);
870 lc += sizeof(dyld_info_command);
871
872 // Add LC_SYMTAB with symbol table info.
873 symtab_command* st = reinterpret_cast<symtab_command*>(lc);
874 st->cmd = LC_SYMTAB;
875 st->cmdsize = sizeof(symtab_command);
876 st->symoff = _startOfSymbols;
Lang Hames436f7d62016-07-27 22:55:30 +0000877 st->nsyms = _file.stabsSymbols.size() + _file.localSymbols.size() +
878 _file.globalSymbols.size() + _file.undefinedSymbols.size();
Nick Kledzike34182f2013-11-06 21:36:55 +0000879 st->stroff = _startOfSymbolStrings;
880 st->strsize = _endOfSymbolStrings - _startOfSymbolStrings;
881 if (_swap)
882 swapStruct(*st);
883 lc += sizeof(symtab_command);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000884
Nick Kledzike34182f2013-11-06 21:36:55 +0000885 // Add LC_DYSYMTAB
886 if (_file.fileType != llvm::MachO::MH_PRELOAD) {
887 dysymtab_command* dst = reinterpret_cast<dysymtab_command*>(lc);
888 dst->cmd = LC_DYSYMTAB;
889 dst->cmdsize = sizeof(dysymtab_command);
890 dst->ilocalsym = _symbolTableLocalsStartIndex;
Lang Hames436f7d62016-07-27 22:55:30 +0000891 dst->nlocalsym = _file.stabsSymbols.size() +
892 _file.localSymbols.size();
Nick Kledzike34182f2013-11-06 21:36:55 +0000893 dst->iextdefsym = _symbolTableGlobalsStartIndex;
894 dst->nextdefsym = _file.globalSymbols.size();
895 dst->iundefsym = _symbolTableUndefinesStartIndex;
896 dst->nundefsym = _file.undefinedSymbols.size();
897 dst->tocoff = 0;
898 dst->ntoc = 0;
899 dst->modtaboff = 0;
900 dst->nmodtab = 0;
901 dst->extrefsymoff = 0;
902 dst->nextrefsyms = 0;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000903 dst->indirectsymoff = _startOfIndirectSymbols;
Nick Kledzike34182f2013-11-06 21:36:55 +0000904 dst->nindirectsyms = _indirectSymbolTableCount;
905 dst->extreloff = 0;
906 dst->nextrel = 0;
907 dst->locreloff = 0;
908 dst->nlocrel = 0;
909 if (_swap)
910 swapStruct(*dst);
911 lc += sizeof(dysymtab_command);
912 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000913
Pete Cooper354809e2016-02-03 22:28:29 +0000914 // If main executable, add LC_LOAD_DYLINKER
Nick Kledzike34182f2013-11-06 21:36:55 +0000915 if (_file.fileType == llvm::MachO::MH_EXECUTE) {
916 // Build LC_LOAD_DYLINKER load command.
917 uint32_t size=pointerAlign(sizeof(dylinker_command)+dyldPath().size()+1);
918 dylinker_command* dl = reinterpret_cast<dylinker_command*>(lc);
919 dl->cmd = LC_LOAD_DYLINKER;
920 dl->cmdsize = size;
921 dl->name = sizeof(dylinker_command); // offset
922 if (_swap)
923 swapStruct(*dl);
924 memcpy(lc+sizeof(dylinker_command), dyldPath().data(), dyldPath().size());
925 lc[sizeof(dylinker_command)+dyldPath().size()] = '\0';
926 lc += size;
Pete Cooper354809e2016-02-03 22:28:29 +0000927 }
928
929 // Add LC_VERSION_MIN_MACOSX, LC_VERSION_MIN_IPHONEOS, LC_VERSION_MIN_WATCHOS,
930 // LC_VERSION_MIN_TVOS
Pete Cooperceee5de2016-02-04 02:16:08 +0000931 writeVersionMinLoadCommand(_file, _swap, lc);
Pete Cooper354809e2016-02-03 22:28:29 +0000932
Pete Cooper40576fa2016-02-04 02:45:23 +0000933 // Add LC_SOURCE_VERSION
934 {
Pete Cooperb565bdf2016-03-23 22:00:09 +0000935 // Note, using a temporary here to appease UB as we may not be aligned
936 // enough for a struct containing a uint64_t when emitting a 32-bit binary
937 source_version_command sv;
938 sv.cmd = LC_SOURCE_VERSION;
939 sv.cmdsize = sizeof(source_version_command);
940 sv.version = _file.sourceVersion;
Pete Cooper40576fa2016-02-04 02:45:23 +0000941 if (_swap)
Pete Cooperb565bdf2016-03-23 22:00:09 +0000942 swapStruct(sv);
943 memcpy(lc, &sv, sizeof(source_version_command));
Pete Cooper40576fa2016-02-04 02:45:23 +0000944 lc += sizeof(source_version_command);
945 }
946
Pete Cooper354809e2016-02-03 22:28:29 +0000947 // If main executable, add LC_MAIN.
948 if (_file.fileType == llvm::MachO::MH_EXECUTE) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000949 // Build LC_MAIN load command.
Pete Cooper07601d32016-03-24 01:05:17 +0000950 // Note, using a temporary here to appease UB as we may not be aligned
951 // enough for a struct containing a uint64_t when emitting a 32-bit binary
952 entry_point_command ep;
953 ep.cmd = LC_MAIN;
954 ep.cmdsize = sizeof(entry_point_command);
955 ep.entryoff = _file.entryAddress - _seg1addr;
956 ep.stacksize = _file.stackSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000957 if (_swap)
Pete Cooper07601d32016-03-24 01:05:17 +0000958 swapStruct(ep);
959 memcpy(lc, &ep, sizeof(entry_point_command));
Nick Kledzike34182f2013-11-06 21:36:55 +0000960 lc += sizeof(entry_point_command);
961 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000962
Nick Kledzike34182f2013-11-06 21:36:55 +0000963 // Add LC_LOAD_DYLIB commands
964 for (const DependentDylib &dep : _file.dependentDylibs) {
965 dylib_command* dc = reinterpret_cast<dylib_command*>(lc);
966 uint32_t size = sizeof(dylib_command) + pointerAlign(dep.path.size()+1);
Nick Kledzik51720672014-10-16 19:31:28 +0000967 dc->cmd = dep.kind;
Nick Kledzike34182f2013-11-06 21:36:55 +0000968 dc->cmdsize = size;
969 dc->dylib.name = sizeof(dylib_command); // offset
Jean-Daniel Dupasedefccc2014-12-20 09:22:56 +0000970 // needs to be some constant value different than the one in LC_ID_DYLIB
Nick Kledzik5b9e48b2014-11-19 02:21:53 +0000971 dc->dylib.timestamp = 2;
972 dc->dylib.current_version = dep.currentVersion;
973 dc->dylib.compatibility_version = dep.compatVersion;
Nick Kledzike34182f2013-11-06 21:36:55 +0000974 if (_swap)
975 swapStruct(*dc);
976 memcpy(lc+sizeof(dylib_command), dep.path.begin(), dep.path.size());
977 lc[sizeof(dylib_command)+dep.path.size()] = '\0';
978 lc += size;
979 }
Jean-Daniel Dupas23dd15e2014-12-18 21:33:38 +0000980
981 // Add LC_RPATH
982 for (const StringRef &path : _file.rpaths) {
983 rpath_command *rpc = reinterpret_cast<rpath_command *>(lc);
Lang Hames2ed3bf92015-10-29 16:50:26 +0000984 uint32_t size = pointerAlign(sizeof(rpath_command) + path.size() + 1);
Jean-Daniel Dupas23dd15e2014-12-18 21:33:38 +0000985 rpc->cmd = LC_RPATH;
986 rpc->cmdsize = size;
987 rpc->path = sizeof(rpath_command); // offset
988 if (_swap)
989 swapStruct(*rpc);
990 memcpy(lc+sizeof(rpath_command), path.begin(), path.size());
991 lc[sizeof(rpath_command)+path.size()] = '\0';
992 lc += size;
993 }
994
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000995 // Add LC_FUNCTION_STARTS if needed.
996 if (_functionStartsSize != 0) {
997 linkedit_data_command* dl = reinterpret_cast<linkedit_data_command*>(lc);
998 dl->cmd = LC_FUNCTION_STARTS;
999 dl->cmdsize = sizeof(linkedit_data_command);
1000 dl->dataoff = _startOfFunctionStarts;
1001 dl->datasize = _functionStartsSize;
1002 if (_swap)
1003 swapStruct(*dl);
1004 lc += sizeof(linkedit_data_command);
1005 }
1006
Pete Cooper9b28a452016-02-09 02:10:39 +00001007 // Add LC_DATA_IN_CODE if requested.
1008 if (_file.generateDataInCodeLoadCommand) {
Nick Kledzik54ce29582014-10-28 22:21:10 +00001009 linkedit_data_command* dl = reinterpret_cast<linkedit_data_command*>(lc);
1010 dl->cmd = LC_DATA_IN_CODE;
1011 dl->cmdsize = sizeof(linkedit_data_command);
1012 dl->dataoff = _startOfDataInCode;
1013 dl->datasize = _dataInCodeSize;
1014 if (_swap)
1015 swapStruct(*dl);
1016 lc += sizeof(linkedit_data_command);
1017 }
Nick Kledzike34182f2013-11-06 21:36:55 +00001018 }
Pete Cooper514594b2016-03-31 00:08:16 +00001019 return llvm::Error();
Nick Kledzike34182f2013-11-06 21:36:55 +00001020}
1021
Nick Kledzike34182f2013-11-06 21:36:55 +00001022void MachOFileLayout::writeSectionContent() {
1023 for (const Section &s : _file.sections) {
1024 // Copy all section content to output buffer.
Lang Hamesac2adce2015-12-11 23:25:09 +00001025 if (isZeroFillSection(s.type))
Nick Kledzik61fdef62014-05-15 20:59:23 +00001026 continue;
Nick Kledzik1bebb282014-09-09 23:52:59 +00001027 if (s.content.empty())
1028 continue;
Nick Kledzike34182f2013-11-06 21:36:55 +00001029 uint32_t offset = _sectInfo[&s].fileOffset;
1030 uint8_t *p = &_buffer[offset];
1031 memcpy(p, &s.content[0], s.content.size());
1032 p += s.content.size();
1033 }
1034}
1035
1036void MachOFileLayout::writeRelocations() {
1037 uint32_t relOffset = _startOfRelocations;
1038 for (Section sect : _file.sections) {
1039 for (Relocation r : sect.relocations) {
1040 any_relocation_info* rb = reinterpret_cast<any_relocation_info*>(
1041 &_buffer[relOffset]);
1042 *rb = packRelocation(r, _swap, _bigEndianArch);
1043 relOffset += sizeof(any_relocation_info);
1044 }
1045 }
1046}
1047
Nick Kledzike34182f2013-11-06 21:36:55 +00001048void MachOFileLayout::appendSymbols(const std::vector<Symbol> &symbols,
1049 uint32_t &symOffset, uint32_t &strOffset) {
1050 for (const Symbol &sym : symbols) {
1051 if (_is64) {
1052 nlist_64* nb = reinterpret_cast<nlist_64*>(&_buffer[symOffset]);
1053 nb->n_strx = strOffset - _startOfSymbolStrings;
1054 nb->n_type = sym.type | sym.scope;
1055 nb->n_sect = sym.sect;
1056 nb->n_desc = sym.desc;
1057 nb->n_value = sym.value;
1058 if (_swap)
1059 swapStruct(*nb);
1060 symOffset += sizeof(nlist_64);
1061 } else {
1062 nlist* nb = reinterpret_cast<nlist*>(&_buffer[symOffset]);
1063 nb->n_strx = strOffset - _startOfSymbolStrings;
1064 nb->n_type = sym.type | sym.scope;
1065 nb->n_sect = sym.sect;
1066 nb->n_desc = sym.desc;
1067 nb->n_value = sym.value;
1068 if (_swap)
1069 swapStruct(*nb);
1070 symOffset += sizeof(nlist);
1071 }
1072 memcpy(&_buffer[strOffset], sym.name.begin(), sym.name.size());
1073 strOffset += sym.name.size();
1074 _buffer[strOffset++] ='\0'; // Strings in table have nul terminator.
1075 }
1076}
1077
Pete Cooper41f3e8e2016-02-09 01:38:13 +00001078void MachOFileLayout::writeFunctionStartsInfo() {
Pete Cooper8e1b9a12016-03-22 22:51:03 +00001079 if (!_functionStartsSize)
1080 return;
Pete Cooper41f3e8e2016-02-09 01:38:13 +00001081 memcpy(&_buffer[_startOfFunctionStarts], _file.functionStarts.data(),
1082 _functionStartsSize);
1083}
1084
Nick Kledzik21921372014-07-24 23:06:56 +00001085void MachOFileLayout::writeDataInCodeInfo() {
1086 uint32_t offset = _startOfDataInCode;
1087 for (const DataInCode &entry : _file.dataInCode) {
1088 data_in_code_entry *dst = reinterpret_cast<data_in_code_entry*>(
1089 &_buffer[offset]);
1090 dst->offset = entry.offset;
1091 dst->length = entry.length;
1092 dst->kind = entry.kind;
1093 if (_swap)
1094 swapStruct(*dst);
1095 offset += sizeof(data_in_code_entry);
1096 }
1097}
1098
Nick Kledzike34182f2013-11-06 21:36:55 +00001099void MachOFileLayout::writeSymbolTable() {
1100 // Write symbol table and symbol strings in parallel.
1101 uint32_t symOffset = _startOfSymbols;
1102 uint32_t strOffset = _startOfSymbolStrings;
Pete Cooper5559b242016-08-08 23:20:04 +00001103 // Reserve n_strx offset of zero to mean no name.
1104 _buffer[strOffset++] = ' ';
1105 _buffer[strOffset++] = '\0';
Lang Hames436f7d62016-07-27 22:55:30 +00001106 appendSymbols(_file.stabsSymbols, symOffset, strOffset);
Nick Kledzike34182f2013-11-06 21:36:55 +00001107 appendSymbols(_file.localSymbols, symOffset, strOffset);
1108 appendSymbols(_file.globalSymbols, symOffset, strOffset);
1109 appendSymbols(_file.undefinedSymbols, symOffset, strOffset);
1110 // Write indirect symbol table array.
1111 uint32_t *indirects = reinterpret_cast<uint32_t*>
1112 (&_buffer[_startOfIndirectSymbols]);
1113 if (_file.fileType == llvm::MachO::MH_OBJECT) {
1114 // Object files have sections in same order as input normalized file.
1115 for (const Section &section : _file.sections) {
1116 for (uint32_t index : section.indirectSymbols) {
1117 if (_swap)
Artyom Skrobov17587fb2014-06-14 12:40:04 +00001118 *indirects++ = llvm::sys::getSwappedBytes(index);
Nick Kledzike34182f2013-11-06 21:36:55 +00001119 else
1120 *indirects++ = index;
1121 }
1122 }
1123 } else {
1124 // Final linked images must sort sections from normalized file.
1125 for (const Segment &seg : _file.segments) {
1126 SegExtraInfo &segInfo = _segInfo[&seg];
1127 for (const Section *section : segInfo.sections) {
1128 for (uint32_t index : section->indirectSymbols) {
1129 if (_swap)
Artyom Skrobov17587fb2014-06-14 12:40:04 +00001130 *indirects++ = llvm::sys::getSwappedBytes(index);
Nick Kledzike34182f2013-11-06 21:36:55 +00001131 else
1132 *indirects++ = index;
1133 }
1134 }
1135 }
1136 }
1137}
1138
1139void MachOFileLayout::writeRebaseInfo() {
1140 memcpy(&_buffer[_startOfRebaseInfo], _rebaseInfo.bytes(), _rebaseInfo.size());
1141}
1142
1143void MachOFileLayout::writeBindingInfo() {
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001144 memcpy(&_buffer[_startOfBindingInfo],
Nick Kledzike34182f2013-11-06 21:36:55 +00001145 _bindingInfo.bytes(), _bindingInfo.size());
1146}
1147
1148void MachOFileLayout::writeLazyBindingInfo() {
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001149 memcpy(&_buffer[_startOfLazyBindingInfo],
Nick Kledzike34182f2013-11-06 21:36:55 +00001150 _lazyBindingInfo.bytes(), _lazyBindingInfo.size());
1151}
1152
Nick Kledzik141330a2014-09-03 19:52:50 +00001153void MachOFileLayout::writeExportInfo() {
1154 memcpy(&_buffer[_startOfExportTrie], _exportTrie.bytes(), _exportTrie.size());
1155}
1156
Nick Kledzike34182f2013-11-06 21:36:55 +00001157void MachOFileLayout::buildLinkEditInfo() {
1158 buildRebaseInfo();
1159 buildBindInfo();
1160 buildLazyBindInfo();
Nick Kledzik141330a2014-09-03 19:52:50 +00001161 buildExportTrie();
Nick Kledzike34182f2013-11-06 21:36:55 +00001162 computeSymbolTableSizes();
Pete Cooper41f3e8e2016-02-09 01:38:13 +00001163 computeFunctionStartsSize();
Nick Kledzik21921372014-07-24 23:06:56 +00001164 computeDataInCodeSize();
Nick Kledzike34182f2013-11-06 21:36:55 +00001165}
1166
1167void MachOFileLayout::buildSectionRelocations() {
1168
1169}
1170
1171void MachOFileLayout::buildRebaseInfo() {
1172 // TODO: compress rebasing info.
1173 for (const RebaseLocation& entry : _file.rebasingInfo) {
1174 _rebaseInfo.append_byte(REBASE_OPCODE_SET_TYPE_IMM | entry.kind);
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001175 _rebaseInfo.append_byte(REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
Nick Kledzike34182f2013-11-06 21:36:55 +00001176 | entry.segIndex);
1177 _rebaseInfo.append_uleb128(entry.segOffset);
1178 _rebaseInfo.append_uleb128(REBASE_OPCODE_DO_REBASE_IMM_TIMES | 1);
1179 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001180 _rebaseInfo.append_byte(REBASE_OPCODE_DONE);
Nick Kledzike34182f2013-11-06 21:36:55 +00001181 _rebaseInfo.align(_is64 ? 8 : 4);
1182}
1183
1184void MachOFileLayout::buildBindInfo() {
1185 // TODO: compress bind info.
Nick Kledzikf373c772014-11-11 01:31:18 +00001186 uint64_t lastAddend = 0;
Pete Cooper21f475e2016-08-11 20:37:02 +00001187 int lastOrdinal = 0x80000000;
1188 StringRef lastSymbolName;
1189 BindType lastType = (BindType)0;
1190 Hex32 lastSegOffset = ~0U;
1191 uint8_t lastSegIndex = (uint8_t)~0U;
Nick Kledzike34182f2013-11-06 21:36:55 +00001192 for (const BindLocation& entry : _file.bindingInfo) {
Pete Cooper21f475e2016-08-11 20:37:02 +00001193 if (entry.ordinal != lastOrdinal) {
1194 if (entry.ordinal <= 0)
1195 _bindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_SPECIAL_IMM |
1196 (entry.ordinal & BIND_IMMEDIATE_MASK));
1197 else if (entry.ordinal <= BIND_IMMEDIATE_MASK)
1198 _bindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM |
1199 entry.ordinal);
1200 else {
1201 _bindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB);
1202 _bindingInfo.append_uleb128(entry.ordinal);
1203 }
1204 lastOrdinal = entry.ordinal;
1205 }
1206
1207 if (lastSymbolName != entry.symbolName) {
1208 _bindingInfo.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM);
1209 _bindingInfo.append_string(entry.symbolName);
1210 lastSymbolName = entry.symbolName;
1211 }
1212
1213 if (lastType != entry.kind) {
1214 _bindingInfo.append_byte(BIND_OPCODE_SET_TYPE_IMM | entry.kind);
1215 lastType = entry.kind;
1216 }
1217
1218 if (lastSegIndex != entry.segIndex || lastSegOffset != entry.segOffset) {
1219 _bindingInfo.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
1220 | entry.segIndex);
1221 _bindingInfo.append_uleb128(entry.segOffset);
1222 lastSegIndex = entry.segIndex;
1223 lastSegOffset = entry.segOffset;
1224 }
Nick Kledzikf373c772014-11-11 01:31:18 +00001225 if (entry.addend != lastAddend) {
Nick Kledzike34182f2013-11-06 21:36:55 +00001226 _bindingInfo.append_byte(BIND_OPCODE_SET_ADDEND_SLEB);
1227 _bindingInfo.append_sleb128(entry.addend);
Nick Kledzikf373c772014-11-11 01:31:18 +00001228 lastAddend = entry.addend;
Nick Kledzike34182f2013-11-06 21:36:55 +00001229 }
1230 _bindingInfo.append_byte(BIND_OPCODE_DO_BIND);
1231 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001232 _bindingInfo.append_byte(BIND_OPCODE_DONE);
Nick Kledzike34182f2013-11-06 21:36:55 +00001233 _bindingInfo.align(_is64 ? 8 : 4);
1234}
1235
1236void MachOFileLayout::buildLazyBindInfo() {
1237 for (const BindLocation& entry : _file.lazyBindingInfo) {
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001238 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
Nick Kledzike34182f2013-11-06 21:36:55 +00001239 | entry.segIndex);
Pete Cooper1ed8f1f2016-08-11 20:59:27 +00001240 _lazyBindingInfo.append_uleb128(entry.segOffset);
1241 if (entry.ordinal <= 0)
Lang Hames5c692002015-09-28 20:25:14 +00001242 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_SPECIAL_IMM |
Pete Cooper1ed8f1f2016-08-11 20:59:27 +00001243 (entry.ordinal & BIND_IMMEDIATE_MASK));
1244 else if (entry.ordinal <= BIND_IMMEDIATE_MASK)
1245 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM |
1246 entry.ordinal);
1247 else {
1248 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB);
1249 _lazyBindingInfo.append_uleb128(entry.ordinal);
1250 }
1251 // FIXME: We need to | the opcode here with flags.
Nick Kledzike34182f2013-11-06 21:36:55 +00001252 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM);
1253 _lazyBindingInfo.append_string(entry.symbolName);
1254 _lazyBindingInfo.append_byte(BIND_OPCODE_DO_BIND);
Nick Kledzikf373c772014-11-11 01:31:18 +00001255 _lazyBindingInfo.append_byte(BIND_OPCODE_DONE);
Nick Kledzike34182f2013-11-06 21:36:55 +00001256 }
Nick Kledzike34182f2013-11-06 21:36:55 +00001257 _lazyBindingInfo.align(_is64 ? 8 : 4);
1258}
1259
Pete Coopere420dd42016-01-25 21:50:54 +00001260void TrieNode::addSymbol(const Export& entry,
1261 BumpPtrAllocator &allocator,
1262 std::vector<TrieNode*> &allNodes) {
Nick Kledzik141330a2014-09-03 19:52:50 +00001263 StringRef partialStr = entry.name.drop_front(_cummulativeString.size());
1264 for (TrieEdge &edge : _children) {
1265 StringRef edgeStr = edge._subString;
1266 if (partialStr.startswith(edgeStr)) {
1267 // Already have matching edge, go down that path.
1268 edge._child->addSymbol(entry, allocator, allNodes);
1269 return;
1270 }
1271 // See if string has commmon prefix with existing edge.
1272 for (int n=edgeStr.size()-1; n > 0; --n) {
1273 if (partialStr.substr(0, n).equals(edgeStr.substr(0, n))) {
1274 // Splice in new node: was A -> C, now A -> B -> C
1275 StringRef bNodeStr = edge._child->_cummulativeString;
1276 bNodeStr = bNodeStr.drop_back(edgeStr.size()-n).copy(allocator);
Eugene Zelenko41547942015-11-10 22:37:38 +00001277 auto *bNode = new (allocator) TrieNode(bNodeStr);
Nick Kledzik141330a2014-09-03 19:52:50 +00001278 allNodes.push_back(bNode);
1279 TrieNode* cNode = edge._child;
1280 StringRef abEdgeStr = edgeStr.substr(0,n).copy(allocator);
1281 StringRef bcEdgeStr = edgeStr.substr(n).copy(allocator);
1282 DEBUG_WITH_TYPE("trie-builder", llvm::dbgs()
1283 << "splice in TrieNode('" << bNodeStr
1284 << "') between edge '"
1285 << abEdgeStr << "' and edge='"
1286 << bcEdgeStr<< "'\n");
1287 TrieEdge& abEdge = edge;
1288 abEdge._subString = abEdgeStr;
1289 abEdge._child = bNode;
Eugene Zelenko41547942015-11-10 22:37:38 +00001290 auto *bcEdge = new (allocator) TrieEdge(bcEdgeStr, cNode);
Pete Coopere420dd42016-01-25 21:50:54 +00001291 bNode->_children.insert(bNode->_children.end(), bcEdge);
Nick Kledzik141330a2014-09-03 19:52:50 +00001292 bNode->addSymbol(entry, allocator, allNodes);
1293 return;
1294 }
1295 }
1296 }
1297 if (entry.flags & EXPORT_SYMBOL_FLAGS_REEXPORT) {
1298 assert(entry.otherOffset != 0);
1299 }
1300 if (entry.flags & EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER) {
1301 assert(entry.otherOffset != 0);
1302 }
1303 // No commonality with any existing child, make a new edge.
Eugene Zelenko41547942015-11-10 22:37:38 +00001304 auto *newNode = new (allocator) TrieNode(entry.name.copy(allocator));
1305 auto *newEdge = new (allocator) TrieEdge(partialStr, newNode);
Pete Coopere420dd42016-01-25 21:50:54 +00001306 _children.insert(_children.end(), newEdge);
Nick Kledzik141330a2014-09-03 19:52:50 +00001307 DEBUG_WITH_TYPE("trie-builder", llvm::dbgs()
1308 << "new TrieNode('" << entry.name << "') with edge '"
1309 << partialStr << "' from node='"
1310 << _cummulativeString << "'\n");
1311 newNode->_address = entry.offset;
1312 newNode->_flags = entry.flags | entry.kind;
1313 newNode->_other = entry.otherOffset;
1314 if ((entry.flags & EXPORT_SYMBOL_FLAGS_REEXPORT) && !entry.otherName.empty())
1315 newNode->_importedName = entry.otherName.copy(allocator);
1316 newNode->_hasExportInfo = true;
1317 allNodes.push_back(newNode);
1318}
1319
Pete Cooperd0de3682016-08-05 21:37:12 +00001320void TrieNode::addOrderedNodes(const Export& entry,
1321 std::vector<TrieNode*> &orderedNodes) {
1322 if (!_ordered) {
1323 orderedNodes.push_back(this);
1324 _ordered = true;
1325 }
1326
1327 StringRef partialStr = entry.name.drop_front(_cummulativeString.size());
1328 for (TrieEdge &edge : _children) {
1329 StringRef edgeStr = edge._subString;
1330 if (partialStr.startswith(edgeStr)) {
1331 // Already have matching edge, go down that path.
1332 edge._child->addOrderedNodes(entry, orderedNodes);
1333 return;
1334 }
1335 }
1336}
1337
Pete Coopere420dd42016-01-25 21:50:54 +00001338bool TrieNode::updateOffset(uint32_t& offset) {
Nick Kledzik141330a2014-09-03 19:52:50 +00001339 uint32_t nodeSize = 1; // Length when no export info
1340 if (_hasExportInfo) {
1341 if (_flags & EXPORT_SYMBOL_FLAGS_REEXPORT) {
1342 nodeSize = llvm::getULEB128Size(_flags);
1343 nodeSize += llvm::getULEB128Size(_other); // Other contains ordinal.
1344 nodeSize += _importedName.size();
1345 ++nodeSize; // Trailing zero in imported name.
1346 } else {
1347 nodeSize = llvm::getULEB128Size(_flags) + llvm::getULEB128Size(_address);
1348 if (_flags & EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1349 nodeSize += llvm::getULEB128Size(_other);
1350 }
1351 // Overall node size so far is uleb128 of export info + actual export info.
1352 nodeSize += llvm::getULEB128Size(nodeSize);
1353 }
1354 // Compute size of all child edges.
1355 ++nodeSize; // Byte for number of chidren.
1356 for (TrieEdge &edge : _children) {
1357 nodeSize += edge._subString.size() + 1 // String length.
1358 + llvm::getULEB128Size(edge._child->_trieOffset); // Offset len.
1359 }
1360 // On input, 'offset' is new prefered location for this node.
1361 bool result = (_trieOffset != offset);
1362 // Store new location in node object for use by parents.
1363 _trieOffset = offset;
1364 // Update offset for next iteration.
1365 offset += nodeSize;
1366 // Return true if _trieOffset was changed.
1367 return result;
1368}
1369
Pete Coopere420dd42016-01-25 21:50:54 +00001370void TrieNode::appendToByteBuffer(ByteBuffer &out) {
Nick Kledzik141330a2014-09-03 19:52:50 +00001371 if (_hasExportInfo) {
1372 if (_flags & EXPORT_SYMBOL_FLAGS_REEXPORT) {
1373 if (!_importedName.empty()) {
1374 // nodes with re-export info: size, flags, ordinal, import-name
1375 uint32_t nodeSize = llvm::getULEB128Size(_flags)
1376 + llvm::getULEB128Size(_other)
1377 + _importedName.size() + 1;
1378 assert(nodeSize < 256);
1379 out.append_byte(nodeSize);
1380 out.append_uleb128(_flags);
1381 out.append_uleb128(_other);
1382 out.append_string(_importedName);
1383 } else {
1384 // nodes without re-export info: size, flags, ordinal, empty-string
1385 uint32_t nodeSize = llvm::getULEB128Size(_flags)
1386 + llvm::getULEB128Size(_other) + 1;
1387 assert(nodeSize < 256);
1388 out.append_byte(nodeSize);
1389 out.append_uleb128(_flags);
1390 out.append_uleb128(_other);
1391 out.append_byte(0);
1392 }
1393 } else if ( _flags & EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER ) {
1394 // Nodes with export info: size, flags, address, other
1395 uint32_t nodeSize = llvm::getULEB128Size(_flags)
1396 + llvm::getULEB128Size(_address)
1397 + llvm::getULEB128Size(_other);
1398 assert(nodeSize < 256);
1399 out.append_byte(nodeSize);
1400 out.append_uleb128(_flags);
1401 out.append_uleb128(_address);
1402 out.append_uleb128(_other);
1403 } else {
1404 // Nodes with export info: size, flags, address
1405 uint32_t nodeSize = llvm::getULEB128Size(_flags)
1406 + llvm::getULEB128Size(_address);
1407 assert(nodeSize < 256);
1408 out.append_byte(nodeSize);
1409 out.append_uleb128(_flags);
1410 out.append_uleb128(_address);
1411 }
1412 } else {
1413 // Node with no export info.
1414 uint32_t nodeSize = 0;
1415 out.append_byte(nodeSize);
1416 }
1417 // Add number of children.
1418 assert(_children.size() < 256);
1419 out.append_byte(_children.size());
1420 // Append each child edge substring and node offset.
1421 for (TrieEdge &edge : _children) {
1422 out.append_string(edge._subString);
1423 out.append_uleb128(edge._child->_trieOffset);
1424 }
1425}
1426
1427void MachOFileLayout::buildExportTrie() {
1428 if (_file.exportInfo.empty())
1429 return;
1430
1431 // For all temporary strings and objects used building trie.
1432 BumpPtrAllocator allocator;
1433
1434 // Build trie of all exported symbols.
Eugene Zelenko41547942015-11-10 22:37:38 +00001435 auto *rootNode = new (allocator) TrieNode(StringRef());
Nick Kledzik141330a2014-09-03 19:52:50 +00001436 std::vector<TrieNode*> allNodes;
1437 allNodes.reserve(_file.exportInfo.size()*2);
1438 allNodes.push_back(rootNode);
1439 for (const Export& entry : _file.exportInfo) {
1440 rootNode->addSymbol(entry, allocator, allNodes);
1441 }
1442
Pete Cooperd0de3682016-08-05 21:37:12 +00001443 std::vector<TrieNode*> orderedNodes;
1444 orderedNodes.reserve(allNodes.size());
1445
1446 for (const Export& entry : _file.exportInfo)
1447 rootNode->addOrderedNodes(entry, orderedNodes);
1448
Nick Kledzik141330a2014-09-03 19:52:50 +00001449 // Assign each node in the vector an offset in the trie stream, iterating
1450 // until all uleb128 sizes have stabilized.
1451 bool more;
1452 do {
1453 uint32_t offset = 0;
1454 more = false;
Pete Cooperd0de3682016-08-05 21:37:12 +00001455 for (TrieNode* node : orderedNodes) {
Nick Kledzik141330a2014-09-03 19:52:50 +00001456 if (node->updateOffset(offset))
1457 more = true;
1458 }
1459 } while (more);
1460
1461 // Serialize trie to ByteBuffer.
Pete Cooperd0de3682016-08-05 21:37:12 +00001462 for (TrieNode* node : orderedNodes) {
Nick Kledzik141330a2014-09-03 19:52:50 +00001463 node->appendToByteBuffer(_exportTrie);
1464 }
1465 _exportTrie.align(_is64 ? 8 : 4);
1466}
1467
Nick Kledzike34182f2013-11-06 21:36:55 +00001468void MachOFileLayout::computeSymbolTableSizes() {
1469 // MachO symbol tables have three ranges: locals, globals, and undefines
1470 const size_t nlistSize = (_is64 ? sizeof(nlist_64) : sizeof(nlist));
Lang Hames436f7d62016-07-27 22:55:30 +00001471 _symbolTableSize = nlistSize * (_file.stabsSymbols.size()
1472 + _file.localSymbols.size()
Nick Kledzike34182f2013-11-06 21:36:55 +00001473 + _file.globalSymbols.size()
1474 + _file.undefinedSymbols.size());
Pete Cooper5559b242016-08-08 23:20:04 +00001475 // Always reserve 1-byte for the empty string and 1-byte for its terminator.
1476 _symbolStringPoolSize = 2;
Lang Hames436f7d62016-07-27 22:55:30 +00001477 for (const Symbol &sym : _file.stabsSymbols) {
1478 _symbolStringPoolSize += (sym.name.size()+1);
1479 }
Nick Kledzike34182f2013-11-06 21:36:55 +00001480 for (const Symbol &sym : _file.localSymbols) {
1481 _symbolStringPoolSize += (sym.name.size()+1);
1482 }
1483 for (const Symbol &sym : _file.globalSymbols) {
1484 _symbolStringPoolSize += (sym.name.size()+1);
1485 }
1486 for (const Symbol &sym : _file.undefinedSymbols) {
1487 _symbolStringPoolSize += (sym.name.size()+1);
1488 }
1489 _symbolTableLocalsStartIndex = 0;
Lang Hames436f7d62016-07-27 22:55:30 +00001490 _symbolTableGlobalsStartIndex = _file.stabsSymbols.size() +
1491 _file.localSymbols.size();
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001492 _symbolTableUndefinesStartIndex = _symbolTableGlobalsStartIndex
Nick Kledzike34182f2013-11-06 21:36:55 +00001493 + _file.globalSymbols.size();
1494
1495 _indirectSymbolTableCount = 0;
1496 for (const Section &sect : _file.sections) {
1497 _indirectSymbolTableCount += sect.indirectSymbols.size();
1498 }
1499}
1500
Pete Cooper41f3e8e2016-02-09 01:38:13 +00001501void MachOFileLayout::computeFunctionStartsSize() {
1502 _functionStartsSize = _file.functionStarts.size();
1503}
1504
Nick Kledzik21921372014-07-24 23:06:56 +00001505void MachOFileLayout::computeDataInCodeSize() {
1506 _dataInCodeSize = _file.dataInCode.size() * sizeof(data_in_code_entry);
1507}
Nick Kledzike34182f2013-11-06 21:36:55 +00001508
1509void MachOFileLayout::writeLinkEditContent() {
1510 if (_file.fileType == llvm::MachO::MH_OBJECT) {
1511 writeRelocations();
Pete Cooper41f3e8e2016-02-09 01:38:13 +00001512 writeFunctionStartsInfo();
Nick Kledzik21921372014-07-24 23:06:56 +00001513 writeDataInCodeInfo();
Nick Kledzike34182f2013-11-06 21:36:55 +00001514 writeSymbolTable();
1515 } else {
1516 writeRebaseInfo();
1517 writeBindingInfo();
1518 writeLazyBindingInfo();
1519 // TODO: add weak binding info
Nick Kledzik141330a2014-09-03 19:52:50 +00001520 writeExportInfo();
Pete Cooper41f3e8e2016-02-09 01:38:13 +00001521 writeFunctionStartsInfo();
Nick Kledzik54ce29582014-10-28 22:21:10 +00001522 writeDataInCodeInfo();
Nick Kledzike34182f2013-11-06 21:36:55 +00001523 writeSymbolTable();
1524 }
1525}
1526
Pete Cooperfefbd222016-03-30 23:10:39 +00001527llvm::Error MachOFileLayout::writeBinary(StringRef path) {
Nick Kledzike34182f2013-11-06 21:36:55 +00001528 // Check for pending error from constructor.
1529 if (_ec)
Pete Cooperfefbd222016-03-30 23:10:39 +00001530 return llvm::errorCodeToError(_ec);
Nick Kledzike34182f2013-11-06 21:36:55 +00001531 // Create FileOutputBuffer with calculated size.
Nick Kledzike34182f2013-11-06 21:36:55 +00001532 unsigned flags = 0;
1533 if (_file.fileType != llvm::MachO::MH_OBJECT)
1534 flags = llvm::FileOutputBuffer::F_executable;
Rafael Espindolabdc8f2f2015-08-13 00:31:46 +00001535 ErrorOr<std::unique_ptr<llvm::FileOutputBuffer>> fobOrErr =
1536 llvm::FileOutputBuffer::create(path, size(), flags);
1537 if (std::error_code ec = fobOrErr.getError())
Pete Cooperfefbd222016-03-30 23:10:39 +00001538 return llvm::errorCodeToError(ec);
Rafael Espindolabdc8f2f2015-08-13 00:31:46 +00001539 std::unique_ptr<llvm::FileOutputBuffer> &fob = *fobOrErr;
Nick Kledzike34182f2013-11-06 21:36:55 +00001540 // Write content.
1541 _buffer = fob->getBufferStart();
1542 writeMachHeader();
Pete Cooper514594b2016-03-31 00:08:16 +00001543 if (auto ec = writeLoadCommands())
Pete Cooperdc59c792016-03-31 00:38:02 +00001544 return ec;
Nick Kledzike34182f2013-11-06 21:36:55 +00001545 writeSectionContent();
1546 writeLinkEditContent();
1547 fob->commit();
1548
Pete Cooperfefbd222016-03-30 23:10:39 +00001549 return llvm::Error();
Nick Kledzike34182f2013-11-06 21:36:55 +00001550}
1551
Nick Kledzike34182f2013-11-06 21:36:55 +00001552/// Takes in-memory normalized view and writes a mach-o object file.
Pete Cooperfefbd222016-03-30 23:10:39 +00001553llvm::Error writeBinary(const NormalizedFile &file, StringRef path) {
Nick Kledzike34182f2013-11-06 21:36:55 +00001554 MachOFileLayout layout(file);
1555 return layout.writeBinary(path);
1556}
1557
Nick Kledzike34182f2013-11-06 21:36:55 +00001558} // namespace normalized
1559} // namespace mach_o
1560} // namespace lld