]> git.saurik.com Git - apple/ld64.git/blame_incremental - src/ld/HeaderAndLoadCommands.hpp
ld64-274.1.tar.gz
[apple/ld64.git] / src / ld / HeaderAndLoadCommands.hpp
... / ...
CommitLineData
1/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-*
2 *
3 * Copyright (c) 2009-2011 Apple Inc. All rights reserved.
4 *
5 * @APPLE_LICENSE_HEADER_START@
6 *
7 * This file contains Original Code and/or Modifications of Original Code
8 * as defined in and that are subject to the Apple Public Source License
9 * Version 2.0 (the 'License'). You may not use this file except in
10 * compliance with the License. Please obtain a copy of the License at
11 * http://www.opensource.apple.com/apsl/ and read it before using this
12 * file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
19 * Please see the License for the specific language governing rights and
20 * limitations under the License.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24
25#ifndef __HEADER_LOAD_COMMANDS_HPP__
26#define __HEADER_LOAD_COMMANDS_HPP__
27
28#include <stdlib.h>
29#include <limits.h>
30#include <unistd.h>
31#include <mach-o/loader.h>
32
33#include <vector>
34
35#include "MachOFileAbstraction.hpp"
36#include "Options.h"
37#include "ld.hpp"
38
39namespace ld {
40namespace tool {
41
42class HeaderAndLoadCommandsAbtract : public ld::Atom
43{
44public:
45 HeaderAndLoadCommandsAbtract(const ld::Section& sect, ld::Atom::Definition d,
46 ld::Atom::Combine c, ld::Atom::Scope s, ld::Atom::ContentType ct,
47 ld::Atom::SymbolTableInclusion i, bool dds, bool thumb, bool al,
48 ld::Atom::Alignment a) : ld::Atom(sect, d, c, s, ct, i, dds, thumb, al, a) { }
49
50 virtual void setUUID(const uint8_t digest[16]) = 0;
51 virtual void recopyUUIDCommand() = 0;
52 virtual const uint8_t* getUUID() const = 0;
53 virtual bool bitcodeBundleCommand(uint64_t& cmdOffset, uint64_t& cmdEnd,
54 uint64_t& sectOffset, uint64_t& sectEnd) const = 0;
55 virtual void linkeditCmdInfo(uint64_t& offset, uint64_t& size) const = 0;
56 virtual void symbolTableCmdInfo(uint64_t& offset, uint64_t& size) const = 0;
57
58};
59
60template <typename A>
61class HeaderAndLoadCommandsAtom : public HeaderAndLoadCommandsAbtract
62{
63public:
64 HeaderAndLoadCommandsAtom(const Options& opts, ld::Internal& state,
65 OutputFile& writer);
66
67 // overrides of ld::Atom
68 virtual ld::File* file() const { return NULL; }
69 virtual const char* name() const { return "mach-o header and load commands"; }
70 virtual uint64_t size() const;
71 virtual uint64_t objectAddress() const { return _address; }
72 virtual void copyRawContent(uint8_t buffer[]) const;
73
74 // overrides of HeaderAndLoadCommandsAbtract
75 virtual void setUUID(const uint8_t digest[16]) { memcpy(_uuid, digest, 16); }
76 virtual void recopyUUIDCommand();
77 virtual const uint8_t* getUUID() const { return &_uuid[0]; }
78 virtual bool bitcodeBundleCommand(uint64_t& cmdOffset, uint64_t& cmdEnd,
79 uint64_t& sectOffset, uint64_t& sectEnd) const;
80 virtual void linkeditCmdInfo(uint64_t& offset, uint64_t& size) const;
81 virtual void symbolTableCmdInfo(uint64_t& offset, uint64_t& size) const;
82
83
84private:
85 typedef typename A::P P;
86 typedef typename A::P::E E;
87 typedef typename A::P::uint_t pint_t;
88
89 unsigned int nonHiddenSectionCount() const;
90 unsigned int segmentCount() const;
91 static uint32_t alignedSize(uint32_t x);
92 uint32_t magic() const;
93 uint32_t cpuType() const;
94 uint32_t cpuSubType() const;
95 uint32_t flags() const;
96 uint32_t fileType() const;
97 uint32_t commandsCount() const;
98 uint32_t threadLoadCommandSize() const;
99 uint8_t* copySingleSegmentLoadCommand(uint8_t* p) const;
100 uint8_t* copySegmentLoadCommands(uint8_t* p, uint8_t* base) const;
101 uint8_t* copyDyldInfoLoadCommand(uint8_t* p) const;
102 uint8_t* copySymbolTableLoadCommand(uint8_t* p, uint8_t* base) const;
103 uint8_t* copyDynamicSymbolTableLoadCommand(uint8_t* p) const;
104 uint8_t* copyDyldLoadCommand(uint8_t* p) const;
105 uint8_t* copyDylibIDLoadCommand(uint8_t* p) const;
106 uint8_t* copyRoutinesLoadCommand(uint8_t* p) const;
107 uint8_t* copyUUIDLoadCommand(uint8_t* p) const;
108 uint8_t* copyVersionLoadCommand(uint8_t* p) const;
109 uint8_t* copySourceVersionLoadCommand(uint8_t* p) const;
110 uint8_t* copyThreadsLoadCommand(uint8_t* p) const;
111 uint8_t* copyEntryPointLoadCommand(uint8_t* p) const;
112 uint8_t* copyEncryptionLoadCommand(uint8_t* p) const;
113 uint8_t* copySplitSegInfoLoadCommand(uint8_t* p) const;
114 uint8_t* copyDylibLoadCommand(uint8_t* p, const ld::dylib::File*) const;
115 uint8_t* copyRPathLoadCommand(uint8_t* p, const char*) const;
116 uint8_t* copySubFrameworkLoadCommand(uint8_t* p) const;
117 uint8_t* copyAllowableClientLoadCommand(uint8_t* p, const char* client) const;
118 uint8_t* copySubLibraryLoadCommand(uint8_t* p, const char* name) const;
119 uint8_t* copySubUmbrellaLoadCommand(uint8_t* p, const char* name) const;
120 uint8_t* copyFunctionStartsLoadCommand(uint8_t* p) const;
121 uint8_t* copyDataInCodeLoadCommand(uint8_t* p) const;
122 uint8_t* copyDyldEnvLoadCommand(uint8_t* p, const char* env) const;
123 uint8_t* copyLinkerOptionsLoadCommand(uint8_t* p, const std::vector<const char*>&) const;
124 uint8_t* copyOptimizationHintsLoadCommand(uint8_t* p) const;
125
126 uint32_t sectionFlags(ld::Internal::FinalSection* sect) const;
127 bool sectionTakesNoDiskSpace(ld::Internal::FinalSection* sect) const;
128
129
130 const Options& _options;
131 ld::Internal& _state;
132 OutputFile& _writer;
133 pint_t _address;
134 bool _hasDyldInfoLoadCommand;
135 bool _hasDyldLoadCommand;
136 bool _hasDylibIDLoadCommand;
137 bool _hasThreadLoadCommand;
138 bool _hasEntryPointLoadCommand;
139 bool _hasEncryptionLoadCommand;
140 bool _hasSplitSegInfoLoadCommand;
141 bool _hasRoutinesLoadCommand;
142 bool _hasUUIDLoadCommand;
143 bool _hasSymbolTableLoadCommand;
144 bool _hasDynamicSymbolTableLoadCommand;
145 bool _hasRPathLoadCommands;
146 bool _hasSubFrameworkLoadCommand;
147 bool _hasVersionLoadCommand;
148 bool _hasFunctionStartsLoadCommand;
149 bool _hasDataInCodeLoadCommand;
150 bool _hasSourceVersionLoadCommand;
151 bool _hasOptimizationHints;
152 uint32_t _dylibLoadCommmandsCount;
153 uint32_t _allowableClientLoadCommmandsCount;
154 uint32_t _dyldEnvironExrasCount;
155 std::vector<const char*> _subLibraryNames;
156 std::vector<const char*> _subUmbrellaNames;
157 uint8_t _uuid[16];
158 mutable macho_uuid_command<P>* _uuidCmdInOutputBuffer;
159 mutable uint32_t _linkeditCmdOffset;
160 mutable uint32_t _symboltableCmdOffset;
161 std::vector< std::vector<const char*> > _linkerOptions;
162
163 static ld::Section _s_section;
164 static ld::Section _s_preload_section;
165};
166
167template <typename A>
168ld::Section HeaderAndLoadCommandsAtom<A>::_s_section("__TEXT", "__mach_header", ld::Section::typeMachHeader, true);
169template <typename A>
170ld::Section HeaderAndLoadCommandsAtom<A>::_s_preload_section("__HEADER", "__mach_header", ld::Section::typeMachHeader, true);
171
172
173template <typename A>
174HeaderAndLoadCommandsAtom<A>::HeaderAndLoadCommandsAtom(const Options& opts, ld::Internal& state, OutputFile& writer)
175 : HeaderAndLoadCommandsAbtract((opts.outputKind() == Options::kPreload) ? _s_preload_section : _s_section,
176 ld::Atom::definitionRegular, ld::Atom::combineNever,
177 ld::Atom::scopeTranslationUnit, ld::Atom::typeUnclassified,
178 ld::Atom::symbolTableNotIn, false, false, false,
179 (opts.outputKind() == Options::kPreload) ? ld::Atom::Alignment(0) : ld::Atom::Alignment(12) ),
180 _options(opts), _state(state), _writer(writer), _address(0), _uuidCmdInOutputBuffer(NULL), _linkeditCmdOffset(0), _symboltableCmdOffset(0)
181{
182 bzero(_uuid, 16);
183 _hasDyldInfoLoadCommand = opts.makeCompressedDyldInfo();
184 _hasDyldLoadCommand = ((opts.outputKind() == Options::kDynamicExecutable) || (_options.outputKind() == Options::kDyld));
185 _hasDylibIDLoadCommand = (opts.outputKind() == Options::kDynamicLibrary);
186 _hasThreadLoadCommand = _options.needsThreadLoadCommand();
187 _hasEntryPointLoadCommand = _options.needsEntryPointLoadCommand();
188 _hasEncryptionLoadCommand = opts.makeEncryptable();
189 _hasSplitSegInfoLoadCommand = opts.sharedRegionEligible();
190 _hasRoutinesLoadCommand = (opts.initFunctionName() != NULL);
191 _hasSymbolTableLoadCommand = true;
192 _hasUUIDLoadCommand = (opts.UUIDMode() != Options::kUUIDNone);
193 _hasOptimizationHints = (_state.someObjectHasOptimizationHints && (opts.outputKind() == Options::kObjectFile));
194 switch ( opts.outputKind() ) {
195 case Options::kDynamicExecutable:
196 case Options::kDynamicLibrary:
197 case Options::kDynamicBundle:
198 case Options::kDyld:
199 case Options::kKextBundle:
200 _hasDynamicSymbolTableLoadCommand = true;
201 break;
202 case Options::kObjectFile:
203 if ( ! state.someObjectFileHasDwarf )
204 _hasUUIDLoadCommand = false;
205 _hasDynamicSymbolTableLoadCommand = false;
206 for (std::vector<ld::Internal::FinalSection*>::iterator it = _state.sections.begin(); it != _state.sections.end(); ++it) {
207 if ( (*it)->type() == ld::Section::typeNonLazyPointer ) {
208 _hasDynamicSymbolTableLoadCommand = true;
209 break;
210 }
211 }
212 for (const char* frameworkName : _state.unprocessedLinkerOptionFrameworks) {
213 std::vector<const char*>* lo = new std::vector<const char*>();
214 lo->push_back("-framework");
215 lo->push_back(frameworkName);
216 _linkerOptions.push_back(*lo);
217 };
218 for (const char* libName : _state.unprocessedLinkerOptionLibraries) {
219 std::vector<const char*>* lo = new std::vector<const char*>();
220 char * s = new char[strlen(libName)+3];
221 strcpy(s, "-l");
222 strcat(s, libName);
223 lo->push_back(s);
224 _linkerOptions.push_back(*lo);
225 };
226 break;
227 case Options::kStaticExecutable:
228 _hasDynamicSymbolTableLoadCommand = opts.positionIndependentExecutable();
229 break;
230 case Options::kPreload:
231 _hasDynamicSymbolTableLoadCommand = opts.positionIndependentExecutable();
232 break;
233 }
234 _hasRPathLoadCommands = (_options.rpaths().size() != 0);
235 _hasSubFrameworkLoadCommand = (_options.umbrellaName() != NULL);
236 _hasVersionLoadCommand = _options.addVersionLoadCommand() ||
237 (!state.objectFileFoundWithNoVersion && (_options.outputKind() == Options::kObjectFile)
238 && ((_options.platform() != Options::kPlatformUnknown) || (state.derivedPlatformLoadCommand != 0)) );
239 _hasFunctionStartsLoadCommand = _options.addFunctionStarts();
240 _hasDataInCodeLoadCommand = _options.addDataInCodeInfo();
241 _hasSourceVersionLoadCommand = _options.needsSourceVersionLoadCommand();
242 _dylibLoadCommmandsCount = _writer.dylibCount();
243 _allowableClientLoadCommmandsCount = _options.allowableClients().size();
244 _dyldEnvironExrasCount = _options.dyldEnvironExtras().size();
245
246 if ( ! _options.useSimplifiedDylibReExports() ) {
247 // target OS does not support LC_REEXPORT_DYLIB, so use old complicated load commands
248 for(uint32_t ord=1; ord <= _writer.dylibCount(); ++ord) {
249 const ld::dylib::File* dylib = _writer.dylibByOrdinal(ord);
250 if ( dylib->willBeReExported() ) {
251 // if child says it is an sub-framework of the image being created, then nothing to do here
252 bool isSubFramework = false;
253 const char* childInUmbrella = dylib->parentUmbrella();
254 if ( childInUmbrella != NULL ) {
255 const char* myLeaf = strrchr(_options.installPath(), '/');
256 if ( myLeaf != NULL ) {
257 if ( strcmp(childInUmbrella, &myLeaf[1]) == 0 )
258 isSubFramework = true;
259 }
260 }
261 // LC_SUB_FRAMEWORK is in child, so do nothing in parent
262 if ( ! isSubFramework ) {
263 // this dylib also needs a sub_x load command
264 bool isFrameworkReExport = false;
265 const char* lastSlash = strrchr(dylib->installPath(), '/');
266 if ( lastSlash != NULL ) {
267 char frameworkName[strlen(lastSlash)+20];
268 sprintf(frameworkName, "/%s.framework/", &lastSlash[1]);
269 isFrameworkReExport = (strstr(dylib->installPath(), frameworkName) != NULL);
270 }
271 if ( isFrameworkReExport ) {
272 // needs a LC_SUB_UMBRELLA command
273 _subUmbrellaNames.push_back(&lastSlash[1]);
274 }
275 else {
276 // needs a LC_SUB_LIBRARY command
277 const char* nameStart = &lastSlash[1];
278 if ( lastSlash == NULL )
279 nameStart = dylib->installPath();
280 int len = strlen(nameStart);
281 const char* dot = strchr(nameStart, '.');
282 if ( dot != NULL )
283 len = dot - nameStart;
284 char* subLibName = new char[len+1];
285 strlcpy(subLibName, nameStart, len+1);
286 _subLibraryNames.push_back(subLibName);
287 }
288 }
289 }
290 }
291 }
292}
293
294template <typename A>
295uint32_t HeaderAndLoadCommandsAtom<A>::alignedSize(uint32_t size)
296{
297 if ( sizeof(pint_t) == 4 )
298 return ((size+3) & (-4)); // 4-byte align all load commands for 32-bit mach-o
299 else
300 return ((size+7) & (-8)); // 8-byte align all load commands for 64-bit mach-o
301}
302
303
304template <typename A>
305unsigned int HeaderAndLoadCommandsAtom<A>::nonHiddenSectionCount() const
306{
307 unsigned int count = 0;
308 for (std::vector<ld::Internal::FinalSection*>::iterator it = _state.sections.begin(); it != _state.sections.end(); ++it) {
309 if ( ! (*it)->isSectionHidden() && ((*it)->type() != ld::Section::typeTentativeDefs) )
310 ++count;
311 }
312 return count;
313}
314
315template <typename A>
316unsigned int HeaderAndLoadCommandsAtom<A>::segmentCount() const
317{
318 if ( _options.outputKind() == Options::kObjectFile ) {
319 // .o files have one anonymous segment that contains all sections
320 return 1;
321 }
322
323 unsigned int count = 0;
324 const char* lastSegName = "";
325 for (std::vector<ld::Internal::FinalSection*>::iterator it = _state.sections.begin(); it != _state.sections.end(); ++it) {
326 if ( _options.outputKind() == Options::kPreload ) {
327 if ( (*it)->type() == ld::Section::typeMachHeader )
328 continue; // for -preload, don't put hidden __HEADER segment into output
329 if ( (*it)->type() == ld::Section::typeLinkEdit )
330 continue; // for -preload, don't put hidden __LINKEDIT segment into output
331 }
332 if ( strcmp(lastSegName, (*it)->segmentName()) != 0 ) {
333 lastSegName = (*it)->segmentName();
334 ++count;
335 }
336 }
337 return count;
338}
339
340template <typename A>
341bool HeaderAndLoadCommandsAtom<A>::bitcodeBundleCommand(uint64_t &cmdOffset, uint64_t &cmdEnd,
342 uint64_t &sectOffset, uint64_t &sectEnd) const
343{
344 if ( _options.outputKind() == Options::kObjectFile ) {
345 return false;
346 }
347 cmdOffset = sizeof(macho_header<P>);
348 const char* lastSegName = "";
349 for (std::vector<ld::Internal::FinalSection*>::iterator it = _state.sections.begin(); it != _state.sections.end(); ++it) {
350 if ( strcmp(lastSegName, (*it)->segmentName()) != 0 ) {
351 lastSegName = (*it)->segmentName();
352 cmdOffset += sizeof(macho_segment_command<P>);
353 }
354 if ( strcmp((*it)->segmentName(), "__LLVM") == 0 && strcmp((*it)->sectionName(), "__bundle") == 0 ) {
355 sectOffset = (*it)->fileOffset;
356 sectEnd = (*(it + 1))->fileOffset;
357 cmdEnd = cmdOffset + sizeof(macho_section<P>);
358 return true;
359 }
360 if ( ! (*it)->isSectionHidden() )
361 cmdOffset += sizeof(macho_section<P>);
362 }
363 return false;
364}
365
366template <typename A>
367void HeaderAndLoadCommandsAtom<A>::linkeditCmdInfo(uint64_t &offset, uint64_t &size) const
368{
369 offset = _linkeditCmdOffset;
370 size = sizeof(macho_segment_command<P>);
371}
372
373template <typename A>
374void HeaderAndLoadCommandsAtom<A>::symbolTableCmdInfo(uint64_t &offset, uint64_t &size) const
375{
376 offset = _symboltableCmdOffset;
377 size = sizeof(macho_symtab_command<P>);
378}
379
380
381template <typename A>
382uint64_t HeaderAndLoadCommandsAtom<A>::size() const
383{
384 uint32_t sz = sizeof(macho_header<P>);
385
386 sz += sizeof(macho_segment_command<P>) * this->segmentCount();
387 sz += sizeof(macho_section<P>) * this->nonHiddenSectionCount();
388
389 if ( _hasDylibIDLoadCommand )
390 sz += alignedSize(sizeof(macho_dylib_command<P>) + strlen(_options.installPath()) + 1);
391
392 if ( _hasDyldInfoLoadCommand )
393 sz += sizeof(macho_dyld_info_command<P>);
394
395 if ( _hasSymbolTableLoadCommand )
396 sz += sizeof(macho_symtab_command<P>);
397
398 if ( _hasDynamicSymbolTableLoadCommand )
399 sz += sizeof(macho_dysymtab_command<P>);
400
401 if ( _hasDyldLoadCommand )
402 sz += alignedSize(sizeof(macho_dylinker_command<P>) + strlen(_options.dyldInstallPath()) + 1);
403
404 if ( _hasRoutinesLoadCommand )
405 sz += sizeof(macho_routines_command<P>);
406
407 if ( _hasUUIDLoadCommand )
408 sz += sizeof(macho_uuid_command<P>);
409
410 if ( _hasVersionLoadCommand )
411 sz += sizeof(macho_version_min_command<P>);
412
413 if ( _hasSourceVersionLoadCommand )
414 sz += sizeof(macho_source_version_command<P>);
415
416 if ( _hasThreadLoadCommand )
417 sz += this->threadLoadCommandSize();
418
419 if ( _hasEntryPointLoadCommand )
420 sz += sizeof(macho_entry_point_command<P>);
421
422 if ( _hasEncryptionLoadCommand )
423 sz += sizeof(macho_encryption_info_command<P>);
424
425 if ( _hasSplitSegInfoLoadCommand )
426 sz += sizeof(macho_linkedit_data_command<P>);
427
428 for(uint32_t ord=1; ord <= _writer.dylibCount(); ++ord) {
429 sz += alignedSize(sizeof(macho_dylib_command<P>) + strlen(_writer.dylibByOrdinal(ord)->installPath()) + 1);
430 }
431
432 if ( _hasRPathLoadCommands ) {
433 const std::vector<const char*>& rpaths = _options.rpaths();
434 for (std::vector<const char*>::const_iterator it = rpaths.begin(); it != rpaths.end(); ++it) {
435 sz += alignedSize(sizeof(macho_rpath_command<P>) + strlen(*it) + 1);
436 }
437 }
438
439 if ( _hasSubFrameworkLoadCommand )
440 sz += alignedSize(sizeof(macho_sub_framework_command<P>) + strlen(_options.umbrellaName()) + 1);
441
442 for (std::vector<const char*>::const_iterator it = _subLibraryNames.begin(); it != _subLibraryNames.end(); ++it) {
443 sz += alignedSize(sizeof(macho_sub_library_command<P>) + strlen(*it) + 1);
444 }
445
446 for (std::vector<const char*>::const_iterator it = _subUmbrellaNames.begin(); it != _subUmbrellaNames.end(); ++it) {
447 sz += alignedSize(sizeof(macho_sub_umbrella_command<P>) + strlen(*it) + 1);
448 }
449
450 if ( _allowableClientLoadCommmandsCount != 0 ) {
451 const std::vector<const char*>& clients = _options.allowableClients();
452 for (std::vector<const char*>::const_iterator it = clients.begin(); it != clients.end(); ++it) {
453 sz += alignedSize(sizeof(macho_sub_client_command<P>) + strlen(*it) + 1);
454 }
455 }
456
457 if ( _dyldEnvironExrasCount != 0 ) {
458 const std::vector<const char*>& extras = _options.dyldEnvironExtras();
459 for (std::vector<const char*>::const_iterator it = extras.begin(); it != extras.end(); ++it) {
460 sz += alignedSize(sizeof(macho_dylinker_command<P>) + strlen(*it) + 1);
461 }
462 }
463
464 if ( _hasFunctionStartsLoadCommand )
465 sz += sizeof(macho_linkedit_data_command<P>);
466
467 if ( _hasDataInCodeLoadCommand )
468 sz += sizeof(macho_linkedit_data_command<P>);
469
470 if ( !_linkerOptions.empty() ) {
471 for (ld::relocatable::File::LinkerOptionsList::const_iterator it = _linkerOptions.begin(); it != _linkerOptions.end(); ++it) {
472 uint32_t s = sizeof(macho_linker_option_command<P>);
473 const std::vector<const char*>& options = *it;
474 for (std::vector<const char*>::const_iterator t=options.begin(); t != options.end(); ++t) {
475 s += (strlen(*t) + 1);
476 }
477 sz += alignedSize(s);
478 }
479 }
480
481 if ( _hasOptimizationHints )
482 sz += sizeof(macho_linkedit_data_command<P>);
483
484 return sz;
485}
486
487template <typename A>
488uint32_t HeaderAndLoadCommandsAtom<A>::commandsCount() const
489{
490 uint32_t count = this->segmentCount();
491
492 if ( _hasDylibIDLoadCommand )
493 ++count;
494
495 if ( _hasDyldInfoLoadCommand )
496 ++count;
497
498 if ( _hasSymbolTableLoadCommand )
499 ++count;
500
501 if ( _hasDynamicSymbolTableLoadCommand )
502 ++count;
503
504 if ( _hasDyldLoadCommand )
505 ++count;
506
507 if ( _hasRoutinesLoadCommand )
508 ++count;
509
510 if ( _hasUUIDLoadCommand )
511 ++count;
512
513 if ( _hasVersionLoadCommand )
514 ++count;
515
516 if ( _hasSourceVersionLoadCommand )
517 ++count;
518
519 if ( _hasThreadLoadCommand )
520 ++count;
521
522 if ( _hasEntryPointLoadCommand )
523 ++count;
524
525 if ( _hasEncryptionLoadCommand )
526 ++count;
527
528 if ( _hasSplitSegInfoLoadCommand )
529 ++count;
530
531 count += _dylibLoadCommmandsCount;
532
533 count += _options.rpaths().size();
534
535 if ( _hasSubFrameworkLoadCommand )
536 ++count;
537
538 count += _subLibraryNames.size();
539
540 count += _subUmbrellaNames.size();
541
542 count += _allowableClientLoadCommmandsCount;
543
544 count += _dyldEnvironExrasCount;
545
546 if ( _hasFunctionStartsLoadCommand )
547 ++count;
548
549 if ( _hasDataInCodeLoadCommand )
550 ++count;
551
552 if ( !_linkerOptions.empty() ) {
553 for (ld::relocatable::File::LinkerOptionsList::const_iterator it = _linkerOptions.begin(); it != _linkerOptions.end(); ++it) {
554 ++count;
555 }
556 }
557
558 if ( _hasOptimizationHints )
559 ++count;
560
561 return count;
562}
563
564template <typename A>
565uint32_t HeaderAndLoadCommandsAtom<A>::fileType() const
566{
567 switch ( _options.outputKind() ) {
568 case Options::kDynamicExecutable:
569 case Options::kStaticExecutable:
570 return MH_EXECUTE;
571 case Options::kDynamicLibrary:
572 return MH_DYLIB;
573 case Options::kDynamicBundle:
574 return MH_BUNDLE;
575 case Options::kObjectFile:
576 return MH_OBJECT;
577 case Options::kDyld:
578 return MH_DYLINKER;
579 case Options::kPreload:
580 return MH_PRELOAD;
581 case Options::kKextBundle:
582 return MH_KEXT_BUNDLE;
583 }
584 throw "unknonwn mach-o file type";
585}
586
587template <typename A>
588uint32_t HeaderAndLoadCommandsAtom<A>::flags() const
589{
590 uint32_t bits = 0;
591 if ( _options.outputKind() == Options::kObjectFile ) {
592 if ( _state.allObjectFilesScatterable )
593 bits = MH_SUBSECTIONS_VIA_SYMBOLS;
594 }
595 else {
596 if ( _options.outputKind() == Options::kStaticExecutable ) {
597 bits |= MH_NOUNDEFS;
598 if ( _options.positionIndependentExecutable() )
599 bits |= MH_PIE;
600 }
601 else if ( _options.outputKind() == Options::kPreload ) {
602 bits |= MH_NOUNDEFS;
603 if ( _options.positionIndependentExecutable() )
604 bits |= MH_PIE;
605 }
606 else {
607 bits = MH_DYLDLINK;
608 switch ( _options.nameSpace() ) {
609 case Options::kTwoLevelNameSpace:
610 bits |= MH_TWOLEVEL | MH_NOUNDEFS;
611 break;
612 case Options::kFlatNameSpace:
613 break;
614 case Options::kForceFlatNameSpace:
615 bits |= MH_FORCE_FLAT;
616 break;
617 }
618 if ( _state.hasWeakExternalSymbols || _writer.overridesWeakExternalSymbols )
619 bits |= MH_WEAK_DEFINES;
620 if ( _writer.usesWeakExternalSymbols || _state.hasWeakExternalSymbols )
621 bits |= MH_BINDS_TO_WEAK;
622 if ( _options.prebind() )
623 bits |= MH_PREBOUND;
624 if ( _options.splitSeg() )
625 bits |= MH_SPLIT_SEGS;
626 if ( (_options.outputKind() == Options::kDynamicLibrary)
627 && _writer._noReExportedDylibs
628 && _options.useSimplifiedDylibReExports() ) {
629 bits |= MH_NO_REEXPORTED_DYLIBS;
630 }
631 if ( _options.positionIndependentExecutable() && ! _writer.pieDisabled )
632 bits |= MH_PIE;
633 if ( _options.markAutoDeadStripDylib() )
634 bits |= MH_DEAD_STRIPPABLE_DYLIB;
635 if ( _state.hasThreadLocalVariableDefinitions )
636 bits |= MH_HAS_TLV_DESCRIPTORS;
637 if ( _options.hasNonExecutableHeap() )
638 bits |= MH_NO_HEAP_EXECUTION;
639 if ( _options.markAppExtensionSafe() && (_options.outputKind() == Options::kDynamicLibrary) )
640 bits |= MH_APP_EXTENSION_SAFE;
641 }
642 if ( _options.hasExecutableStack() )
643 bits |= MH_ALLOW_STACK_EXECUTION;
644 }
645 return bits;
646}
647
648template <> uint32_t HeaderAndLoadCommandsAtom<x86>::magic() const { return MH_MAGIC; }
649template <> uint32_t HeaderAndLoadCommandsAtom<x86_64>::magic() const { return MH_MAGIC_64; }
650template <> uint32_t HeaderAndLoadCommandsAtom<arm>::magic() const { return MH_MAGIC; }
651template <> uint32_t HeaderAndLoadCommandsAtom<arm64>::magic() const { return MH_MAGIC_64; }
652
653template <> uint32_t HeaderAndLoadCommandsAtom<x86>::cpuType() const { return CPU_TYPE_I386; }
654template <> uint32_t HeaderAndLoadCommandsAtom<x86_64>::cpuType() const { return CPU_TYPE_X86_64; }
655template <> uint32_t HeaderAndLoadCommandsAtom<arm>::cpuType() const { return CPU_TYPE_ARM; }
656template <> uint32_t HeaderAndLoadCommandsAtom<arm64>::cpuType() const { return CPU_TYPE_ARM64; }
657
658
659template <>
660uint32_t HeaderAndLoadCommandsAtom<x86>::cpuSubType() const
661{
662 return CPU_SUBTYPE_I386_ALL;
663}
664
665template <>
666uint32_t HeaderAndLoadCommandsAtom<x86_64>::cpuSubType() const
667{
668 if ( (_options.outputKind() == Options::kDynamicExecutable) && (_state.cpuSubType == CPU_SUBTYPE_X86_64_ALL) && (_options.macosxVersionMin() >= ld::mac10_5) )
669 return (_state.cpuSubType | 0x80000000);
670 else
671 return _state.cpuSubType;
672}
673
674template <>
675uint32_t HeaderAndLoadCommandsAtom<arm>::cpuSubType() const
676{
677 return _state.cpuSubType;
678}
679
680template <>
681uint32_t HeaderAndLoadCommandsAtom<arm64>::cpuSubType() const
682{
683 return CPU_SUBTYPE_ARM64_ALL;
684}
685
686
687
688template <typename A>
689uint8_t* HeaderAndLoadCommandsAtom<A>::copySingleSegmentLoadCommand(uint8_t* p) const
690{
691 // in .o files there is just one segment load command with a blank name
692 // and all sections under it
693 macho_segment_command<P>* cmd = (macho_segment_command<P>*)p;
694 cmd->set_cmd(macho_segment_command<P>::CMD);
695 cmd->set_segname("");
696 cmd->set_vmaddr(_options.baseAddress());
697 cmd->set_vmsize(0); // updated after sections set
698 cmd->set_fileoff(0); // updated after sections set
699 cmd->set_filesize(0); // updated after sections set
700 cmd->set_maxprot(VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE);
701 cmd->set_initprot(VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE);
702 cmd->set_nsects(this->nonHiddenSectionCount());
703 cmd->set_flags(0);
704 // add sections array
705 macho_section<P>* msect = (macho_section<P>*)&p[sizeof(macho_segment_command<P>)];
706 for (std::vector<ld::Internal::FinalSection*>::iterator sit = _state.sections.begin(); sit != _state.sections.end(); ++sit) {
707 ld::Internal::FinalSection* fsect = *sit;
708 if ( fsect->isSectionHidden() )
709 continue;
710 if ( fsect->type() == ld::Section::typeTentativeDefs )
711 continue;
712 msect->set_sectname(fsect->sectionName());
713 msect->set_segname(fsect->segmentName());
714 msect->set_addr(fsect->address);
715 msect->set_size(fsect->size);
716 msect->set_offset(fsect->fileOffset);
717 msect->set_align(fsect->alignment);
718 msect->set_reloff((fsect->relocCount == 0) ? 0 : _writer.sectionRelocationsSection->fileOffset + fsect->relocStart * sizeof(macho_relocation_info<P>));
719 msect->set_nreloc(fsect->relocCount);
720 msect->set_flags(sectionFlags(fsect));
721 msect->set_reserved1(fsect->indirectSymTabStartIndex);
722 msect->set_reserved2(fsect->indirectSymTabElementSize);
723 // update segment info
724 if ( cmd->fileoff() == 0 )
725 cmd->set_fileoff(fsect->fileOffset);
726 cmd->set_vmsize(fsect->address + fsect->size - cmd->vmaddr());
727 if ( (fsect->type() != ld::Section::typeZeroFill) && (fsect->type() != ld::Section::typeTentativeDefs) )
728 cmd->set_filesize(fsect->fileOffset + fsect->size - cmd->fileoff());
729 ++msect;
730 }
731 cmd->set_cmdsize(sizeof(macho_segment_command<P>) + cmd->nsects()*sizeof(macho_section<P>));
732 return p + cmd->cmdsize();
733}
734
735struct SegInfo {
736 SegInfo(const char* n, const Options&);
737 const char* segName;
738 uint32_t nonHiddenSectionCount;
739 uint32_t nonSectCreateSections;
740 uint32_t maxProt;
741 uint32_t initProt;
742 std::vector<ld::Internal::FinalSection*> sections;
743};
744
745
746SegInfo::SegInfo(const char* n, const Options& opts)
747 : segName(n), nonHiddenSectionCount(0), nonSectCreateSections(0), maxProt(opts.maxSegProtection(n)), initProt(opts.initialSegProtection(n))
748{
749}
750
751
752template <typename A>
753uint32_t HeaderAndLoadCommandsAtom<A>::sectionFlags(ld::Internal::FinalSection* sect) const
754{
755 uint32_t bits;
756 switch ( sect->type() ) {
757 case ld::Section::typeUnclassified:
758 if ( strcmp(sect->segmentName(), "__OBJC") == 0 )
759 return S_REGULAR | S_ATTR_NO_DEAD_STRIP;
760 else if ( (strcmp(sect->sectionName(), "__objc_classlist") == 0) && (strcmp(sect->segmentName(), "__DATA") == 0) )
761 return S_REGULAR | S_ATTR_NO_DEAD_STRIP;
762 else if ( (strcmp(sect->sectionName(), "__objc_catlist") == 0) && (strcmp(sect->segmentName(), "__DATA") == 0) )
763 return S_REGULAR | S_ATTR_NO_DEAD_STRIP;
764 else if ( (strncmp(sect->sectionName(), "__objc_superrefs", 16) == 0) && (strcmp(sect->segmentName(), "__DATA") == 0) )
765 return S_REGULAR | S_ATTR_NO_DEAD_STRIP;
766 else if ( (strncmp(sect->sectionName(), "__objc_nlclslist", 16) == 0) && (strcmp(sect->segmentName(), "__DATA") == 0) )
767 return S_REGULAR | S_ATTR_NO_DEAD_STRIP;
768 else if ( (strncmp(sect->sectionName(), "__objc_nlcatlist", 16) == 0) && (strcmp(sect->segmentName(), "__DATA") == 0) )
769 return S_REGULAR | S_ATTR_NO_DEAD_STRIP;
770 else if ( (_options.outputKind() == Options::kObjectFile) && !sect->atoms.empty() && sect->atoms.front()->dontDeadStripIfReferencesLive() )
771 return S_REGULAR | S_ATTR_LIVE_SUPPORT;
772 else
773 return S_REGULAR;
774 case ld::Section::typeCode:
775 bits = S_REGULAR | S_ATTR_SOME_INSTRUCTIONS | S_ATTR_PURE_INSTRUCTIONS;
776 if ( sect->hasLocalRelocs && ! _writer.pieDisabled )
777 bits |= S_ATTR_LOC_RELOC;
778 if ( sect->hasExternalRelocs )
779 bits |= S_ATTR_EXT_RELOC;
780 return bits;
781 case ld::Section::typePageZero:
782 return S_REGULAR;
783 case ld::Section::typeImportProxies:
784 return S_REGULAR;
785 case ld::Section::typeLinkEdit:
786 return S_REGULAR;
787 case ld::Section::typeMachHeader:
788 return S_REGULAR;
789 case ld::Section::typeStack:
790 return S_REGULAR;
791 case ld::Section::typeLiteral4:
792 return S_4BYTE_LITERALS;
793 case ld::Section::typeLiteral8:
794 return S_8BYTE_LITERALS;
795 case ld::Section::typeLiteral16:
796 return S_16BYTE_LITERALS;
797 case ld::Section::typeConstants:
798 return S_REGULAR;
799 case ld::Section::typeTempLTO:
800 assert(0 && "typeTempLTO should not make it to final linked image");
801 return S_REGULAR;
802 case ld::Section::typeTempAlias:
803 assert(0 && "typeAlias should not make it to final linked image");
804 return S_REGULAR;
805 case ld::Section::typeAbsoluteSymbols:
806 assert(0 && "typeAbsoluteSymbols should not make it to final linked image");
807 return S_REGULAR;
808 case ld::Section::typeCString:
809 case ld::Section::typeNonStdCString:
810 return S_CSTRING_LITERALS;
811 case ld::Section::typeCStringPointer:
812 return S_LITERAL_POINTERS | S_ATTR_NO_DEAD_STRIP;
813 case ld::Section::typeUTF16Strings:
814 return S_REGULAR;
815 case ld::Section::typeCFString:
816 return S_REGULAR;
817 case ld::Section::typeObjC1Classes:
818 return S_REGULAR | S_ATTR_NO_DEAD_STRIP;
819 case ld::Section::typeCFI:
820 return S_REGULAR;
821 case ld::Section::typeLSDA:
822 return S_REGULAR;
823 case ld::Section::typeDtraceDOF:
824 return S_DTRACE_DOF;
825 case ld::Section::typeUnwindInfo:
826 return S_REGULAR;
827 case ld::Section::typeObjCClassRefs:
828 case ld::Section::typeObjC2CategoryList:
829 return S_REGULAR | S_ATTR_NO_DEAD_STRIP;
830 case ld::Section::typeZeroFill:
831 if ( _options.optimizeZeroFill() )
832 return S_ZEROFILL;
833 else
834 return S_REGULAR;
835 case ld::Section::typeTentativeDefs:
836 assert(0 && "typeTentativeDefs should not make it to final linked image");
837 return S_REGULAR;
838 case ld::Section::typeLazyPointer:
839 case ld::Section::typeLazyPointerClose:
840 return S_LAZY_SYMBOL_POINTERS;
841 case ld::Section::typeStubClose:
842 case ld::Section::typeStub:
843 if ( sect->hasLocalRelocs )
844 return S_SYMBOL_STUBS | S_ATTR_SOME_INSTRUCTIONS | S_ATTR_PURE_INSTRUCTIONS | S_ATTR_LOC_RELOC;
845 else
846 return S_SYMBOL_STUBS | S_ATTR_SOME_INSTRUCTIONS | S_ATTR_PURE_INSTRUCTIONS;
847 case ld::Section::typeNonLazyPointer:
848 if ( _options.outputKind() == Options::kKextBundle )
849 return S_REGULAR;
850 else if ( (_options.outputKind() == Options::kStaticExecutable) && _options.positionIndependentExecutable() )
851 return S_REGULAR;
852 else
853 return S_NON_LAZY_SYMBOL_POINTERS;
854 case ld::Section::typeDyldInfo:
855 return S_REGULAR;
856 case ld::Section::typeLazyDylibPointer:
857 return S_LAZY_DYLIB_SYMBOL_POINTERS;
858 case ld::Section::typeStubHelper:
859 if ( sect->hasLocalRelocs )
860 return S_REGULAR | S_ATTR_SOME_INSTRUCTIONS | S_ATTR_PURE_INSTRUCTIONS | S_ATTR_LOC_RELOC;
861 else
862 return S_REGULAR | S_ATTR_SOME_INSTRUCTIONS | S_ATTR_PURE_INSTRUCTIONS;
863 case ld::Section::typeInitializerPointers:
864 // <rdar://problem/11456679> i386 kexts need different section type
865 if ( (_options.outputKind() == Options::kObjectFile)
866 && (strcmp(sect->sectionName(), "__constructor") == 0)
867 && (strcmp(sect->segmentName(), "__TEXT") == 0) )
868 return S_REGULAR;
869 else
870 return S_MOD_INIT_FUNC_POINTERS;
871 case ld::Section::typeTerminatorPointers:
872 return S_MOD_TERM_FUNC_POINTERS;
873 case ld::Section::typeTLVInitialValues:
874 return S_THREAD_LOCAL_REGULAR;
875 case ld::Section::typeTLVZeroFill:
876 return S_THREAD_LOCAL_ZEROFILL;
877 case ld::Section::typeTLVDefs:
878 return S_THREAD_LOCAL_VARIABLES;
879 case ld::Section::typeTLVInitializerPointers:
880 return S_THREAD_LOCAL_INIT_FUNCTION_POINTERS;
881 case ld::Section::typeTLVPointers:
882 return S_THREAD_LOCAL_VARIABLE_POINTERS;
883 case ld::Section::typeFirstSection:
884 assert(0 && "typeFirstSection should not make it to final linked image");
885 return S_REGULAR;
886 case ld::Section::typeLastSection:
887 assert(0 && "typeLastSection should not make it to final linked image");
888 return S_REGULAR;
889 case ld::Section::typeDebug:
890 return S_REGULAR | S_ATTR_DEBUG;
891 case ld::Section::typeSectCreate:
892 return S_REGULAR;
893 }
894 return S_REGULAR;
895}
896
897
898template <typename A>
899bool HeaderAndLoadCommandsAtom<A>::sectionTakesNoDiskSpace(ld::Internal::FinalSection* sect) const
900{
901 switch ( sect->type() ) {
902 case ld::Section::typeZeroFill:
903 case ld::Section::typeTLVZeroFill:
904 return _options.optimizeZeroFill();
905 case ld::Section::typeAbsoluteSymbols:
906 case ld::Section::typeTentativeDefs:
907 case ld::Section::typeLastSection:
908 return true;
909 default:
910 break;
911 }
912 return false;
913}
914
915
916template <typename A>
917uint8_t* HeaderAndLoadCommandsAtom<A>::copySegmentLoadCommands(uint8_t* p, uint8_t* base) const
918{
919 // group sections into segments
920 std::vector<SegInfo> segs;
921 const char* lastSegName = "";
922 for (std::vector<ld::Internal::FinalSection*>::iterator it = _state.sections.begin(); it != _state.sections.end(); ++it) {
923 ld::Internal::FinalSection* sect = *it;
924 if ( _options.outputKind() == Options::kPreload ) {
925 if ( (*it)->type() == ld::Section::typeMachHeader )
926 continue; // for -preload, don't put hidden __HEADER segment into output
927 if ( (*it)->type() == ld::Section::typeLinkEdit )
928 continue; // for -preload, don't put hidden __LINKEDIT segment into output
929 }
930 if ( strcmp(lastSegName, sect->segmentName()) != 0 ) {
931 SegInfo si(sect->segmentName(), _options);
932 segs.push_back(si);
933 lastSegName = sect->segmentName();
934 }
935 if ( ! sect->isSectionHidden() )
936 segs.back().nonHiddenSectionCount++;
937 if ( sect->type() != ld::Section::typeSectCreate )
938 segs.back().nonSectCreateSections++;
939
940 segs.back().sections.push_back(sect);
941 }
942 // write out segment load commands for each section with trailing sections
943 for (std::vector<SegInfo>::iterator it = segs.begin(); it != segs.end(); ++it) {
944 SegInfo& si = *it;
945 ld::Internal::FinalSection* lastNonZeroFillSection = NULL;
946 for (int i=si.sections.size()-1; i >= 0; --i) {
947 if ( !sectionTakesNoDiskSpace(si.sections[i]) ) {
948 lastNonZeroFillSection = si.sections[i];
949 break;
950 }
951 }
952 uint64_t vmsize = si.sections.back()->address + si.sections.back()->size - si.sections.front()->address;
953 vmsize = ((vmsize+_options.segmentAlignment()-1) & (-_options.segmentAlignment()));
954 uint64_t filesize = 0;
955 if ( lastNonZeroFillSection != NULL ) {
956 filesize = lastNonZeroFillSection->address + lastNonZeroFillSection->size - si.sections.front()->address;
957 // round up all segments to page aligned, except __LINKEDIT
958 if ( (si.sections[0]->type() != ld::Section::typeLinkEdit) && (si.sections[0]->type() != ld::Section::typeImportProxies) )
959 filesize = (filesize + _options.segmentAlignment()-1) & (-_options.segmentAlignment());
960 }
961 if ( si.sections.front()->type() == ld::Section::typePageZero )
962 filesize = 0;
963 else if ( si.sections.front()->type() == ld::Section::typeStack )
964 filesize = 0;
965 macho_segment_command<P>* segCmd = (macho_segment_command<P>*)p;
966 segCmd->set_cmd(macho_segment_command<P>::CMD);
967 segCmd->set_cmdsize(sizeof(macho_segment_command<P>) + si.nonHiddenSectionCount*sizeof(macho_section<P>));
968 segCmd->set_segname(si.sections.front()->segmentName());
969 segCmd->set_vmaddr(si.sections.front()->address);
970 segCmd->set_vmsize(vmsize);
971 segCmd->set_fileoff(si.sections.front()->fileOffset);
972 segCmd->set_filesize(filesize);
973 segCmd->set_maxprot(si.maxProt);
974 segCmd->set_initprot(si.initProt);
975 segCmd->set_nsects(si.nonHiddenSectionCount);
976 segCmd->set_flags(si.nonSectCreateSections ? 0 : SG_NORELOC); // FIXME, really should check all References
977 if ( strcmp(segCmd->segname(), "__LINKEDIT") == 0 )
978 _linkeditCmdOffset = p - base;
979 p += sizeof(macho_segment_command<P>);
980 macho_section<P>* msect = (macho_section<P>*)p;
981 for (std::vector<ld::Internal::FinalSection*>::iterator sit = si.sections.begin(); sit != si.sections.end(); ++sit) {
982 ld::Internal::FinalSection* fsect = *sit;
983 if ( ! fsect->isSectionHidden() ) {
984 msect->set_sectname(fsect->sectionName());
985 msect->set_segname(fsect->segmentName());
986 msect->set_addr(fsect->address);
987 msect->set_size(fsect->size);
988 msect->set_offset(sectionTakesNoDiskSpace(fsect) ? 0 : fsect->fileOffset);
989 msect->set_align(fsect->alignment);
990 msect->set_reloff(0);
991 msect->set_nreloc(0);
992 msect->set_flags(sectionFlags(fsect));
993 msect->set_reserved1(fsect->indirectSymTabStartIndex);
994 msect->set_reserved2(fsect->indirectSymTabElementSize);
995 p += sizeof(macho_section<P>);
996 ++msect;
997 }
998 }
999 }
1000
1001 return p;
1002}
1003
1004
1005template <typename A>
1006uint8_t* HeaderAndLoadCommandsAtom<A>::copySymbolTableLoadCommand(uint8_t* p, uint8_t* base) const
1007{
1008 _symboltableCmdOffset = p - base;
1009 // build LC_SYMTAB command
1010 macho_symtab_command<P>* symbolTableCmd = (macho_symtab_command<P>*)p;
1011 symbolTableCmd->set_cmd(LC_SYMTAB);
1012 symbolTableCmd->set_cmdsize(sizeof(macho_symtab_command<P>));
1013 symbolTableCmd->set_nsyms(_writer.symbolTableSection->size/sizeof(macho_nlist<P>));
1014 symbolTableCmd->set_symoff(_writer.symbolTableSection->size == 0 ? 0 : _writer.symbolTableSection->fileOffset);
1015 symbolTableCmd->set_stroff(_writer.stringPoolSection->size == 0 ? 0 : _writer.stringPoolSection->fileOffset );
1016 symbolTableCmd->set_strsize(_writer.stringPoolSection->size);
1017 return p + sizeof(macho_symtab_command<P>);
1018}
1019
1020template <typename A>
1021uint8_t* HeaderAndLoadCommandsAtom<A>::copyDynamicSymbolTableLoadCommand(uint8_t* p) const
1022{
1023 // build LC_SYMTAB command
1024 macho_dysymtab_command<P>* dynamicSymbolTableCmd = (macho_dysymtab_command<P>*)p;
1025 dynamicSymbolTableCmd->set_cmd(LC_DYSYMTAB);
1026 dynamicSymbolTableCmd->set_cmdsize(sizeof(macho_dysymtab_command<P>));
1027 dynamicSymbolTableCmd->set_ilocalsym(0);
1028 dynamicSymbolTableCmd->set_nlocalsym(_writer._localSymbolsCount);
1029 dynamicSymbolTableCmd->set_iextdefsym(dynamicSymbolTableCmd->ilocalsym()+dynamicSymbolTableCmd->nlocalsym());
1030 dynamicSymbolTableCmd->set_nextdefsym(_writer._globalSymbolsCount);
1031 dynamicSymbolTableCmd->set_iundefsym(dynamicSymbolTableCmd->iextdefsym()+dynamicSymbolTableCmd->nextdefsym());
1032 dynamicSymbolTableCmd->set_nundefsym(_writer._importSymbolsCount);
1033
1034 // FIX ME: support for 10.3 dylibs which need modules
1035 //if ( fWriter.fModuleInfoAtom != NULL ) {
1036 // dynamicSymbolTableCmd->set_tocoff(fWriter.fModuleInfoAtom->getTableOfContentsFileOffset());
1037 // dynamicSymbolTableCmd->set_ntoc(fWriter.fSymbolTableExportCount);
1038 // dynamicSymbolTableCmd->set_modtaboff(fWriter.fModuleInfoAtom->getModuleTableFileOffset());
1039 // dynamicSymbolTableCmd->set_nmodtab(1);
1040 // dynamicSymbolTableCmd->set_extrefsymoff(fWriter.fModuleInfoAtom->getReferencesFileOffset());
1041 // dynamicSymbolTableCmd->set_nextrefsyms(fWriter.fModuleInfoAtom->getReferencesCount());
1042 //}
1043
1044 bool hasIndirectSymbols = ( (_writer.indirectSymbolTableSection != NULL) && (_writer.indirectSymbolTableSection->size != 0) );
1045 dynamicSymbolTableCmd->set_indirectsymoff(hasIndirectSymbols ? _writer.indirectSymbolTableSection->fileOffset : 0);
1046 dynamicSymbolTableCmd->set_nindirectsyms( hasIndirectSymbols ? _writer.indirectSymbolTableSection->size/sizeof(uint32_t) : 0);
1047
1048 // FIX ME: support for classic relocations
1049 if ( _options.outputKind() != Options::kObjectFile ) {
1050 bool hasExternalRelocs = ( (_writer.externalRelocationsSection != NULL) && (_writer.externalRelocationsSection->size != 0) );
1051 dynamicSymbolTableCmd->set_extreloff(hasExternalRelocs ? _writer.externalRelocationsSection->fileOffset : 0);
1052 dynamicSymbolTableCmd->set_nextrel( hasExternalRelocs ? _writer.externalRelocationsSection->size/8 : 0);
1053 bool hasLocalRelocs = ( (_writer.localRelocationsSection != NULL) && (_writer.localRelocationsSection->size != 0) );
1054 dynamicSymbolTableCmd->set_locreloff(hasLocalRelocs ? _writer.localRelocationsSection->fileOffset : 0);
1055 dynamicSymbolTableCmd->set_nlocrel (hasLocalRelocs ? _writer.localRelocationsSection->size/8 : 0);
1056 }
1057 return p + sizeof(macho_dysymtab_command<P>);
1058}
1059
1060
1061template <typename A>
1062uint8_t* HeaderAndLoadCommandsAtom<A>::copyDyldInfoLoadCommand(uint8_t* p) const
1063{
1064 // build LC_DYLD_INFO command
1065 macho_dyld_info_command<P>* cmd = (macho_dyld_info_command<P>*)p;
1066
1067 cmd->set_cmd(LC_DYLD_INFO_ONLY);
1068 cmd->set_cmdsize(sizeof(macho_dyld_info_command<P>));
1069 if ( _writer.rebaseSection->size != 0 ) {
1070 cmd->set_rebase_off(_writer.rebaseSection->fileOffset);
1071 cmd->set_rebase_size(_writer.rebaseSection->size);
1072 }
1073 if ( _writer.bindingSection->size != 0 ) {
1074 cmd->set_bind_off(_writer.bindingSection->fileOffset);
1075 cmd->set_bind_size(_writer.bindingSection->size);
1076 }
1077 if ( _writer.weakBindingSection->size != 0 ) {
1078 cmd->set_weak_bind_off(_writer.weakBindingSection->fileOffset);
1079 cmd->set_weak_bind_size(_writer.weakBindingSection->size);
1080 }
1081 if ( _writer.lazyBindingSection->size != 0 ) {
1082 cmd->set_lazy_bind_off(_writer.lazyBindingSection->fileOffset);
1083 cmd->set_lazy_bind_size(_writer.lazyBindingSection->size);
1084 }
1085 if ( _writer.exportSection->size != 0 ) {
1086 cmd->set_export_off(_writer.exportSection->fileOffset);
1087 cmd->set_export_size(_writer.exportSection->size);
1088 }
1089 return p + sizeof(macho_dyld_info_command<P>);
1090}
1091
1092
1093template <typename A>
1094uint8_t* HeaderAndLoadCommandsAtom<A>::copyDyldLoadCommand(uint8_t* p) const
1095{
1096 uint32_t sz = alignedSize(sizeof(macho_dylinker_command<P>) + strlen(_options.dyldInstallPath()) + 1);
1097 macho_dylinker_command<P>* cmd = (macho_dylinker_command<P>*)p;
1098 if ( _options.outputKind() == Options::kDyld )
1099 cmd->set_cmd(LC_ID_DYLINKER);
1100 else
1101 cmd->set_cmd(LC_LOAD_DYLINKER);
1102 cmd->set_cmdsize(sz);
1103 cmd->set_name_offset();
1104 strcpy((char*)&p[sizeof(macho_dylinker_command<P>)], _options.dyldInstallPath());
1105 return p + sz;
1106}
1107
1108
1109template <typename A>
1110uint8_t* HeaderAndLoadCommandsAtom<A>::copyDylibIDLoadCommand(uint8_t* p) const
1111{
1112 uint32_t sz = alignedSize(sizeof(macho_dylib_command<P>) + strlen(_options.installPath()) + 1);
1113 macho_dylib_command<P>* cmd = (macho_dylib_command<P>*)p;
1114 cmd->set_cmd(LC_ID_DYLIB);
1115 cmd->set_cmdsize(sz);
1116 cmd->set_name_offset();
1117 cmd->set_timestamp(1); // needs to be some constant value that is different than DylibLoadCommandsAtom uses
1118 cmd->set_current_version(_options.currentVersion32());
1119 cmd->set_compatibility_version(_options.compatibilityVersion());
1120 strcpy((char*)&p[sizeof(macho_dylib_command<P>)], _options.installPath());
1121 return p + sz;
1122}
1123
1124template <typename A>
1125uint8_t* HeaderAndLoadCommandsAtom<A>::copyRoutinesLoadCommand(uint8_t* p) const
1126{
1127 pint_t initAddr = _state.entryPoint->finalAddress();
1128 if ( _state.entryPoint->isThumb() )
1129 initAddr |= 1ULL;
1130 macho_routines_command<P>* cmd = (macho_routines_command<P>*)p;
1131 cmd->set_cmd(macho_routines_command<P>::CMD);
1132 cmd->set_cmdsize(sizeof(macho_routines_command<P>));
1133 cmd->set_init_address(initAddr);
1134 return p + sizeof(macho_routines_command<P>);
1135}
1136
1137
1138template <typename A>
1139void HeaderAndLoadCommandsAtom<A>::recopyUUIDCommand()
1140{
1141 assert(_uuidCmdInOutputBuffer != NULL);
1142 _uuidCmdInOutputBuffer->set_uuid(_uuid);
1143}
1144
1145
1146template <typename A>
1147uint8_t* HeaderAndLoadCommandsAtom<A>::copyUUIDLoadCommand(uint8_t* p) const
1148{
1149 macho_uuid_command<P>* cmd = (macho_uuid_command<P>*)p;
1150 cmd->set_cmd(LC_UUID);
1151 cmd->set_cmdsize(sizeof(macho_uuid_command<P>));
1152 cmd->set_uuid(_uuid);
1153 _uuidCmdInOutputBuffer = cmd; // save for later re-write by recopyUUIDCommand()
1154 return p + sizeof(macho_uuid_command<P>);
1155}
1156
1157
1158template <typename A>
1159uint8_t* HeaderAndLoadCommandsAtom<A>::copyVersionLoadCommand(uint8_t* p) const
1160{
1161 macho_version_min_command<P>* cmd = (macho_version_min_command<P>*)p;
1162 switch (_options.platform()) {
1163 case Options::kPlatformUnknown:
1164 assert(_state.derivedPlatformLoadCommand != 0 && "unknown platform");
1165 cmd->set_cmd(_state.derivedPlatformLoadCommand);
1166 cmd->set_cmdsize(sizeof(macho_version_min_command<P>));
1167 cmd->set_version(_state.minOSVersion);
1168 cmd->set_sdk(0);
1169 break;
1170 case Options::kPlatformOSX:
1171 cmd->set_cmd(LC_VERSION_MIN_MACOSX);
1172 cmd->set_cmdsize(sizeof(macho_version_min_command<P>));
1173 cmd->set_version(_state.minOSVersion);
1174 cmd->set_sdk(_options.sdkVersion());
1175 break;
1176 case Options::kPlatformiOS:
1177 cmd->set_cmd(LC_VERSION_MIN_IPHONEOS);
1178 cmd->set_cmdsize(sizeof(macho_version_min_command<P>));
1179 cmd->set_version(_state.minOSVersion);
1180 cmd->set_sdk(_options.sdkVersion());
1181 break;
1182 case Options::kPlatformWatchOS:
1183 cmd->set_cmd(LC_VERSION_MIN_WATCHOS);
1184 cmd->set_cmdsize(sizeof(macho_version_min_command<P>));
1185 cmd->set_version(_state.minOSVersion);
1186 cmd->set_sdk(_options.sdkVersion());
1187 break;
1188#if SUPPORT_APPLE_TV
1189 case Options::kPlatform_tvOS:
1190 cmd->set_cmd(LC_VERSION_MIN_TVOS);
1191 cmd->set_cmdsize(sizeof(macho_version_min_command<P>));
1192 cmd->set_version(_state.minOSVersion);
1193 cmd->set_sdk(_options.sdkVersion());
1194 break;
1195#endif
1196 }
1197 return p + sizeof(macho_version_min_command<P>);
1198}
1199
1200template <typename A>
1201uint8_t* HeaderAndLoadCommandsAtom<A>::copySourceVersionLoadCommand(uint8_t* p) const
1202{
1203 macho_source_version_command<P>* cmd = (macho_source_version_command<P>*)p;
1204 cmd->set_cmd(LC_SOURCE_VERSION);
1205 cmd->set_cmdsize(sizeof(macho_source_version_command<P>));
1206 cmd->set_version(_options.sourceVersion());
1207 return p + sizeof(macho_source_version_command<P>);
1208}
1209
1210
1211template <>
1212uint32_t HeaderAndLoadCommandsAtom<x86>::threadLoadCommandSize() const
1213{
1214 return this->alignedSize(16 + 16*4); // base size + i386_THREAD_STATE_COUNT * 4
1215}
1216
1217template <>
1218uint8_t* HeaderAndLoadCommandsAtom<x86>::copyThreadsLoadCommand(uint8_t* p) const
1219{
1220 assert(_state.entryPoint != NULL);
1221 pint_t start = _state.entryPoint->finalAddress();
1222 macho_thread_command<P>* cmd = (macho_thread_command<P>*)p;
1223 cmd->set_cmd(LC_UNIXTHREAD);
1224 cmd->set_cmdsize(threadLoadCommandSize());
1225 cmd->set_flavor(1); // i386_THREAD_STATE
1226 cmd->set_count(16); // i386_THREAD_STATE_COUNT;
1227 cmd->set_thread_register(10, start);
1228 if ( _options.hasCustomStack() )
1229 cmd->set_thread_register(7, _options.customStackAddr()); // r1
1230 return p + threadLoadCommandSize();
1231}
1232
1233template <>
1234uint32_t HeaderAndLoadCommandsAtom<x86_64>::threadLoadCommandSize() const
1235{
1236 return this->alignedSize(16 + 42*4); // base size + x86_THREAD_STATE64_COUNT * 4
1237}
1238
1239template <>
1240uint8_t* HeaderAndLoadCommandsAtom<x86_64>::copyThreadsLoadCommand(uint8_t* p) const
1241{
1242 assert(_state.entryPoint != NULL);
1243 pint_t start = _state.entryPoint->finalAddress();
1244 macho_thread_command<P>* cmd = (macho_thread_command<P>*)p;
1245 cmd->set_cmd(LC_UNIXTHREAD);
1246 cmd->set_cmdsize(threadLoadCommandSize());
1247 cmd->set_flavor(4); // x86_THREAD_STATE64
1248 cmd->set_count(42); // x86_THREAD_STATE64_COUNT
1249 cmd->set_thread_register(16, start); // rip
1250 if ( _options.hasCustomStack() )
1251 cmd->set_thread_register(7, _options.customStackAddr()); // r1
1252 return p + threadLoadCommandSize();
1253}
1254
1255template <>
1256uint32_t HeaderAndLoadCommandsAtom<arm>::threadLoadCommandSize() const
1257{
1258 return this->alignedSize(16 + 17 * 4); // base size + ARM_THREAD_STATE_COUNT * 4
1259}
1260
1261template <>
1262uint8_t* HeaderAndLoadCommandsAtom<arm>::copyThreadsLoadCommand(uint8_t* p) const
1263{
1264 assert(_state.entryPoint != NULL);
1265 pint_t start = _state.entryPoint->finalAddress();
1266 if ( _state.entryPoint->isThumb() )
1267 start |= 1ULL;
1268 macho_thread_command<P>* cmd = (macho_thread_command<P>*)p;
1269 cmd->set_cmd(LC_UNIXTHREAD);
1270 cmd->set_cmdsize(threadLoadCommandSize());
1271 cmd->set_flavor(1);
1272 cmd->set_count(17);
1273 cmd->set_thread_register(15, start); // pc
1274 if ( _options.hasCustomStack() )
1275 cmd->set_thread_register(13, _options.customStackAddr()); // sp
1276 return p + threadLoadCommandSize();
1277}
1278
1279
1280template <>
1281uint32_t HeaderAndLoadCommandsAtom<arm64>::threadLoadCommandSize() const
1282{
1283 return this->alignedSize(16 + 34 * 8); // base size + ARM_EXCEPTION_STATE64_COUNT * 4
1284}
1285
1286template <>
1287uint8_t* HeaderAndLoadCommandsAtom<arm64>::copyThreadsLoadCommand(uint8_t* p) const
1288{
1289 assert(_state.entryPoint != NULL);
1290 pint_t start = _state.entryPoint->finalAddress();
1291 macho_thread_command<P>* cmd = (macho_thread_command<P>*)p;
1292 cmd->set_cmd(LC_UNIXTHREAD);
1293 cmd->set_cmdsize(threadLoadCommandSize());
1294 cmd->set_flavor(6); // ARM_THREAD_STATE64
1295 cmd->set_count(68); // ARM_EXCEPTION_STATE64_COUNT
1296 cmd->set_thread_register(32, start); // pc
1297 if ( _options.hasCustomStack() )
1298 cmd->set_thread_register(31, _options.customStackAddr()); // sp
1299 return p + threadLoadCommandSize();
1300}
1301
1302
1303template <typename A>
1304uint8_t* HeaderAndLoadCommandsAtom<A>::copyEntryPointLoadCommand(uint8_t* p) const
1305{
1306 macho_entry_point_command<P>* cmd = (macho_entry_point_command<P>*)p;
1307 cmd->set_cmd(LC_MAIN);
1308 cmd->set_cmdsize(sizeof(macho_entry_point_command<P>));
1309 assert(_state.entryPoint != NULL);
1310 pint_t start = _state.entryPoint->finalAddress();
1311 if ( _state.entryPoint->isThumb() )
1312 start |= 1ULL;
1313 cmd->set_entryoff(start - this->finalAddress());
1314 cmd->set_stacksize(_options.hasCustomStack() ? _options.customStackSize() : 0 );
1315 return p + sizeof(macho_entry_point_command<P>);
1316}
1317
1318
1319template <typename A>
1320uint8_t* HeaderAndLoadCommandsAtom<A>::copyEncryptionLoadCommand(uint8_t* p) const
1321{
1322 macho_encryption_info_command<P>* cmd = (macho_encryption_info_command<P>*)p;
1323 cmd->set_cmd(sizeof(typename A::P::uint_t) == 4 ? LC_ENCRYPTION_INFO : LC_ENCRYPTION_INFO_64);
1324 cmd->set_cmdsize(sizeof(macho_encryption_info_command<P>));
1325 assert(_writer.encryptedTextStartOffset() != 0);
1326 assert(_writer.encryptedTextEndOffset() != 0);
1327 cmd->set_cryptoff(_writer.encryptedTextStartOffset());
1328 cmd->set_cryptsize(_writer.encryptedTextEndOffset()-_writer.encryptedTextStartOffset());
1329 cmd->set_cryptid(0);
1330 return p + sizeof(macho_encryption_info_command<P>);
1331}
1332
1333
1334template <typename A>
1335uint8_t* HeaderAndLoadCommandsAtom<A>::copySplitSegInfoLoadCommand(uint8_t* p) const
1336{
1337 macho_linkedit_data_command<P>* cmd = (macho_linkedit_data_command<P>*)p;
1338 cmd->set_cmd(LC_SEGMENT_SPLIT_INFO);
1339 cmd->set_cmdsize(sizeof(macho_linkedit_data_command<P>));
1340 cmd->set_dataoff(_writer.splitSegInfoSection->fileOffset);
1341 cmd->set_datasize(_writer.splitSegInfoSection->size);
1342 return p + sizeof(macho_linkedit_data_command<P>);
1343}
1344
1345
1346template <typename A>
1347uint8_t* HeaderAndLoadCommandsAtom<A>::copyDylibLoadCommand(uint8_t* p, const ld::dylib::File* dylib) const
1348{
1349 uint32_t sz = alignedSize(sizeof(macho_dylib_command<P>) + strlen(dylib->installPath()) + 1);
1350 macho_dylib_command<P>* cmd = (macho_dylib_command<P>*)p;
1351 if ( dylib->willBeLazyLoadedDylib() )
1352 cmd->set_cmd(LC_LAZY_LOAD_DYLIB);
1353 else if ( dylib->forcedWeakLinked() || dylib->allSymbolsAreWeakImported() )
1354 cmd->set_cmd(LC_LOAD_WEAK_DYLIB);
1355 else if ( dylib->willBeReExported() && _options.useSimplifiedDylibReExports() )
1356 cmd->set_cmd(LC_REEXPORT_DYLIB);
1357 else if ( dylib->willBeUpwardDylib() && _options.useUpwardDylibs() )
1358 cmd->set_cmd(LC_LOAD_UPWARD_DYLIB);
1359 else
1360 cmd->set_cmd(LC_LOAD_DYLIB);
1361 cmd->set_cmdsize(sz);
1362 cmd->set_timestamp(2); // needs to be some constant value that is different than DylibIDLoadCommandsAtom uses
1363 cmd->set_current_version(dylib->currentVersion());
1364 cmd->set_compatibility_version(dylib->compatibilityVersion());
1365 cmd->set_name_offset();
1366 strcpy((char*)&p[sizeof(macho_dylib_command<P>)], dylib->installPath());
1367 return p + sz;
1368}
1369
1370template <typename A>
1371uint8_t* HeaderAndLoadCommandsAtom<A>::copyRPathLoadCommand(uint8_t* p, const char* path) const
1372{
1373 uint32_t sz = alignedSize(sizeof(macho_rpath_command<P>) + strlen(path) + 1);
1374 macho_rpath_command<P>* cmd = (macho_rpath_command<P>*)p;
1375 cmd->set_cmd(LC_RPATH);
1376 cmd->set_cmdsize(sz);
1377 cmd->set_path_offset();
1378 strcpy((char*)&p[sizeof(macho_rpath_command<P>)], path);
1379 return p + sz;
1380}
1381
1382template <typename A>
1383uint8_t* HeaderAndLoadCommandsAtom<A>::copySubFrameworkLoadCommand(uint8_t* p) const
1384{
1385 const char* umbrellaName = _options.umbrellaName();
1386 uint32_t sz = alignedSize(sizeof(macho_sub_framework_command<P>) + strlen(umbrellaName) + 1);
1387 macho_sub_framework_command<P>* cmd = (macho_sub_framework_command<P>*)p;
1388 cmd->set_cmd(LC_SUB_FRAMEWORK);
1389 cmd->set_cmdsize(sz);
1390 cmd->set_umbrella_offset();
1391 strcpy((char*)&p[sizeof(macho_sub_framework_command<P>)], umbrellaName);
1392 return p + sz;
1393}
1394
1395
1396template <typename A>
1397uint8_t* HeaderAndLoadCommandsAtom<A>::copyAllowableClientLoadCommand(uint8_t* p, const char* client) const
1398{
1399 uint32_t sz = alignedSize(sizeof(macho_sub_client_command<P>) + strlen(client) + 1);
1400 macho_sub_client_command<P>* cmd = (macho_sub_client_command<P>*)p;
1401 cmd->set_cmd(LC_SUB_CLIENT);
1402 cmd->set_cmdsize(sz);
1403 cmd->set_client_offset();
1404 strcpy((char*)&p[sizeof(macho_sub_client_command<P>)], client);
1405 return p + sz;
1406}
1407
1408template <typename A>
1409uint8_t* HeaderAndLoadCommandsAtom<A>::copyDyldEnvLoadCommand(uint8_t* p, const char* env) const
1410{
1411 uint32_t sz = alignedSize(sizeof(macho_dylinker_command<P>) + strlen(env) + 1);
1412 macho_dylinker_command<P>* cmd = (macho_dylinker_command<P>*)p;
1413 cmd->set_cmd(LC_DYLD_ENVIRONMENT);
1414 cmd->set_cmdsize(sz);
1415 cmd->set_name_offset();
1416 strcpy((char*)&p[sizeof(macho_dylinker_command<P>)], env);
1417 return p + sz;
1418}
1419
1420template <typename A>
1421uint8_t* HeaderAndLoadCommandsAtom<A>::copySubUmbrellaLoadCommand(uint8_t* p, const char* nm) const
1422{
1423 uint32_t sz = alignedSize(sizeof(macho_sub_umbrella_command<P>) + strlen(nm) + 1);
1424 macho_sub_umbrella_command<P>* cmd = (macho_sub_umbrella_command<P>*)p;
1425 cmd->set_cmd(LC_SUB_UMBRELLA);
1426 cmd->set_cmdsize(sz);
1427 cmd->set_sub_umbrella_offset();
1428 strcpy((char*)&p[sizeof(macho_sub_umbrella_command<P>)], nm);
1429 return p + sz;
1430}
1431
1432template <typename A>
1433uint8_t* HeaderAndLoadCommandsAtom<A>::copySubLibraryLoadCommand(uint8_t* p, const char* nm) const
1434{
1435 uint32_t sz = alignedSize(sizeof(macho_sub_library_command<P>) + strlen(nm) + 1);
1436 macho_sub_library_command<P>* cmd = (macho_sub_library_command<P>*)p;
1437 cmd->set_cmd(LC_SUB_LIBRARY);
1438 cmd->set_cmdsize(sz);
1439 cmd->set_sub_library_offset();
1440 strcpy((char*)&p[sizeof(macho_sub_library_command<P>)], nm);
1441 return p + sz;
1442}
1443
1444template <typename A>
1445uint8_t* HeaderAndLoadCommandsAtom<A>::copyFunctionStartsLoadCommand(uint8_t* p) const
1446{
1447 macho_linkedit_data_command<P>* cmd = (macho_linkedit_data_command<P>*)p;
1448 cmd->set_cmd(LC_FUNCTION_STARTS);
1449 cmd->set_cmdsize(sizeof(macho_linkedit_data_command<P>));
1450 cmd->set_dataoff(_writer.functionStartsSection->fileOffset);
1451 cmd->set_datasize(_writer.functionStartsSection->size);
1452 return p + sizeof(macho_linkedit_data_command<P>);
1453}
1454
1455
1456template <typename A>
1457uint8_t* HeaderAndLoadCommandsAtom<A>::copyDataInCodeLoadCommand(uint8_t* p) const
1458{
1459 macho_linkedit_data_command<P>* cmd = (macho_linkedit_data_command<P>*)p;
1460 cmd->set_cmd(LC_DATA_IN_CODE);
1461 cmd->set_cmdsize(sizeof(macho_linkedit_data_command<P>));
1462 cmd->set_dataoff(_writer.dataInCodeSection->fileOffset);
1463 cmd->set_datasize(_writer.dataInCodeSection->size);
1464 return p + sizeof(macho_linkedit_data_command<P>);
1465}
1466
1467
1468template <typename A>
1469uint8_t* HeaderAndLoadCommandsAtom<A>::copyLinkerOptionsLoadCommand(uint8_t* p, const std::vector<const char*>& options) const
1470{
1471 macho_linker_option_command<P>* cmd = (macho_linker_option_command<P>*)p;
1472 cmd->set_cmd(LC_LINKER_OPTION);
1473 cmd->set_count(options.size());
1474 char* buffer = cmd->buffer();
1475 uint32_t sz = sizeof(macho_linker_option_command<P>);
1476 for (std::vector<const char*>::const_iterator it=options.begin(); it != options.end(); ++it) {
1477 const char* opt = *it;
1478 uint32_t len = strlen(opt);
1479 strcpy(buffer, opt);
1480 sz += (len + 1);
1481 buffer += (len + 1);
1482 }
1483 sz = alignedSize(sz);
1484 cmd->set_cmdsize(sz);
1485 return p + sz;
1486}
1487
1488
1489
1490template <typename A>
1491uint8_t* HeaderAndLoadCommandsAtom<A>::copyOptimizationHintsLoadCommand(uint8_t* p) const
1492{
1493 macho_linkedit_data_command<P>* cmd = (macho_linkedit_data_command<P>*)p;
1494 cmd->set_cmd(LC_LINKER_OPTIMIZATION_HINTS);
1495 cmd->set_cmdsize(sizeof(macho_linkedit_data_command<P>));
1496 cmd->set_dataoff(_writer.optimizationHintsSection->fileOffset);
1497 cmd->set_datasize(_writer.optimizationHintsSection->size);
1498 return p + sizeof(macho_linkedit_data_command<P>);
1499}
1500
1501
1502template <typename A>
1503void HeaderAndLoadCommandsAtom<A>::copyRawContent(uint8_t buffer[]) const
1504{
1505 macho_header<P>* mh = (macho_header<P>*)buffer;
1506 bzero(buffer, this->size());
1507
1508 // copy mach_header
1509 mh->set_magic(this->magic());
1510 mh->set_cputype(this->cpuType());
1511 mh->set_cpusubtype(this->cpuSubType());
1512 mh->set_filetype(this->fileType());
1513 mh->set_ncmds(this->commandsCount());
1514 mh->set_sizeofcmds(this->size()-sizeof(macho_header<P>));
1515 mh->set_flags(this->flags());
1516
1517 // copy load commands
1518 uint8_t* p = &buffer[sizeof(macho_header<P>)];
1519
1520 if ( _options.outputKind() == Options::kObjectFile )
1521 p = this->copySingleSegmentLoadCommand(p);
1522 else
1523 p = this->copySegmentLoadCommands(p, buffer);
1524
1525 if ( _hasDylibIDLoadCommand )
1526 p = this->copyDylibIDLoadCommand(p);
1527
1528 if ( _hasDyldInfoLoadCommand )
1529 p = this->copyDyldInfoLoadCommand(p);
1530
1531 if ( _hasSymbolTableLoadCommand )
1532 p = this->copySymbolTableLoadCommand(p, buffer);
1533
1534 if ( _hasDynamicSymbolTableLoadCommand )
1535 p = this->copyDynamicSymbolTableLoadCommand(p);
1536
1537 if ( _hasDyldLoadCommand )
1538 p = this->copyDyldLoadCommand(p);
1539
1540 if ( _hasRoutinesLoadCommand )
1541 p = this->copyRoutinesLoadCommand(p);
1542
1543 if ( _hasUUIDLoadCommand )
1544 p = this->copyUUIDLoadCommand(p);
1545
1546 if ( _hasVersionLoadCommand )
1547 p = this->copyVersionLoadCommand(p);
1548
1549 if ( _hasSourceVersionLoadCommand )
1550 p = this->copySourceVersionLoadCommand(p);
1551
1552 if ( _hasThreadLoadCommand )
1553 p = this->copyThreadsLoadCommand(p);
1554
1555 if ( _hasEntryPointLoadCommand )
1556 p = this->copyEntryPointLoadCommand(p);
1557
1558 if ( _hasEncryptionLoadCommand )
1559 p = this->copyEncryptionLoadCommand(p);
1560
1561 if ( _hasSplitSegInfoLoadCommand )
1562 p = this->copySplitSegInfoLoadCommand(p);
1563
1564 for (uint32_t ord=1; ord <= _writer.dylibCount(); ++ord) {
1565 p = this->copyDylibLoadCommand(p, _writer.dylibByOrdinal(ord));
1566 }
1567
1568 if ( _hasRPathLoadCommands ) {
1569 const std::vector<const char*>& rpaths = _options.rpaths();
1570 for (std::vector<const char*>::const_iterator it = rpaths.begin(); it != rpaths.end(); ++it) {
1571 p = this->copyRPathLoadCommand(p, *it);
1572 }
1573 }
1574
1575 if ( _hasSubFrameworkLoadCommand )
1576 p = this->copySubFrameworkLoadCommand(p);
1577
1578 for (std::vector<const char*>::const_iterator it = _subLibraryNames.begin(); it != _subLibraryNames.end(); ++it) {
1579 p = this->copySubLibraryLoadCommand(p, *it);
1580 }
1581
1582 for (std::vector<const char*>::const_iterator it = _subUmbrellaNames.begin(); it != _subUmbrellaNames.end(); ++it) {
1583 p = this->copySubUmbrellaLoadCommand(p, *it);
1584 }
1585
1586 if ( _allowableClientLoadCommmandsCount != 0 ) {
1587 const std::vector<const char*>& clients = _options.allowableClients();
1588 for (std::vector<const char*>::const_iterator it = clients.begin(); it != clients.end(); ++it) {
1589 p = this->copyAllowableClientLoadCommand(p, *it);
1590 }
1591 }
1592
1593 if ( _dyldEnvironExrasCount != 0 ) {
1594 const std::vector<const char*>& extras = _options.dyldEnvironExtras();
1595 for (std::vector<const char*>::const_iterator it = extras.begin(); it != extras.end(); ++it) {
1596 p = this->copyDyldEnvLoadCommand(p, *it);
1597 }
1598 }
1599
1600 if ( _hasFunctionStartsLoadCommand )
1601 p = this->copyFunctionStartsLoadCommand(p);
1602
1603 if ( _hasDataInCodeLoadCommand )
1604 p = this->copyDataInCodeLoadCommand(p);
1605
1606 if ( !_linkerOptions.empty() ) {
1607 for (ld::relocatable::File::LinkerOptionsList::const_iterator it = _linkerOptions.begin(); it != _linkerOptions.end(); ++it) {
1608 p = this->copyLinkerOptionsLoadCommand(p, *it);
1609 }
1610 }
1611
1612 if ( _hasOptimizationHints )
1613 p = this->copyOptimizationHintsLoadCommand(p);
1614
1615}
1616
1617
1618
1619} // namespace tool
1620} // namespace ld
1621
1622#endif // __HEADER_LOAD_COMMANDS_HPP__