blob: 755e9aa4fd13085aac13571218a9bb34eb1856bc [file] [log] [blame]
Nick Kledzike34182f2013-11-06 21:36:55 +00001//===- lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp ---------===//
2//
3// The LLVM Linker
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10///
Shankar Easwaran3d8de472014-01-27 03:09:26 +000011/// \file For mach-o object files, this implementation converts normalized
Nick Kledzike34182f2013-11-06 21:36:55 +000012/// mach-o in memory to mach-o binary on disk.
13///
Shankar Easwaran3d8de472014-01-27 03:09:26 +000014/// +---------------+
15/// | binary mach-o |
16/// +---------------+
Nick Kledzike34182f2013-11-06 21:36:55 +000017/// ^
18/// |
19/// |
Shankar Easwaran3d8de472014-01-27 03:09:26 +000020/// +------------+
21/// | normalized |
22/// +------------+
Nick Kledzike34182f2013-11-06 21:36:55 +000023
24#include "MachONormalizedFile.h"
25#include "MachONormalizedFileBinaryUtils.h"
Nick Kledzike34182f2013-11-06 21:36:55 +000026#include "lld/Core/Error.h"
27#include "lld/Core/LLVM.h"
Nick Kledzike34182f2013-11-06 21:36:55 +000028#include "llvm/ADT/SmallString.h"
29#include "llvm/ADT/SmallVector.h"
30#include "llvm/ADT/StringRef.h"
31#include "llvm/Support/Casting.h"
Rafael Espindola372bc702014-06-13 17:20:48 +000032#include "llvm/Support/Errc.h"
Nick Kledzike34182f2013-11-06 21:36:55 +000033#include "llvm/Support/Debug.h"
34#include "llvm/Support/ErrorHandling.h"
35#include "llvm/Support/FileOutputBuffer.h"
36#include "llvm/Support/Host.h"
Nick Kledzik00a15d92013-11-09 01:00:51 +000037#include "llvm/Support/LEB128.h"
Nick Kledzike34182f2013-11-06 21:36:55 +000038#include "llvm/Support/MachO.h"
39#include "llvm/Support/MemoryBuffer.h"
40#include "llvm/Support/raw_ostream.h"
Nick Kledzike34182f2013-11-06 21:36:55 +000041#include <functional>
42#include <map>
Rafael Espindola54427cc2014-06-12 17:15:58 +000043#include <system_error>
Nick Kledzike34182f2013-11-06 21:36:55 +000044
45using namespace llvm::MachO;
46
47namespace lld {
48namespace mach_o {
49namespace normalized {
50
51/// Utility class for writing a mach-o binary file given an in-memory
Shankar Easwaran3d8de472014-01-27 03:09:26 +000052/// normalized file.
Nick Kledzike34182f2013-11-06 21:36:55 +000053class MachOFileLayout {
54public:
Joey Goulyb275d7f2013-12-23 23:29:50 +000055 /// All layout computation is done in the constructor.
56 MachOFileLayout(const NormalizedFile &file);
57
Nick Kledzike34182f2013-11-06 21:36:55 +000058 /// Returns the final file size as computed in the constructor.
59 size_t size() const;
60
Shankar Easwaran3d8de472014-01-27 03:09:26 +000061 /// Writes the normalized file as a binary mach-o file to the specified
Nick Kledzike34182f2013-11-06 21:36:55 +000062 /// path. This does not have a stream interface because the generated
63 /// file may need the 'x' bit set.
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +000064 std::error_code writeBinary(StringRef path);
Shankar Easwaran3d8de472014-01-27 03:09:26 +000065
Nick Kledzike34182f2013-11-06 21:36:55 +000066private:
67 uint32_t loadCommandsSize(uint32_t &count);
68 void buildFileOffsets();
69 void writeMachHeader();
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +000070 std::error_code writeLoadCommands();
Nick Kledzike34182f2013-11-06 21:36:55 +000071 void writeSectionContent();
72 void writeRelocations();
73 void writeSymbolTable();
74 void writeRebaseInfo();
75 void writeBindingInfo();
76 void writeLazyBindingInfo();
77 void writeLinkEditContent();
78 void buildLinkEditInfo();
79 void buildRebaseInfo();
80 void buildBindInfo();
81 void buildLazyBindInfo();
82 void computeSymbolTableSizes();
83 void buildSectionRelocations();
84 void appendSymbols(const std::vector<Symbol> &symbols,
85 uint32_t &symOffset, uint32_t &strOffset);
86 uint32_t indirectSymbolIndex(const Section &sect, uint32_t &index);
87 uint32_t indirectSymbolElementSize(const Section &sect);
88
Nick Kledzik29f749e2013-11-09 00:07:28 +000089 // For use as template parameter to load command methods.
90 struct MachO64Trait {
91 typedef llvm::MachO::segment_command_64 command;
92 typedef llvm::MachO::section_64 section;
93 enum { LC = llvm::MachO::LC_SEGMENT_64 };
94 };
95
96 // For use as template parameter to load command methods.
97 struct MachO32Trait {
98 typedef llvm::MachO::segment_command command;
99 typedef llvm::MachO::section section;
100 enum { LC = llvm::MachO::LC_SEGMENT };
101 };
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000102
Nick Kledzik29f749e2013-11-09 00:07:28 +0000103 template <typename T>
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000104 std::error_code writeSingleSegmentLoadCommand(uint8_t *&lc);
105 template <typename T> std::error_code writeSegmentLoadCommands(uint8_t *&lc);
Nick Kledzik29f749e2013-11-09 00:07:28 +0000106
Nick Kledzike34182f2013-11-06 21:36:55 +0000107 uint32_t pointerAlign(uint32_t value);
108 static StringRef dyldPath();
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000109
Nick Kledzike34182f2013-11-06 21:36:55 +0000110 class ByteBuffer {
111 public:
Nick Kledzik00a15d92013-11-09 01:00:51 +0000112 ByteBuffer() : _ostream(_bytes) { }
113 void append_byte(uint8_t b) {
114 _ostream << b;
115 }
116 void append_uleb128(uint64_t value) {
117 llvm::encodeULEB128(value, _ostream);
118 }
119 void append_sleb128(int64_t value) {
120 llvm::encodeSLEB128(value, _ostream);
121 }
122 void append_string(StringRef str) {
123 _ostream << str;
124 append_byte(0);
125 }
126 void align(unsigned alignment) {
127 while ( (_ostream.tell() % alignment) != 0 )
128 append_byte(0);
129 }
130 size_t size() {
131 return _ostream.tell();
132 }
133 const uint8_t *bytes() {
134 return reinterpret_cast<const uint8_t*>(_ostream.str().data());
135 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000136 private:
Nick Kledzik00a15d92013-11-09 01:00:51 +0000137 SmallVector<char, 128> _bytes;
138 // Stream ivar must be after SmallVector ivar to construct properly.
139 llvm::raw_svector_ostream _ostream;
Nick Kledzike34182f2013-11-06 21:36:55 +0000140 };
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000141
Nick Kledzik00a15d92013-11-09 01:00:51 +0000142
Nick Kledzike34182f2013-11-06 21:36:55 +0000143 struct SegExtraInfo {
144 uint32_t fileOffset;
Tim Northover08d6a7b2014-06-30 09:49:30 +0000145 uint32_t fileSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000146 std::vector<const Section*> sections;
147 };
148 typedef std::map<const Segment*, SegExtraInfo> SegMap;
149 struct SectionExtraInfo {
150 uint32_t fileOffset;
151 };
152 typedef std::map<const Section*, SectionExtraInfo> SectionMap;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000153
Nick Kledzike34182f2013-11-06 21:36:55 +0000154 const NormalizedFile &_file;
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000155 std::error_code _ec;
Nick Kledzike34182f2013-11-06 21:36:55 +0000156 uint8_t *_buffer;
157 const bool _is64;
158 const bool _swap;
159 const bool _bigEndianArch;
160 uint64_t _seg1addr;
161 uint32_t _startOfLoadCommands;
162 uint32_t _countOfLoadCommands;
163 uint32_t _endOfLoadCommands;
164 uint32_t _startOfRelocations;
165 uint32_t _startOfSymbols;
166 uint32_t _startOfIndirectSymbols;
167 uint32_t _startOfSymbolStrings;
168 uint32_t _endOfSymbolStrings;
169 uint32_t _symbolTableLocalsStartIndex;
170 uint32_t _symbolTableGlobalsStartIndex;
171 uint32_t _symbolTableUndefinesStartIndex;
172 uint32_t _symbolStringPoolSize;
173 uint32_t _symbolTableSize;
174 uint32_t _indirectSymbolTableCount;
175 // Used in object file creation only
176 uint32_t _startOfSectionsContent;
177 uint32_t _endOfSectionsContent;
178 // Used in final linked image only
179 uint32_t _startOfLinkEdit;
180 uint32_t _startOfRebaseInfo;
181 uint32_t _endOfRebaseInfo;
182 uint32_t _startOfBindingInfo;
183 uint32_t _endOfBindingInfo;
184 uint32_t _startOfLazyBindingInfo;
185 uint32_t _endOfLazyBindingInfo;
186 uint32_t _endOfLinkEdit;
187 uint64_t _addressOfLinkEdit;
188 SegMap _segInfo;
189 SectionMap _sectInfo;
190 ByteBuffer _rebaseInfo;
191 ByteBuffer _bindingInfo;
192 ByteBuffer _lazyBindingInfo;
193 ByteBuffer _weakBindingInfo;
194 ByteBuffer _exportInfo;
195};
196
197size_t headerAndLoadCommandsSize(const NormalizedFile &file) {
198 MachOFileLayout layout(file);
199 return layout.size();
200}
201
202StringRef MachOFileLayout::dyldPath() {
203 return "/usr/lib/dyld";
204}
205
206uint32_t MachOFileLayout::pointerAlign(uint32_t value) {
207 return llvm::RoundUpToAlignment(value, _is64 ? 8 : 4);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000208}
Nick Kledzike34182f2013-11-06 21:36:55 +0000209
210
Nick Kledzike34182f2013-11-06 21:36:55 +0000211
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000212
213MachOFileLayout::MachOFileLayout(const NormalizedFile &file)
Nick Kledzike34182f2013-11-06 21:36:55 +0000214 : _file(file),
215 _is64(MachOLinkingContext::is64Bit(file.arch)),
216 _swap(!MachOLinkingContext::isHostEndian(file.arch)),
217 _bigEndianArch(MachOLinkingContext::isBigEndian(file.arch)),
218 _seg1addr(INT64_MAX) {
219 _startOfLoadCommands = _is64 ? sizeof(mach_header_64) : sizeof(mach_header);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000220 const size_t segCommandBaseSize =
Nick Kledzike34182f2013-11-06 21:36:55 +0000221 (_is64 ? sizeof(segment_command_64) : sizeof(segment_command));
222 const size_t sectsSize = (_is64 ? sizeof(section_64) : sizeof(section));
223 if (file.fileType == llvm::MachO::MH_OBJECT) {
224 // object files have just one segment load command containing all sections
225 _endOfLoadCommands = _startOfLoadCommands
226 + segCommandBaseSize
227 + file.sections.size() * sectsSize
228 + sizeof(symtab_command);
229 _countOfLoadCommands = 2;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000230
Nick Kledzike34182f2013-11-06 21:36:55 +0000231 // Accumulate size of each section.
232 _startOfSectionsContent = _endOfLoadCommands;
233 _endOfSectionsContent = _startOfSectionsContent;
234 unsigned relocCount = 0;
235 for (const Section &sect : file.sections) {
236 _sectInfo[&sect].fileOffset = _endOfSectionsContent;
237 _endOfSectionsContent += sect.content.size();
238 relocCount += sect.relocations.size();
239 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000240
Nick Kledzike34182f2013-11-06 21:36:55 +0000241 computeSymbolTableSizes();
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000242
Nick Kledzike34182f2013-11-06 21:36:55 +0000243 // Align start of relocations.
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000244 _startOfRelocations = pointerAlign(_endOfSectionsContent);
Nick Kledzike34182f2013-11-06 21:36:55 +0000245 _startOfSymbols = _startOfRelocations + relocCount * 8;
246 // Add Indirect symbol table.
247 _startOfIndirectSymbols = _startOfSymbols + _symbolTableSize;
248 // Align start of symbol table and symbol strings.
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000249 _startOfSymbolStrings = _startOfIndirectSymbols
Nick Kledzike34182f2013-11-06 21:36:55 +0000250 + pointerAlign(_indirectSymbolTableCount * sizeof(uint32_t));
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000251 _endOfSymbolStrings = _startOfSymbolStrings
Nick Kledzike34182f2013-11-06 21:36:55 +0000252 + pointerAlign(_symbolStringPoolSize);
253 _endOfLinkEdit = _endOfSymbolStrings;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000254 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000255 llvm::dbgs() << "MachOFileLayout()\n"
256 << " startOfLoadCommands=" << _startOfLoadCommands << "\n"
257 << " countOfLoadCommands=" << _countOfLoadCommands << "\n"
258 << " endOfLoadCommands=" << _endOfLoadCommands << "\n"
259 << " startOfRelocations=" << _startOfRelocations << "\n"
260 << " startOfSymbols=" << _startOfSymbols << "\n"
261 << " startOfSymbolStrings=" << _startOfSymbolStrings << "\n"
262 << " endOfSymbolStrings=" << _endOfSymbolStrings << "\n"
263 << " startOfSectionsContent=" << _startOfSectionsContent << "\n"
264 << " endOfSectionsContent=" << _endOfSectionsContent << "\n");
265 } else {
266 // Final linked images have one load command per segment.
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000267 _endOfLoadCommands = _startOfLoadCommands
Nick Kledzike34182f2013-11-06 21:36:55 +0000268 + loadCommandsSize(_countOfLoadCommands);
269
270 // Assign section file offsets.
271 buildFileOffsets();
272 buildLinkEditInfo();
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000273
Nick Kledzike34182f2013-11-06 21:36:55 +0000274 // LINKEDIT of final linked images has in order:
275 // rebase info, binding info, lazy binding info, weak binding info,
276 // indirect symbol table, symbol table, symbol table strings.
277 _startOfRebaseInfo = _startOfLinkEdit;
278 _endOfRebaseInfo = _startOfRebaseInfo + _rebaseInfo.size();
279 _startOfBindingInfo = _endOfRebaseInfo;
280 _endOfBindingInfo = _startOfBindingInfo + _bindingInfo.size();
281 _startOfLazyBindingInfo = _endOfBindingInfo;
282 _endOfLazyBindingInfo = _startOfLazyBindingInfo + _lazyBindingInfo.size();
283
284 _startOfSymbols = _endOfLazyBindingInfo;
285 _startOfIndirectSymbols = _startOfSymbols + _symbolTableSize;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000286 _startOfSymbolStrings = _startOfIndirectSymbols
Nick Kledzike34182f2013-11-06 21:36:55 +0000287 + pointerAlign(_indirectSymbolTableCount * sizeof(uint32_t));
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000288 _endOfSymbolStrings = _startOfSymbolStrings
Nick Kledzike34182f2013-11-06 21:36:55 +0000289 + pointerAlign(_symbolStringPoolSize);
290 _endOfLinkEdit = _endOfSymbolStrings;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000291 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000292 llvm::dbgs() << "MachOFileLayout()\n"
293 << " startOfLoadCommands=" << _startOfLoadCommands << "\n"
294 << " countOfLoadCommands=" << _countOfLoadCommands << "\n"
295 << " endOfLoadCommands=" << _endOfLoadCommands << "\n"
296 << " startOfLinkEdit=" << _startOfLinkEdit << "\n"
297 << " startOfRebaseInfo=" << _startOfRebaseInfo << "\n"
298 << " endOfRebaseInfo=" << _endOfRebaseInfo << "\n"
299 << " startOfBindingInfo=" << _startOfBindingInfo << "\n"
300 << " endOfBindingInfo=" << _endOfBindingInfo << "\n"
301 << " startOfLazyBindingInfo=" << _startOfLazyBindingInfo << "\n"
302 << " endOfLazyBindingInfo=" << _endOfLazyBindingInfo << "\n"
303 << " startOfSymbols=" << _startOfSymbols << "\n"
304 << " startOfSymbolStrings=" << _startOfSymbolStrings << "\n"
305 << " endOfSymbolStrings=" << _endOfSymbolStrings << "\n"
306 << " addressOfLinkEdit=" << _addressOfLinkEdit << "\n");
307 }
308}
309
310uint32_t MachOFileLayout::loadCommandsSize(uint32_t &count) {
311 uint32_t size = 0;
312 count = 0;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000313
314 const size_t segCommandSize =
Nick Kledzike34182f2013-11-06 21:36:55 +0000315 (_is64 ? sizeof(segment_command_64) : sizeof(segment_command));
316 const size_t sectionSize = (_is64 ? sizeof(section_64) : sizeof(section));
317
318 // Add LC_SEGMENT for each segment.
319 size += _file.segments.size() * segCommandSize;
320 count += _file.segments.size();
321 // Add section record for each section.
322 size += _file.sections.size() * sectionSize;
323 // Add one LC_SEGMENT for implicit __LINKEDIT segment
324 size += segCommandSize;
325 ++count;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000326
Tim Northover301c4e62014-07-01 08:15:41 +0000327 // If creating a dylib, add LC_ID_DYLIB.
328 if (_file.fileType == llvm::MachO::MH_DYLIB) {
329 size += sizeof(dylib_command) + pointerAlign(_file.installName.size() + 1);
330 ++count;
331 }
332
Nick Kledzike34182f2013-11-06 21:36:55 +0000333 // Add LC_DYLD_INFO
334 size += sizeof(dyld_info_command);
335 ++count;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000336
Nick Kledzike34182f2013-11-06 21:36:55 +0000337 // Add LC_SYMTAB
338 size += sizeof(symtab_command);
339 ++count;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000340
Nick Kledzike34182f2013-11-06 21:36:55 +0000341 // Add LC_DYSYMTAB
342 if (_file.fileType != llvm::MachO::MH_PRELOAD) {
343 size += sizeof(dysymtab_command);
344 ++count;
345 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000346
Nick Kledzike34182f2013-11-06 21:36:55 +0000347 // If main executable add LC_LOAD_DYLINKER and LC_MAIN
348 if (_file.fileType == llvm::MachO::MH_EXECUTE) {
349 size += pointerAlign(sizeof(dylinker_command) + dyldPath().size()+1);
350 ++count;
351 size += sizeof(entry_point_command);
352 ++count;
353 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000354
Nick Kledzike34182f2013-11-06 21:36:55 +0000355 // Add LC_LOAD_DYLIB for each dependent dylib.
356 for (const DependentDylib &dep : _file.dependentDylibs) {
357 size += sizeof(dylib_command) + pointerAlign(dep.path.size()+1);
358 ++count;
359 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000360
Nick Kledzike34182f2013-11-06 21:36:55 +0000361 return size;
362}
363
364static bool overlaps(const Segment &s1, const Segment &s2) {
365 if (s2.address >= s1.address+s1.size)
366 return false;
367 if (s1.address >= s2.address+s2.size)
368 return false;
369 return true;
370}
371
372static bool overlaps(const Section &s1, const Section &s2) {
373 if (s2.address >= s1.address+s1.content.size())
374 return false;
375 if (s1.address >= s2.address+s2.content.size())
376 return false;
377 return true;
378}
379
380void MachOFileLayout::buildFileOffsets() {
381 // Verify no segments overlap
382 for (const Segment &sg1 : _file.segments) {
383 for (const Segment &sg2 : _file.segments) {
384 if (&sg1 == &sg2)
385 continue;
386 if (overlaps(sg1,sg2)) {
Rafael Espindola372bc702014-06-13 17:20:48 +0000387 _ec = make_error_code(llvm::errc::executable_format_error);
Nick Kledzike34182f2013-11-06 21:36:55 +0000388 return;
389 }
390 }
391 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000392
393 // Verify no sections overlap
Nick Kledzike34182f2013-11-06 21:36:55 +0000394 for (const Section &s1 : _file.sections) {
395 for (const Section &s2 : _file.sections) {
396 if (&s1 == &s2)
397 continue;
398 if (overlaps(s1,s2)) {
Rafael Espindola372bc702014-06-13 17:20:48 +0000399 _ec = make_error_code(llvm::errc::executable_format_error);
Nick Kledzike34182f2013-11-06 21:36:55 +0000400 return;
401 }
402 }
403 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000404
Nick Kledzike34182f2013-11-06 21:36:55 +0000405 // Build side table of extra info about segments and sections.
406 SegExtraInfo t;
407 t.fileOffset = 0;
408 for (const Segment &sg : _file.segments) {
409 _segInfo[&sg] = t;
410 }
411 SectionExtraInfo t2;
412 t2.fileOffset = 0;
413 // Assign sections to segments.
414 for (const Section &s : _file.sections) {
415 _sectInfo[&s] = t2;
416 for (const Segment &sg : _file.segments) {
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000417 if ((s.address >= sg.address)
Nick Kledzike34182f2013-11-06 21:36:55 +0000418 && (s.address+s.content.size() <= sg.address+sg.size)) {
419 if (!sg.name.equals(s.segmentName)) {
Rafael Espindola372bc702014-06-13 17:20:48 +0000420 _ec = make_error_code(llvm::errc::executable_format_error);
Nick Kledzike34182f2013-11-06 21:36:55 +0000421 return;
422 }
423 _segInfo[&sg].sections.push_back(&s);
424 }
425 }
426 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000427
Nick Kledzike34182f2013-11-06 21:36:55 +0000428 // Assign file offsets.
429 uint32_t fileOffset = 0;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000430 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000431 llvm::dbgs() << "buildFileOffsets()\n");
432 for (const Segment &sg : _file.segments) {
Tim Northover08d6a7b2014-06-30 09:49:30 +0000433 _segInfo[&sg].fileOffset = fileOffset;
Nick Kledzike34182f2013-11-06 21:36:55 +0000434 if ((_seg1addr == INT64_MAX) && sg.access)
435 _seg1addr = sg.address;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000436 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000437 llvm::dbgs() << " segment=" << sg.name
438 << ", fileOffset=" << _segInfo[&sg].fileOffset << "\n");
Tim Northover08d6a7b2014-06-30 09:49:30 +0000439
440 uint32_t segFileSize = 0;
Nick Kledzike34182f2013-11-06 21:36:55 +0000441 for (const Section *s : _segInfo[&sg].sections) {
Tim Northover08d6a7b2014-06-30 09:49:30 +0000442 uint32_t sectOffset = s->address - sg.address;
443 uint32_t sectFileSize =
444 s->type == llvm::MachO::S_ZEROFILL ? 0 : s->content.size();
445 segFileSize = std::max(segFileSize, sectOffset + sectFileSize);
446
447 _sectInfo[s].fileOffset = _segInfo[&sg].fileOffset + sectOffset;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000448 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000449 llvm::dbgs() << " section=" << s->sectionName
450 << ", fileOffset=" << fileOffset << "\n");
451 }
Tim Northover08d6a7b2014-06-30 09:49:30 +0000452
453 // FIXME: 4096 should be inferred from segments in normalized file.
454 _segInfo[&sg].fileSize = llvm::RoundUpToAlignment(segFileSize, 4096);
455 fileOffset = llvm::RoundUpToAlignment(fileOffset + segFileSize, 4096);
Nick Kledzike34182f2013-11-06 21:36:55 +0000456 _addressOfLinkEdit = sg.address + sg.size;
457 }
Tim Northover08d6a7b2014-06-30 09:49:30 +0000458 _startOfLinkEdit = fileOffset;
Nick Kledzike34182f2013-11-06 21:36:55 +0000459}
460
461
462size_t MachOFileLayout::size() const {
463 return _endOfSymbolStrings;
464}
465
466void MachOFileLayout::writeMachHeader() {
467 mach_header *mh = reinterpret_cast<mach_header*>(_buffer);
468 mh->magic = _is64 ? llvm::MachO::MH_MAGIC_64 : llvm::MachO::MH_MAGIC;
469 mh->cputype = MachOLinkingContext::cpuTypeFromArch(_file.arch);
470 mh->cpusubtype = MachOLinkingContext::cpuSubtypeFromArch(_file.arch);
471 mh->filetype = _file.fileType;
472 mh->ncmds = _countOfLoadCommands;
473 mh->sizeofcmds = _endOfLoadCommands - _startOfLoadCommands;
474 mh->flags = _file.flags;
475 if (_swap)
476 swapStruct(*mh);
477}
478
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000479uint32_t MachOFileLayout::indirectSymbolIndex(const Section &sect,
Nick Kledzike34182f2013-11-06 21:36:55 +0000480 uint32_t &index) {
481 if (sect.indirectSymbols.empty())
482 return 0;
483 uint32_t result = index;
484 index += sect.indirectSymbols.size();
485 return result;
486}
487
488uint32_t MachOFileLayout::indirectSymbolElementSize(const Section &sect) {
489 if (sect.indirectSymbols.empty())
490 return 0;
491 if (sect.type != S_SYMBOL_STUBS)
492 return 0;
493 return sect.content.size() / sect.indirectSymbols.size();
494}
495
Nick Kledzik29f749e2013-11-09 00:07:28 +0000496template <typename T>
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000497std::error_code MachOFileLayout::writeSingleSegmentLoadCommand(uint8_t *&lc) {
Nick Kledzik29f749e2013-11-09 00:07:28 +0000498 typename T::command* seg = reinterpret_cast<typename T::command*>(lc);
499 seg->cmd = T::LC;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000500 seg->cmdsize = sizeof(typename T::command)
Nick Kledzik29f749e2013-11-09 00:07:28 +0000501 + _file.sections.size() * sizeof(typename T::section);
Nick Kledzike34182f2013-11-06 21:36:55 +0000502 uint8_t *next = lc + seg->cmdsize;
503 memset(seg->segname, 0, 16);
504 seg->vmaddr = 0;
505 seg->vmsize = _endOfSectionsContent - _endOfLoadCommands;
506 seg->fileoff = _endOfLoadCommands;
507 seg->filesize = seg->vmsize;
508 seg->maxprot = VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE;
509 seg->initprot = VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE;
510 seg->nsects = _file.sections.size();
511 seg->flags = 0;
512 if (_swap)
513 swapStruct(*seg);
Nick Kledzik29f749e2013-11-09 00:07:28 +0000514 typename T::section *sout = reinterpret_cast<typename T::section*>
515 (lc+sizeof(typename T::command));
Nick Kledzike34182f2013-11-06 21:36:55 +0000516 uint32_t relOffset = _startOfRelocations;
517 uint32_t contentOffset = _startOfSectionsContent;
518 uint32_t indirectSymRunningIndex = 0;
519 for (const Section &sin : _file.sections) {
520 setString16(sin.sectionName, sout->sectname);
521 setString16(sin.segmentName, sout->segname);
522 sout->addr = sin.address;
523 sout->size = sin.content.size();
524 sout->offset = contentOffset;
525 sout->align = sin.alignment;
526 sout->reloff = sin.relocations.empty() ? 0 : relOffset;
527 sout->nreloc = sin.relocations.size();
528 sout->flags = sin.type | sin.attributes;
529 sout->reserved1 = indirectSymbolIndex(sin, indirectSymRunningIndex);
530 sout->reserved2 = indirectSymbolElementSize(sin);
531 relOffset += sin.relocations.size() * sizeof(any_relocation_info);
532 contentOffset += sin.content.size();
533 if (_swap)
534 swapStruct(*sout);
535 ++sout;
536 }
537 lc = next;
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000538 return std::error_code();
Nick Kledzike34182f2013-11-06 21:36:55 +0000539}
540
Nick Kledzik29f749e2013-11-09 00:07:28 +0000541template <typename T>
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000542std::error_code MachOFileLayout::writeSegmentLoadCommands(uint8_t *&lc) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000543 uint32_t indirectSymRunningIndex = 0;
544 for (const Segment &seg : _file.segments) {
545 // Write segment command with trailing sections.
546 SegExtraInfo &segInfo = _segInfo[&seg];
Nick Kledzik29f749e2013-11-09 00:07:28 +0000547 typename T::command* cmd = reinterpret_cast<typename T::command*>(lc);
548 cmd->cmd = T::LC;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000549 cmd->cmdsize = sizeof(typename T::command)
Nick Kledzik29f749e2013-11-09 00:07:28 +0000550 + segInfo.sections.size() * sizeof(typename T::section);
Nick Kledzike34182f2013-11-06 21:36:55 +0000551 uint8_t *next = lc + cmd->cmdsize;
552 setString16(seg.name, cmd->segname);
553 cmd->vmaddr = seg.address;
554 cmd->vmsize = seg.size;
555 cmd->fileoff = segInfo.fileOffset;
Tim Northover08d6a7b2014-06-30 09:49:30 +0000556 cmd->filesize = segInfo.fileSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000557 cmd->maxprot = seg.access;
558 cmd->initprot = seg.access;
559 cmd->nsects = segInfo.sections.size();
560 cmd->flags = 0;
561 if (_swap)
562 swapStruct(*cmd);
Nick Kledzik29f749e2013-11-09 00:07:28 +0000563 typename T::section *sect = reinterpret_cast<typename T::section*>
564 (lc+sizeof(typename T::command));
Nick Kledzike34182f2013-11-06 21:36:55 +0000565 for (const Section *section : segInfo.sections) {
566 setString16(section->sectionName, sect->sectname);
567 setString16(section->segmentName, sect->segname);
568 sect->addr = section->address;
569 sect->size = section->content.size();
570 sect->offset = section->address - seg.address + segInfo.fileOffset;
571 sect->align = section->alignment;
572 sect->reloff = 0;
573 sect->nreloc = 0;
574 sect->flags = section->type | section->attributes;
575 sect->reserved1 = indirectSymbolIndex(*section, indirectSymRunningIndex);
576 sect->reserved2 = indirectSymbolElementSize(*section);
577 if (_swap)
578 swapStruct(*sect);
579 ++sect;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000580 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000581 lc = reinterpret_cast<uint8_t*>(next);
582 }
583 // Add implicit __LINKEDIT segment
Nick Kledzik29f749e2013-11-09 00:07:28 +0000584 typename T::command* cmd = reinterpret_cast<typename T::command*>(lc);
585 cmd->cmd = T::LC;
586 cmd->cmdsize = sizeof(typename T::command);
Nick Kledzike34182f2013-11-06 21:36:55 +0000587 uint8_t *next = lc + cmd->cmdsize;
588 setString16("__LINKEDIT", cmd->segname);
589 cmd->vmaddr = _addressOfLinkEdit;
590 cmd->vmsize = _endOfLinkEdit - _startOfLinkEdit;
591 cmd->fileoff = _startOfLinkEdit;
592 cmd->filesize = _endOfLinkEdit - _startOfLinkEdit;
593 cmd->maxprot = VM_PROT_READ;
594 cmd->initprot = VM_PROT_READ;
595 cmd->nsects = 0;
596 cmd->flags = 0;
597 if (_swap)
598 swapStruct(*cmd);
599 lc = next;
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000600 return std::error_code();
Nick Kledzike34182f2013-11-06 21:36:55 +0000601}
602
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000603std::error_code MachOFileLayout::writeLoadCommands() {
604 std::error_code ec;
Nick Kledzike34182f2013-11-06 21:36:55 +0000605 uint8_t *lc = &_buffer[_startOfLoadCommands];
606 if (_file.fileType == llvm::MachO::MH_OBJECT) {
607 // Object files have one unnamed segment which holds all sections.
608 if (_is64)
Nick Kledzik29f749e2013-11-09 00:07:28 +0000609 ec = writeSingleSegmentLoadCommand<MachO64Trait>(lc);
Nick Kledzike34182f2013-11-06 21:36:55 +0000610 else
Nick Kledzik29f749e2013-11-09 00:07:28 +0000611 ec = writeSingleSegmentLoadCommand<MachO32Trait>(lc);
Nick Kledzike34182f2013-11-06 21:36:55 +0000612 // Add LC_SYMTAB with symbol table info
613 symtab_command* st = reinterpret_cast<symtab_command*>(lc);
614 st->cmd = LC_SYMTAB;
615 st->cmdsize = sizeof(symtab_command);
616 st->symoff = _startOfSymbols;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000617 st->nsyms = _file.localSymbols.size() + _file.globalSymbols.size()
Nick Kledzike34182f2013-11-06 21:36:55 +0000618 + _file.undefinedSymbols.size();
619 st->stroff = _startOfSymbolStrings;
620 st->strsize = _endOfSymbolStrings - _startOfSymbolStrings;
621 if (_swap)
622 swapStruct(*st);
623 } else {
624 // Final linked images have sections under segments.
625 if (_is64)
Nick Kledzik29f749e2013-11-09 00:07:28 +0000626 ec = writeSegmentLoadCommands<MachO64Trait>(lc);
Nick Kledzike34182f2013-11-06 21:36:55 +0000627 else
Nick Kledzik29f749e2013-11-09 00:07:28 +0000628 ec = writeSegmentLoadCommands<MachO32Trait>(lc);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000629
Tim Northover301c4e62014-07-01 08:15:41 +0000630 // Add LC_ID_DYLIB command for dynamic libraries.
631 if (_file.fileType == llvm::MachO::MH_DYLIB) {
632 dylib_command *dc = reinterpret_cast<dylib_command*>(lc);
633 StringRef path = _file.installName;
634 uint32_t size = sizeof(dylib_command) + pointerAlign(path.size() + 1);
635 dc->cmd = LC_ID_DYLIB;
636 dc->cmdsize = size;
637 dc->dylib.name = sizeof(dylib_command); // offset
638 dc->dylib.timestamp = 0; // FIXME
639 dc->dylib.current_version = 0; // FIXME
640 dc->dylib.compatibility_version = 0; // FIXME
641 if (_swap)
642 swapStruct(*dc);
643 memcpy(lc + sizeof(dylib_command), path.begin(), path.size());
644 lc[sizeof(dylib_command) + path.size()] = '\0';
645 lc += size;
646 }
647
Nick Kledzike34182f2013-11-06 21:36:55 +0000648 // Add LC_DYLD_INFO_ONLY.
649 dyld_info_command* di = reinterpret_cast<dyld_info_command*>(lc);
650 di->cmd = LC_DYLD_INFO_ONLY;
651 di->cmdsize = sizeof(dyld_info_command);
652 di->rebase_off = _rebaseInfo.size() ? _startOfRebaseInfo : 0;
653 di->rebase_size = _rebaseInfo.size();
654 di->bind_off = _bindingInfo.size() ? _startOfBindingInfo : 0;
655 di->bind_size = _bindingInfo.size();
656 di->weak_bind_off = 0;
657 di->weak_bind_size = 0;
658 di->lazy_bind_off = _lazyBindingInfo.size() ? _startOfLazyBindingInfo : 0;
659 di->lazy_bind_size = _lazyBindingInfo.size();
660 di->export_off = 0;
661 di->export_size = 0;
662 if (_swap)
663 swapStruct(*di);
664 lc += sizeof(dyld_info_command);
665
666 // Add LC_SYMTAB with symbol table info.
667 symtab_command* st = reinterpret_cast<symtab_command*>(lc);
668 st->cmd = LC_SYMTAB;
669 st->cmdsize = sizeof(symtab_command);
670 st->symoff = _startOfSymbols;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000671 st->nsyms = _file.localSymbols.size() + _file.globalSymbols.size()
Nick Kledzike34182f2013-11-06 21:36:55 +0000672 + _file.undefinedSymbols.size();
673 st->stroff = _startOfSymbolStrings;
674 st->strsize = _endOfSymbolStrings - _startOfSymbolStrings;
675 if (_swap)
676 swapStruct(*st);
677 lc += sizeof(symtab_command);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000678
Nick Kledzike34182f2013-11-06 21:36:55 +0000679 // Add LC_DYSYMTAB
680 if (_file.fileType != llvm::MachO::MH_PRELOAD) {
681 dysymtab_command* dst = reinterpret_cast<dysymtab_command*>(lc);
682 dst->cmd = LC_DYSYMTAB;
683 dst->cmdsize = sizeof(dysymtab_command);
684 dst->ilocalsym = _symbolTableLocalsStartIndex;
685 dst->nlocalsym = _file.localSymbols.size();
686 dst->iextdefsym = _symbolTableGlobalsStartIndex;
687 dst->nextdefsym = _file.globalSymbols.size();
688 dst->iundefsym = _symbolTableUndefinesStartIndex;
689 dst->nundefsym = _file.undefinedSymbols.size();
690 dst->tocoff = 0;
691 dst->ntoc = 0;
692 dst->modtaboff = 0;
693 dst->nmodtab = 0;
694 dst->extrefsymoff = 0;
695 dst->nextrefsyms = 0;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000696 dst->indirectsymoff = _startOfIndirectSymbols;
Nick Kledzike34182f2013-11-06 21:36:55 +0000697 dst->nindirectsyms = _indirectSymbolTableCount;
698 dst->extreloff = 0;
699 dst->nextrel = 0;
700 dst->locreloff = 0;
701 dst->nlocrel = 0;
702 if (_swap)
703 swapStruct(*dst);
704 lc += sizeof(dysymtab_command);
705 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000706
Nick Kledzike34182f2013-11-06 21:36:55 +0000707 // If main executable, add LC_LOAD_DYLINKER and LC_MAIN.
708 if (_file.fileType == llvm::MachO::MH_EXECUTE) {
709 // Build LC_LOAD_DYLINKER load command.
710 uint32_t size=pointerAlign(sizeof(dylinker_command)+dyldPath().size()+1);
711 dylinker_command* dl = reinterpret_cast<dylinker_command*>(lc);
712 dl->cmd = LC_LOAD_DYLINKER;
713 dl->cmdsize = size;
714 dl->name = sizeof(dylinker_command); // offset
715 if (_swap)
716 swapStruct(*dl);
717 memcpy(lc+sizeof(dylinker_command), dyldPath().data(), dyldPath().size());
718 lc[sizeof(dylinker_command)+dyldPath().size()] = '\0';
719 lc += size;
720 // Build LC_MAIN load command.
721 entry_point_command* ep = reinterpret_cast<entry_point_command*>(lc);
722 ep->cmd = LC_MAIN;
723 ep->cmdsize = sizeof(entry_point_command);
724 ep->entryoff = _file.entryAddress - _seg1addr;
725 ep->stacksize = 0;
726 if (_swap)
727 swapStruct(*ep);
728 lc += sizeof(entry_point_command);
729 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000730
Nick Kledzike34182f2013-11-06 21:36:55 +0000731 // Add LC_LOAD_DYLIB commands
732 for (const DependentDylib &dep : _file.dependentDylibs) {
733 dylib_command* dc = reinterpret_cast<dylib_command*>(lc);
734 uint32_t size = sizeof(dylib_command) + pointerAlign(dep.path.size()+1);
735 dc->cmd = LC_LOAD_DYLIB;
736 dc->cmdsize = size;
737 dc->dylib.name = sizeof(dylib_command); // offset
738 dc->dylib.timestamp = 0; // FIXME
739 dc->dylib.current_version = 0; // FIXME
740 dc->dylib.compatibility_version = 0; // FIXME
741 if (_swap)
742 swapStruct(*dc);
743 memcpy(lc+sizeof(dylib_command), dep.path.begin(), dep.path.size());
744 lc[sizeof(dylib_command)+dep.path.size()] = '\0';
745 lc += size;
746 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000747 }
748 return ec;
749}
750
751
752void MachOFileLayout::writeSectionContent() {
753 for (const Section &s : _file.sections) {
754 // Copy all section content to output buffer.
Nick Kledzik61fdef62014-05-15 20:59:23 +0000755 if (s.type == llvm::MachO::S_ZEROFILL)
756 continue;
Nick Kledzike34182f2013-11-06 21:36:55 +0000757 uint32_t offset = _sectInfo[&s].fileOffset;
758 uint8_t *p = &_buffer[offset];
759 memcpy(p, &s.content[0], s.content.size());
760 p += s.content.size();
761 }
762}
763
764void MachOFileLayout::writeRelocations() {
765 uint32_t relOffset = _startOfRelocations;
766 for (Section sect : _file.sections) {
767 for (Relocation r : sect.relocations) {
768 any_relocation_info* rb = reinterpret_cast<any_relocation_info*>(
769 &_buffer[relOffset]);
770 *rb = packRelocation(r, _swap, _bigEndianArch);
771 relOffset += sizeof(any_relocation_info);
772 }
773 }
774}
775
776
777void MachOFileLayout::appendSymbols(const std::vector<Symbol> &symbols,
778 uint32_t &symOffset, uint32_t &strOffset) {
779 for (const Symbol &sym : symbols) {
780 if (_is64) {
781 nlist_64* nb = reinterpret_cast<nlist_64*>(&_buffer[symOffset]);
782 nb->n_strx = strOffset - _startOfSymbolStrings;
783 nb->n_type = sym.type | sym.scope;
784 nb->n_sect = sym.sect;
785 nb->n_desc = sym.desc;
786 nb->n_value = sym.value;
787 if (_swap)
788 swapStruct(*nb);
789 symOffset += sizeof(nlist_64);
790 } else {
791 nlist* nb = reinterpret_cast<nlist*>(&_buffer[symOffset]);
792 nb->n_strx = strOffset - _startOfSymbolStrings;
793 nb->n_type = sym.type | sym.scope;
794 nb->n_sect = sym.sect;
795 nb->n_desc = sym.desc;
796 nb->n_value = sym.value;
797 if (_swap)
798 swapStruct(*nb);
799 symOffset += sizeof(nlist);
800 }
801 memcpy(&_buffer[strOffset], sym.name.begin(), sym.name.size());
802 strOffset += sym.name.size();
803 _buffer[strOffset++] ='\0'; // Strings in table have nul terminator.
804 }
805}
806
807void MachOFileLayout::writeSymbolTable() {
808 // Write symbol table and symbol strings in parallel.
809 uint32_t symOffset = _startOfSymbols;
810 uint32_t strOffset = _startOfSymbolStrings;
811 _buffer[strOffset++] = '\0'; // Reserve n_strx offset of zero to mean no name.
812 appendSymbols(_file.localSymbols, symOffset, strOffset);
813 appendSymbols(_file.globalSymbols, symOffset, strOffset);
814 appendSymbols(_file.undefinedSymbols, symOffset, strOffset);
815 // Write indirect symbol table array.
816 uint32_t *indirects = reinterpret_cast<uint32_t*>
817 (&_buffer[_startOfIndirectSymbols]);
818 if (_file.fileType == llvm::MachO::MH_OBJECT) {
819 // Object files have sections in same order as input normalized file.
820 for (const Section &section : _file.sections) {
821 for (uint32_t index : section.indirectSymbols) {
822 if (_swap)
Artyom Skrobov17587fb2014-06-14 12:40:04 +0000823 *indirects++ = llvm::sys::getSwappedBytes(index);
Nick Kledzike34182f2013-11-06 21:36:55 +0000824 else
825 *indirects++ = index;
826 }
827 }
828 } else {
829 // Final linked images must sort sections from normalized file.
830 for (const Segment &seg : _file.segments) {
831 SegExtraInfo &segInfo = _segInfo[&seg];
832 for (const Section *section : segInfo.sections) {
833 for (uint32_t index : section->indirectSymbols) {
834 if (_swap)
Artyom Skrobov17587fb2014-06-14 12:40:04 +0000835 *indirects++ = llvm::sys::getSwappedBytes(index);
Nick Kledzike34182f2013-11-06 21:36:55 +0000836 else
837 *indirects++ = index;
838 }
839 }
840 }
841 }
842}
843
844void MachOFileLayout::writeRebaseInfo() {
845 memcpy(&_buffer[_startOfRebaseInfo], _rebaseInfo.bytes(), _rebaseInfo.size());
846}
847
848void MachOFileLayout::writeBindingInfo() {
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000849 memcpy(&_buffer[_startOfBindingInfo],
Nick Kledzike34182f2013-11-06 21:36:55 +0000850 _bindingInfo.bytes(), _bindingInfo.size());
851}
852
853void MachOFileLayout::writeLazyBindingInfo() {
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000854 memcpy(&_buffer[_startOfLazyBindingInfo],
Nick Kledzike34182f2013-11-06 21:36:55 +0000855 _lazyBindingInfo.bytes(), _lazyBindingInfo.size());
856}
857
858void MachOFileLayout::buildLinkEditInfo() {
859 buildRebaseInfo();
860 buildBindInfo();
861 buildLazyBindInfo();
862 computeSymbolTableSizes();
863}
864
865void MachOFileLayout::buildSectionRelocations() {
866
867}
868
869void MachOFileLayout::buildRebaseInfo() {
870 // TODO: compress rebasing info.
871 for (const RebaseLocation& entry : _file.rebasingInfo) {
872 _rebaseInfo.append_byte(REBASE_OPCODE_SET_TYPE_IMM | entry.kind);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000873 _rebaseInfo.append_byte(REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
Nick Kledzike34182f2013-11-06 21:36:55 +0000874 | entry.segIndex);
875 _rebaseInfo.append_uleb128(entry.segOffset);
876 _rebaseInfo.append_uleb128(REBASE_OPCODE_DO_REBASE_IMM_TIMES | 1);
877 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000878 _rebaseInfo.append_byte(REBASE_OPCODE_DONE);
Nick Kledzike34182f2013-11-06 21:36:55 +0000879 _rebaseInfo.align(_is64 ? 8 : 4);
880}
881
882void MachOFileLayout::buildBindInfo() {
883 // TODO: compress bind info.
884 for (const BindLocation& entry : _file.bindingInfo) {
885 _bindingInfo.append_byte(BIND_OPCODE_SET_TYPE_IMM | entry.kind);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000886 _bindingInfo.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
Nick Kledzike34182f2013-11-06 21:36:55 +0000887 | entry.segIndex);
888 _bindingInfo.append_uleb128(entry.segOffset);
889 _bindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM | entry.ordinal);
890 _bindingInfo.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM);
891 _bindingInfo.append_string(entry.symbolName);
892 if (entry.addend != 0) {
893 _bindingInfo.append_byte(BIND_OPCODE_SET_ADDEND_SLEB);
894 _bindingInfo.append_sleb128(entry.addend);
895 }
896 _bindingInfo.append_byte(BIND_OPCODE_DO_BIND);
897 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000898 _bindingInfo.append_byte(BIND_OPCODE_DONE);
Nick Kledzike34182f2013-11-06 21:36:55 +0000899 _bindingInfo.align(_is64 ? 8 : 4);
900}
901
902void MachOFileLayout::buildLazyBindInfo() {
903 for (const BindLocation& entry : _file.lazyBindingInfo) {
904 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_TYPE_IMM | entry.kind);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000905 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
Nick Kledzike34182f2013-11-06 21:36:55 +0000906 | entry.segIndex);
907 _lazyBindingInfo.append_uleb128(entry.segOffset);
908 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM | entry.ordinal);
909 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM);
910 _lazyBindingInfo.append_string(entry.symbolName);
911 _lazyBindingInfo.append_byte(BIND_OPCODE_DO_BIND);
912 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000913 _lazyBindingInfo.append_byte(BIND_OPCODE_DONE);
Nick Kledzike34182f2013-11-06 21:36:55 +0000914 _lazyBindingInfo.align(_is64 ? 8 : 4);
915}
916
917void MachOFileLayout::computeSymbolTableSizes() {
918 // MachO symbol tables have three ranges: locals, globals, and undefines
919 const size_t nlistSize = (_is64 ? sizeof(nlist_64) : sizeof(nlist));
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000920 _symbolTableSize = nlistSize * (_file.localSymbols.size()
Nick Kledzike34182f2013-11-06 21:36:55 +0000921 + _file.globalSymbols.size()
922 + _file.undefinedSymbols.size());
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000923 _symbolStringPoolSize = 0;
Nick Kledzike34182f2013-11-06 21:36:55 +0000924 for (const Symbol &sym : _file.localSymbols) {
925 _symbolStringPoolSize += (sym.name.size()+1);
926 }
927 for (const Symbol &sym : _file.globalSymbols) {
928 _symbolStringPoolSize += (sym.name.size()+1);
929 }
930 for (const Symbol &sym : _file.undefinedSymbols) {
931 _symbolStringPoolSize += (sym.name.size()+1);
932 }
933 _symbolTableLocalsStartIndex = 0;
934 _symbolTableGlobalsStartIndex = _file.localSymbols.size();
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000935 _symbolTableUndefinesStartIndex = _symbolTableGlobalsStartIndex
Nick Kledzike34182f2013-11-06 21:36:55 +0000936 + _file.globalSymbols.size();
937
938 _indirectSymbolTableCount = 0;
939 for (const Section &sect : _file.sections) {
940 _indirectSymbolTableCount += sect.indirectSymbols.size();
941 }
942}
943
944
945void MachOFileLayout::writeLinkEditContent() {
946 if (_file.fileType == llvm::MachO::MH_OBJECT) {
947 writeRelocations();
948 writeSymbolTable();
949 } else {
950 writeRebaseInfo();
951 writeBindingInfo();
952 writeLazyBindingInfo();
953 // TODO: add weak binding info
954 writeSymbolTable();
955 }
956}
957
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000958std::error_code MachOFileLayout::writeBinary(StringRef path) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000959 // Check for pending error from constructor.
960 if (_ec)
961 return _ec;
962 // Create FileOutputBuffer with calculated size.
Ahmed Charles13c70b62014-03-13 16:20:38 +0000963 std::unique_ptr<llvm::FileOutputBuffer> fob;
Nick Kledzike34182f2013-11-06 21:36:55 +0000964 unsigned flags = 0;
965 if (_file.fileType != llvm::MachO::MH_OBJECT)
966 flags = llvm::FileOutputBuffer::F_executable;
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000967 std::error_code ec;
Nick Kledzike34182f2013-11-06 21:36:55 +0000968 ec = llvm::FileOutputBuffer::create(path, size(), fob, flags);
969 if (ec)
970 return ec;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000971
Nick Kledzike34182f2013-11-06 21:36:55 +0000972 // Write content.
973 _buffer = fob->getBufferStart();
974 writeMachHeader();
975 ec = writeLoadCommands();
976 if (ec)
977 return ec;
978 writeSectionContent();
979 writeLinkEditContent();
980 fob->commit();
981
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000982 return std::error_code();
Nick Kledzike34182f2013-11-06 21:36:55 +0000983}
984
985
986
987/// Takes in-memory normalized view and writes a mach-o object file.
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000988std::error_code writeBinary(const NormalizedFile &file, StringRef path) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000989 MachOFileLayout layout(file);
990 return layout.writeBinary(path);
991}
992
993
994} // namespace normalized
995} // namespace mach_o
996} // namespace lld
997