]> git.saurik.com Git - apple/ld64.git/blame - src/ld/passes/bitcode_bundle.cpp
ld64-409.12.tar.gz
[apple/ld64.git] / src / ld / passes / bitcode_bundle.cpp
CommitLineData
eaf282aa
A
1/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
2 *
3 * Copyright (c) 2010 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#include <stdio.h>
26#include <stdlib.h>
27#include <fcntl.h>
28#include <vector>
29#include <dlfcn.h>
30#include <math.h>
31#include <unistd.h>
32#include <time.h>
33#include <unordered_map>
fb9a160c 34#include <sstream>
eaf282aa
A
35
36#include "llvm-c/lto.h"
37// c header
38extern "C" {
39#include <xar/xar.h>
40}
41
42#include "bitcode_bundle.h"
43
44#include "Options.h"
45#include "ld.hpp"
46#include "Bitcode.hpp"
47#include "macho_relocatable_file.h"
48
49
50namespace ld {
51namespace passes {
52namespace bitcode_bundle {
53
54class BitcodeTempFile;
55
56class BitcodeAtom : public ld::Atom {
57 static ld::Section bitcodeBundleSection;
58public:
59 BitcodeAtom();
60 BitcodeAtom(BitcodeTempFile& tempfile);
61 ~BitcodeAtom() { free(_content); }
62 virtual ld::File* file() const { return NULL; }
63 virtual const char* name() const { return "bitcode bundle"; }
64 virtual uint64_t size() const { return _size; }
65 virtual uint64_t objectAddress() const { return 0; }
66 virtual void copyRawContent(uint8_t buffer[]) const
67 { memcpy(buffer, _content, _size); }
68 virtual void setScope(Scope) { }
69
70private:
71 uint8_t* _content;
72 uint64_t _size;
73};
74
75ld::Section BitcodeAtom::bitcodeBundleSection("__LLVM", "__bundle", ld::Section::typeSectCreate);
76
77class BitcodeTempFile {
78public:
79 BitcodeTempFile(const char* path, bool deleteAfterRead);
80 ~BitcodeTempFile();
81 uint8_t* getContent() const { return _content; }
82 uint64_t getSize() const { return _size; }
83private:
84 friend class BitcodeAtom;
85 const char* _path;
86 uint8_t* _content;
87 uint64_t _size;
88 bool _deleteAfterRead;
89};
90
91class BitcodeObfuscator {
92public:
93 BitcodeObfuscator();
94 ~BitcodeObfuscator();
95
96 void addMustPreserveSymbols(const char* name);
fb9a160c 97 void addAsmSymbolsToMustPreserve(lto_module_t module);
eaf282aa
A
98 void bitcodeHideSymbols(ld::Bitcode* bc, const char* filePath, const char* outputPath);
99 void writeSymbolMap(const char* outputPath);
fb9a160c 100 const char* lookupHiddenName(const char* symbol);
eaf282aa
A
101private:
102 typedef void (*lto_codegen_func_t) (lto_code_gen_t);
103 typedef void (*lto_codegen_output_t) (lto_code_gen_t, const char*);
fb9a160c
A
104 typedef const char* (*lto_codegen_lookup_t) (lto_code_gen_t, const char*);
105 typedef unsigned int (*lto_module_num_symbols) (lto_module_t);
106 typedef const char* (*lto_module_symbol_name) (lto_module_t, unsigned int);
eaf282aa
A
107
108 lto_code_gen_t _obfuscator;
109 lto_codegen_func_t _lto_hide_symbols;
110 lto_codegen_func_t _lto_reset_context;
111 lto_codegen_output_t _lto_write_reverse_map;
fb9a160c
A
112 lto_codegen_lookup_t _lto_lookup_hidden_name;
113 lto_module_num_symbols _lto_get_asm_symbol_num;
114 lto_module_symbol_name _lto_get_asm_symbol_name;
eaf282aa
A
115};
116
117class FileHandler {
118 // generic handler for files in a bundle
119public:
120 virtual void populateMustPreserveSymbols(BitcodeObfuscator* _obfuscator) { }
fb9a160c
A
121 virtual void obfuscateAndWriteToPath(BitcodeObfuscator* _obfuscator, const char* path);
122 virtual const char* compressionMethod() { return XAR_OPT_VAL_NONE; } // no compression by default
eaf282aa
A
123 xar_file_t getXARFile() { return _xar_file; }
124
125 FileHandler(char* content, size_t size) :
126 _parent(NULL), _xar_file(NULL), _file_buffer(content), _file_size(size) { } // eager construct
127 FileHandler(xar_t parent, xar_file_t xar_file) :
128 _parent(parent), _xar_file(xar_file), _file_buffer(NULL), _file_size(0) { } // lazy construct
129 virtual ~FileHandler() { }
130
131protected:
132 void initFile() {
133 if (!_file_buffer) {
134 if (xar_extract_tobuffersz(_parent, _xar_file, &_file_buffer, &_file_size) != 0)
135 throwf("could not extract files from bitcode bundle");
136 }
137 }
138 void destroyFile() {
139 if (_parent)
140 free(_file_buffer);
141 }
142
143 xar_t _parent;
144 xar_file_t _xar_file;
145 char* _file_buffer;
146 size_t _file_size;
147};
148
149class BundleHandler : public FileHandler {
150public:
151 BundleHandler(char* bundleContent, size_t bundleSize, const Options& options) :
152 FileHandler(bundleContent, bundleSize), _xar(NULL), _temp_dir(NULL), _options(options) { }
153 BundleHandler(xar_t parent, xar_file_t xar_file, const Options& options) :
154 FileHandler(parent, xar_file), _xar(NULL), _temp_dir(NULL), _options(options) { }
155
156 ~BundleHandler();
157
158 virtual void populateMustPreserveSymbols(BitcodeObfuscator* obfuscator) override;
159 virtual void obfuscateAndWriteToPath(BitcodeObfuscator* obfuscator, const char* path) override;
160
161private:
162 void init();
163 void copyXARProp(xar_file_t src, xar_file_t dst);
164
165 xar_t _xar;
166 char* _temp_dir;
167 const Options& _options;
168 std::vector<FileHandler*> _handlers;
169};
170
171class BitcodeHandler : public FileHandler {
172public:
173 BitcodeHandler(char* content, size_t size) : FileHandler(content, size) { }
174 BitcodeHandler(xar_t parent, xar_file_t xar_file) : FileHandler(parent, xar_file) { }
175
176 ~BitcodeHandler();
177
fb9a160c 178 virtual void populateMustPreserveSymbols(BitcodeObfuscator* obfuscator) override;
eaf282aa
A
179 virtual void obfuscateAndWriteToPath(BitcodeObfuscator* obfuscator, const char* path) override;
180};
181
182class ObjectHandler : public FileHandler {
183public:
184 ObjectHandler(char* content, size_t size) :
185 FileHandler(content, size) { }
186 ObjectHandler(xar_t parent, xar_file_t xar_file) :
187 FileHandler(parent, xar_file) { }
188
189 ~ObjectHandler();
190
fb9a160c 191 virtual void populateMustPreserveSymbols(BitcodeObfuscator* obfuscator) override;
eaf282aa
A
192
193};
194
fb9a160c
A
195class SymbolListHandler : public FileHandler {
196public:
197 SymbolListHandler(char* content, size_t size) :
198 FileHandler(content, size) { }
199 SymbolListHandler(xar_t parent, xar_file_t xar_file) :
200 FileHandler(parent, xar_file) { }
201
202 ~SymbolListHandler();
203
204 virtual void obfuscateAndWriteToPath(BitcodeObfuscator* obfuscator, const char* path) override;
205 virtual const char* compressionMethod() override { return XAR_OPT_VAL_GZIP; }
206};
207
eaf282aa
A
208
209class BitcodeBundle {
210public:
211 BitcodeBundle(const Options& opts, ld::Internal& internal) :
212 _options(opts), _state(internal) { }
213 ~BitcodeBundle() { }
214 void doPass();
215
216private:
217 const Options& _options;
218 ld::Internal& _state;
219};
220
82b4b32b
A
221#if LTO_API_VERSION >= 7
222static void ltoDiagnosticHandler(lto_codegen_diagnostic_severity_t severity, const char* message, void*)
223{
224 switch ( severity ) {
225#if LTO_API_VERSION >= 10
226 case LTO_DS_REMARK:
227#endif
228 case LTO_DS_NOTE:
229 break; // ignore remarks and notes
230 case LTO_DS_WARNING:
231 warning("%s", message);
232 break;
233 case LTO_DS_ERROR:
234 throwf("%s", message);
235 }
236}
237#endif
238
239
eaf282aa
A
240BitcodeAtom::BitcodeAtom()
241: ld::Atom(bitcodeBundleSection,
242 ld::Atom::definitionRegular, ld::Atom::combineNever,
243 ld::Atom::scopeTranslationUnit, ld::Atom::typeUnclassified,
244 ld::Atom::symbolTableNotIn, true, false, false, ld::Atom::Alignment(0)),
245 _size(1)
246{
247 // initialize a marker of 1 byte
248 _content = (uint8_t*)calloc(1,1);
249}
250
251BitcodeAtom::BitcodeAtom(BitcodeTempFile& tempfile)
252 : ld::Atom(bitcodeBundleSection,
253 ld::Atom::definitionRegular, ld::Atom::combineNever,
254 ld::Atom::scopeTranslationUnit, ld::Atom::typeUnclassified,
255 ld::Atom::symbolTableNotIn, true, false, false, ld::Atom::Alignment(0)),
256 _content(tempfile._content), _size(tempfile._size)
257{
258 // Creating the Atom will transfer the ownership of the buffer from Tempfile to Atom
259 tempfile._content = NULL;
260}
261
262BitcodeTempFile::BitcodeTempFile(const char* path, bool deleteAfterRead = true)
263 : _path(path), _deleteAfterRead(deleteAfterRead)
264{
265 int fd = ::open(path, O_RDONLY, 0);
266 if ( fd == -1 )
267 throwf("could not open bitcode temp file: %s", path);
268 struct stat stat_buf;
269 ::fstat(fd, &stat_buf);
270 _content = (uint8_t*)malloc(stat_buf.st_size);
271 if ( _content == NULL )
272 throwf("could not process bitcode temp file: %s", path);
273 if ( read(fd, _content, stat_buf.st_size) != stat_buf.st_size )
274 throwf("could not read bitcode temp file: %s", path);
275 ::close(fd);
276 _size = stat_buf.st_size;
277}
278
279BitcodeTempFile::~BitcodeTempFile()
280{
281 free(_content);
282 if ( _deleteAfterRead ) {
283 if ( ::unlink(_path) != 0 )
284 throwf("could not remove temp file: %s", _path);
285 }
286}
287
288BitcodeObfuscator::BitcodeObfuscator()
289{
ec29ba20
A
290#if LTO_API_VERSION < 11
291 throwf("compile-time libLTO (%d) didn't support -bitcode_hide_symbols", LTO_API_VERSION);
292#else
eaf282aa
A
293 // check if apple internal libLTO is used
294 if ( ::lto_get_version() == NULL )
295 throwf("libLTO is not loaded");
296 _lto_hide_symbols = (lto_codegen_func_t) dlsym(RTLD_DEFAULT, "lto_codegen_hide_symbols");
297 _lto_write_reverse_map = (lto_codegen_output_t) dlsym(RTLD_DEFAULT, "lto_codegen_write_symbol_reverse_map");
298 _lto_reset_context = (lto_codegen_func_t) dlsym(RTLD_DEFAULT, "lto_codegen_reset_context");
fb9a160c
A
299 _lto_lookup_hidden_name = (lto_codegen_lookup_t) dlsym(RTLD_DEFAULT, "lto_codegen_lookup_hidden_name");
300 _lto_get_asm_symbol_num = (lto_module_num_symbols) dlsym(RTLD_DEFAULT, "lto_module_get_num_asm_symbols");
301 _lto_get_asm_symbol_name = (lto_module_symbol_name) dlsym(RTLD_DEFAULT, "lto_module_get_asm_symbol_name");
eaf282aa 302 if ( _lto_hide_symbols == NULL || _lto_write_reverse_map == NULL ||
fb9a160c
A
303 _lto_reset_context == NULL || _lto_lookup_hidden_name == NULL ||
304 _lto_get_asm_symbol_num == NULL || _lto_get_asm_symbol_name == NULL || ::lto_api_version() < 14 )
eaf282aa
A
305 throwf("loaded libLTO doesn't support -bitcode_hide_symbols: %s", ::lto_get_version());
306 _obfuscator = ::lto_codegen_create_in_local_context();
82b4b32b
A
307
308#if LTO_API_VERSION >= 7
309 lto_codegen_set_diagnostic_handler(_obfuscator, ltoDiagnosticHandler, NULL);
310#endif
311
ec29ba20 312 #if LTO_API_VERSION >= 14
eaf282aa 313 lto_codegen_set_should_internalize(_obfuscator, false);
ec29ba20 314 #endif
eaf282aa
A
315#endif
316}
317
ec29ba20 318
eaf282aa
A
319BitcodeObfuscator::~BitcodeObfuscator()
320{
321 ::lto_codegen_dispose(_obfuscator);
322}
323
324void BitcodeObfuscator::addMustPreserveSymbols(const char* name)
325{
326 ::lto_codegen_add_must_preserve_symbol(_obfuscator, name);
327}
328
329void BitcodeObfuscator::bitcodeHideSymbols(ld::Bitcode* bc, const char* filePath, const char* outputPath)
330{
331#if LTO_API_VERSION >= 13 && LTO_APPLE_INTERNAL
332 lto_module_t module = ::lto_module_create_in_codegen_context(bc->getContent(), bc->getSize(), filePath, _obfuscator);
333 if ( module == NULL )
ec29ba20
A
334 throwf("could not reparse object file %s in bitcode bundle: '%s', using libLTO version '%s'",
335 filePath, ::lto_get_error_message(), ::lto_get_version());
eaf282aa
A
336 ::lto_codegen_set_module(_obfuscator, module);
337 (*_lto_hide_symbols)(_obfuscator);
338#if LTO_API_VERSION >= 15
339 ::lto_codegen_set_should_embed_uselists(_obfuscator, true);
340#endif
341 ::lto_codegen_write_merged_modules(_obfuscator, outputPath);
342 (*_lto_reset_context)(_obfuscator);
343#endif
344 return;
345}
346
347void BitcodeObfuscator::writeSymbolMap(const char *outputPath)
348{
349 (*_lto_write_reverse_map)(_obfuscator, outputPath);
350}
351
fb9a160c
A
352const char* BitcodeObfuscator::lookupHiddenName(const char *symbol)
353{
354 return (*_lto_lookup_hidden_name)(_obfuscator, symbol);
355}
356
357void BitcodeObfuscator::addAsmSymbolsToMustPreserve(lto_module_t module)
358{
359 for (unsigned int i = 0; i < _lto_get_asm_symbol_num(module); ++ i) {
360 addMustPreserveSymbols(_lto_get_asm_symbol_name(module, i));
361 }
362}
363
eaf282aa
A
364BundleHandler::~BundleHandler()
365{
366 // free buffers
367 destroyFile();
368 // free handlers
369 for (auto handler : _handlers)
370 delete handler;
371
372 // delete temp file if not -save-temps
373 if ( _xar ) {
374 xar_close(_xar);
375 std::string oldXARPath = std::string(_temp_dir) + std::string("/bundle.xar");
376 if ( !_options.saveTempFiles() && ::unlink(oldXARPath.c_str()) != 0)
377 warning("could not delete temp file: %s", oldXARPath.c_str());
378 }
379
380 if ( _temp_dir ) {
381 if ( !_options.saveTempFiles() && ::rmdir(_temp_dir) != 0 )
382 warning("could not delete temp directory: %s", _temp_dir);
383 free(_temp_dir);
384 }
385}
386
387BitcodeHandler::~BitcodeHandler()
388{
389 destroyFile();
390}
391
392ObjectHandler::~ObjectHandler()
393{
394 destroyFile();
395}
396
fb9a160c
A
397SymbolListHandler::~SymbolListHandler()
398{
399 destroyFile();
400}
401
eaf282aa
A
402void BundleHandler::init()
403{
404 if ( _xar != NULL )
405 return;
406
407 // make temp directory
408 const char* finalOutput = _options.outputFilePath();
409 _temp_dir = (char*)malloc(PATH_MAX * sizeof(char));
410 // Check outputFilePath.bundle-XXXXXX/YYYYYYYYYY.bc will not over flow PATH_MAX
411 // If so, fall back to /tmp
412 if ( strlen(finalOutput) + 30 >= PATH_MAX )
413 sprintf(_temp_dir, "/tmp/ld.bundle.XXXXXX");
414 else
415 sprintf(_temp_dir, "%s.bundle.XXXXXX", finalOutput);
416 ::mkdtemp(_temp_dir);
417
418 // write the bundle to the temp_directory
419 initFile();
420 std::string oldXARPath = std::string(_temp_dir) + std::string("/bundle.xar");
421 int f = ::open(oldXARPath.c_str(), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
422 if ( f == -1 )
423 throwf("could not write file to temp directory: %s", _temp_dir);
424 if ( ::write(f, _file_buffer, _file_size) != (int)_file_size )
425 throwf("failed to write content to temp file: %s", oldXARPath.c_str());
426 ::close(f);
427
428 // read the xar file
429 _xar = xar_open(oldXARPath.c_str(), READ);
ec29ba20
A
430 if ( _xar == NULL )
431 throwf("malformed bundle format");
eaf282aa
A
432
433 // Init the vector of handler
434 xar_iter_t iter = xar_iter_new();
435 if ( !iter )
436 throwf("could not aquire iterator for the bitcode bundle");
437 for ( xar_file_t f = xar_file_first(_xar, iter); f; f = xar_file_next(iter) ) {
438 const char* filetype = NULL;
439 if ( xar_prop_get(f, "file-type", &filetype) != 0 )
440 throwf("could not get the file type for the bitcode bundle");
441 if ( strcmp(filetype, "Bundle") == 0 )
442 _handlers.push_back(new BundleHandler(_xar, f, _options));
443 else if ( strcmp(filetype, "Object") == 0 )
444 _handlers.push_back(new ObjectHandler(_xar, f));
445 else if ( strcmp(filetype, "Bitcode") == 0 || strcmp(filetype, "LTO") == 0 )
446 _handlers.push_back(new BitcodeHandler(_xar, f));
fb9a160c
A
447 else if ( strcmp(filetype, "Exports") == 0 || strcmp(filetype, "OrderFile") == 0)
448 _handlers.push_back(new SymbolListHandler(_xar, f));
eaf282aa 449 else
fb9a160c 450 _handlers.push_back(new FileHandler(_xar, f));
eaf282aa
A
451 }
452 xar_iter_free(iter);
453}
454
455void BundleHandler::copyXARProp(xar_file_t src, xar_file_t dst)
456{
457 // copy the property in the XAR.
458 // Since XAR API can only get the first value from the key,
459 // Deleting the value after read.
460 int i = 0;
461 while (1) {
462 xar_iter_t p = xar_iter_new();
463 const char* key = xar_prop_first(src, p);
464 for (int x = 0; x < i; x++)
465 key = xar_prop_next(p);
ec29ba20
A
466 if ( !key ) {
467 xar_iter_free(p);
eaf282aa 468 break;
ec29ba20 469 }
eaf282aa
A
470 const char* val = NULL;
471 xar_prop_get(src, key, &val);
472 if ( // Info from bitcode files
473 strcmp(key, "file-type") == 0 ||
474 strcmp(key, "clang/cmd") == 0 ||
475 strcmp(key, "swift/cmd") == 0 ||
476 // Info from linker subdoc
477 strcmp(key, "version") == 0 ||
478 strcmp(key, "architecture") == 0 ||
479 strcmp(key, "hide-symbols") == 0 ||
480 strcmp(key, "platform") == 0 ||
481 strcmp(key, "sdkversion") == 0 ||
82b4b32b 482 strcmp(key, "swift-version") == 0 ||
eaf282aa
A
483 strcmp(key, "dylibs/lib") == 0 ||
484 strcmp(key, "link-options/option") == 0 ) {
485 xar_prop_create(dst, key, val);
486 xar_prop_unset(src, key);
487 } else
488 ++ i;
489 xar_iter_free(p);
490 }
491}
492
493void BundleHandler::populateMustPreserveSymbols(BitcodeObfuscator* obfuscator)
494{
495 // init the handler
496 if ( _xar == NULL )
497 init();
498
499 // iterate through the XAR file and add symbols
500 for ( auto handler : _handlers )
501 handler->populateMustPreserveSymbols(obfuscator);
502}
503
fb9a160c
A
504void BitcodeHandler::populateMustPreserveSymbols(BitcodeObfuscator* obfuscator)
505{
506 initFile();
507
508 // init LTOModule and add asm labels
ec29ba20 509#if LTO_API_VERSION < 11
fb9a160c 510 lto_module_t module = lto_module_create_from_memory(_file_buffer, _file_size);
ec29ba20
A
511#else
512 lto_module_t module = lto_module_create_in_local_context(_file_buffer, _file_size, "bitcode bundle temp file");
513#endif
514 if ( module == NULL )
515 throwf("could not reparse object file in bitcode bundle: '%s', using libLTO version '%s'",
516 ::lto_get_error_message(), ::lto_get_version());
fb9a160c
A
517 obfuscator->addAsmSymbolsToMustPreserve(module);
518 lto_module_dispose(module);
519}
520
521
eaf282aa
A
522void ObjectHandler::populateMustPreserveSymbols(BitcodeObfuscator* obfuscator)
523{
524 initFile();
525 // Parse the object file and add the symbols
526 std::vector<const char*> symbols;
527 if ( mach_o::relocatable::getNonLocalSymbols((uint8_t*)_file_buffer, symbols) ) {
528 for ( auto sym : symbols )
529 obfuscator->addMustPreserveSymbols(sym);
530 }
531}
532
533void BundleHandler::obfuscateAndWriteToPath(BitcodeObfuscator *obfuscator, const char *path)
534{
535 // init the handler
536 if ( _xar == NULL )
537 init();
538
539 // creating the new xar
540 xar_t x = xar_open(path, WRITE);
541 if (x == NULL)
542 throwf("could not open output bundle to write %s", path);
543 // Disable compression
544 if (xar_opt_set(x, XAR_OPT_COMPRESSION, XAR_OPT_VAL_NONE) != 0)
545 throwf("could not disable compression for bitcode bundle");
546
547 // iterate through the XAR file and obfuscate
548 for ( auto handler : _handlers ) {
549 const char* name = NULL;
550 xar_file_t f = handler->getXARFile();
551 if ( xar_prop_get(f, "name", &name) != 0 )
552 throwf("could not get the name of the file from bitcode bundle");
553 char outputPath[PATH_MAX];
554 sprintf(outputPath, "%s/%s", _temp_dir, name);
555 handler->obfuscateAndWriteToPath(obfuscator, outputPath);
556 BitcodeTempFile* bcOut = new BitcodeTempFile(outputPath, !_options.saveTempFiles());
fb9a160c
A
557 if ( xar_opt_set(x, XAR_OPT_COMPRESSION, handler->compressionMethod()) != 0 )
558 throwf("could not set compression type for exports list");
eaf282aa 559 xar_file_t bcEntry = xar_add_frombuffer(x, NULL, name, (char*)bcOut->getContent(), bcOut->getSize());
fb9a160c
A
560 if ( bcEntry == NULL )
561 throwf("could not add file to the bundle");
562 if ( xar_opt_set(x, XAR_OPT_COMPRESSION, XAR_OPT_VAL_NONE) != 0 )
563 throwf("could not reset compression type for exports list");
eaf282aa
A
564 copyXARProp(f, bcEntry);
565 delete bcOut;
566 }
567
568 // copy the subdoc as well
569 for ( xar_subdoc_t sub = xar_subdoc_first(_xar); sub; sub = xar_subdoc_next(sub) ) {
570 const char *name = xar_subdoc_name(sub);
571 xar_subdoc_t newDoc = xar_subdoc_new(x, name);
572 copyXARProp((xar_file_t) sub, (xar_file_t) newDoc);
573 }
574 xar_close(x);
575}
576
577void BitcodeHandler::obfuscateAndWriteToPath(BitcodeObfuscator *obfuscator, const char *path)
578{
579 initFile();
580 ld::Bitcode bc((uint8_t*)_file_buffer, _file_size);
581 obfuscator->bitcodeHideSymbols(&bc, path, path);
582}
583
fb9a160c
A
584void SymbolListHandler::obfuscateAndWriteToPath(BitcodeObfuscator* obfuscator, const char* path)
585{
586 initFile();
587 // Obfuscate exported symbol list.
588 std::string exports_list;
589 for (size_t i = 0, start = 0; i < _file_size; ++i) {
590 if ( _file_buffer[i] == '\n' ) {
591 _file_buffer[i] = '\0';
592 const char* hiddenName = obfuscator->lookupHiddenName(_file_buffer + start);
593 if ( hiddenName == NULL )
594 exports_list += _file_buffer + start;
595 else
596 exports_list += hiddenName;
597 exports_list += "\n";
598 start = i + 1;
599 } else if ( _file_buffer[i] == '*' ) {
600 throwf("illegal export list found. Please rebuild your static library using -exported_symbol[s_list] with the newest Xcode");
601 }
602 }
603 exports_list += "\n";
604 int f = ::open(path, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
605 if ( f == -1 || ::write(f, exports_list.data(), exports_list.size()) != (int)exports_list.size() )
606 throwf("failed to write content to temp file: %s", path);
607 ::close(f);
608}
609
610void FileHandler::obfuscateAndWriteToPath(BitcodeObfuscator *obfuscator, const char *path)
eaf282aa
A
611{
612 initFile();
613 int f = ::open(path, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
614 if ( f == -1 || ::write(f, _file_buffer, _file_size) != (int)_file_size )
615 throwf("failed to write content to temp file: %s", path);
616 ::close(f);
617}
618
619void BitcodeBundle::doPass()
620{
dd9e569f
A
621 if ( _options.bitcodeKind() == Options::kBitcodeStrip ||
622 _options.bitcodeKind() == Options::kBitcodeAsData )
623 // if emit no bitcode or emit bitcode segment as data, no need to generate bundle.
624 return;
625 else if ( _state.embedMarkerOnly || _options.bitcodeKind() == Options::kBitcodeMarker ) {
626 // if the bitcode is just a marker,
627 // the executable will be created without bitcode section.
628 // Otherwise, create a marker.
629 if( _options.outputKind() != Options::kDynamicExecutable &&
630 _options.outputKind() != Options::kStaticExecutable ) {
631 BitcodeAtom* marker = new BitcodeAtom();
632 _state.addAtom(*marker);
633 }
eaf282aa
A
634 return;
635 }
636
637 if ( _state.filesWithBitcode.empty() && _state.ltoBitcodePath.empty() )
638 return;
639 // Create tempdir, the temp directory should be OUTPUT/main.exe.bundle-XXXXXX
640 char tempdir[PATH_MAX];
641 const char* finalOutput = _options.outputFilePath();
642 // Check outputFilePath.bundle-XXXXXX/YYYYYYYYYY.bc will not over flow PATH_MAX
643 // If so, fall back to /tmp
644 if ( strlen(finalOutput) + 30 >= PATH_MAX )
645 sprintf(tempdir, "/tmp/ld.bundle.XXXXXX");
646 else
647 sprintf(tempdir, "%s.bundle.XXXXXX", finalOutput);
648 ::mkdtemp(tempdir);
649 // A lookup map to look for BundlerHandler base on filename
650 std::unordered_map<std::string, BundleHandler*> handlerMap;
651
652 BitcodeObfuscator* obfuscator = _options.hideSymbols() ? new BitcodeObfuscator() : NULL;
653 // Build must keep symbols if we need to hide all the symbols
654 if ( _options.hideSymbols() ) {
655 // Go through all the atoms and decide if it should be obfuscated.
656 // The following symbols are kept:
657 // 1. entry point
658 // 2. undefined symbols
659 // 3. symbols must not be stripped
660 // 4. all the globals if the globals are dead_strip root (ex. dylibs)
661 // 5. there is an exported symbol list suggests the symbol should be exported
ec29ba20
A
662 // 6. weak external symbols (not auto-hide)
663 // 7. the special symbols supplied by linker
eaf282aa
A
664 for ( auto &sect : _state.sections ) {
665 for ( auto &atom : sect->atoms ) {
666 if ( atom == _state.entryPoint ||
667 atom->definition() == ld::Atom::definitionProxy ||
668 atom->symbolTableInclusion() == ld::Atom::symbolTableInAndNeverStrip ||
669 ( _options.allGlobalsAreDeadStripRoots() && atom->scope() == ld::Atom::scopeGlobal ) ||
ec29ba20
A
670 ( _options.hasExportRestrictList() && _options.shouldExport(atom->name()) ) ||
671 ( atom->combine() == ld::Atom::combineByName && atom->scope() == ld::Atom::scopeGlobal && !atom->autoHide() ) )
eaf282aa
A
672 obfuscator->addMustPreserveSymbols(atom->name());
673 }
674 }
675 // If there are assembly sources, add globals and undefined symbols from them as well
676 for ( auto &f : _state.filesWithBitcode ) {
677 if ( ld::AsmBitcode* ab = dynamic_cast<ld::AsmBitcode*>(f->getBitcode()) ) {
678 ObjectHandler objHandler((char*)ab->getContent(), ab->getSize());
679 objHandler.populateMustPreserveSymbols(obfuscator);
680 } else if ( ld::BundleBitcode* bb = dynamic_cast<ld::BundleBitcode*>(f->getBitcode()) ) {
681 BundleHandler* bh = new BundleHandler((char*)bb->getContent(), bb->getSize(), _options);
682 bh->populateMustPreserveSymbols(obfuscator);
683 handlerMap.emplace(std::string(f->path()), bh);
fb9a160c 684 } else if ( ld::LLVMBitcode* bitcode = dynamic_cast<ld::LLVMBitcode*>(f->getBitcode()) ) {
0a8dc3df
A
685 BitcodeHandler bitcodeHandler((char*)bitcode->getContent(), bitcode->getSize());
686 bitcodeHandler.populateMustPreserveSymbols(obfuscator);
eaf282aa
A
687 }
688 }
0a8dc3df
A
689 // add must preserve symbols from lto input.
690 for ( auto &f : _state.ltoBitcodePath ) {
691 BitcodeTempFile ltoTemp(f.c_str(), false); // Keep the temp file because it needs to be read in later in the pass.
692 BitcodeHandler bitcodeHandler((char*)ltoTemp.getContent(), ltoTemp.getSize());
693 bitcodeHandler.populateMustPreserveSymbols(obfuscator);
694 }
82b4b32b
A
695 // add must preserve symbols from compiler_rt input.
696 for ( auto &f : _state.filesFromCompilerRT ) {
697 std::vector<const char*> symbols;
698 if ( f->fileContent() && mach_o::relocatable::getNonLocalSymbols(f->fileContent(), symbols) ) {
699 for ( auto &sym : symbols)
700 obfuscator->addMustPreserveSymbols(sym);
701 }
702 }
0a8dc3df 703
eaf282aa
A
704 // special symbols supplied by linker
705 obfuscator->addMustPreserveSymbols("___dso_handle");
706 obfuscator->addMustPreserveSymbols("__mh_execute_header");
707 obfuscator->addMustPreserveSymbols("__mh_dylib_header");
708 obfuscator->addMustPreserveSymbols("__mh_bundle_header");
709 obfuscator->addMustPreserveSymbols("__mh_dylinker_header");
710 obfuscator->addMustPreserveSymbols("__mh_object_header");
711 obfuscator->addMustPreserveSymbols("__mh_preload_header");
ec29ba20
A
712
713 // add all the Proxy Atom linker ever created and all the undefs that are possibily dead-stripped.
714 for (auto sym : _state.allUndefProxies)
715 obfuscator->addMustPreserveSymbols(sym);
716 _state.allUndefProxies.clear();
eaf282aa
A
717 }
718
719 // Open XAR output
720 xar_t x;
721 char outFile[PATH_MAX];
722 sprintf(outFile, "%s/bundle.xar", tempdir);
723
724 // By default, it uses gzip to compress and SHA1 as checksum
725 x = xar_open(outFile, WRITE);
726 if (x == NULL)
727 throwf("could not open output bundle to write %s", outFile);
728 // Disable compression
729 if (xar_opt_set(x, XAR_OPT_COMPRESSION, XAR_OPT_VAL_NONE) != 0)
730 throwf("could not disable compression for bitcode bundle");
731
732 // Sort all the object file according to oridnal order
733 std::sort(_state.filesWithBitcode.begin(), _state.filesWithBitcode.end(),
734 [](const ld::relocatable::File* a, const ld::relocatable::File* b) {
735 return a->ordinal() < b->ordinal();
736 });
737
738 // Copy each bitcode file into archive
739 int index = 1;
740 char formatString[10];
741 sprintf(formatString, "%%0%ud", (unsigned int)log10(_state.filesWithBitcode.size()) + 1);
742 for ( auto &obj : _state.filesWithBitcode ) {
743 assert(obj->getBitcode() != NULL && "File should contain bitcode");
744 char outFilePath[16];
745 sprintf(outFilePath, formatString, index++);
746 if ( ld::LLVMBitcode* llvmbc = dynamic_cast<ld::LLVMBitcode*>(obj->getBitcode()) ) {
747 // Handle clang and swift bitcode
748 xar_file_t bcFile = NULL;
749 if ( _options.hideSymbols() && !llvmbc->isMarker() ) { // dont strip if it is just a marker
750 char tempfile[PATH_MAX];
751 sprintf(tempfile, "%s/%s.bc", tempdir, outFilePath);
752 obfuscator->bitcodeHideSymbols(llvmbc, obj->path(), tempfile);
753 BitcodeTempFile* bcTemp = new BitcodeTempFile(tempfile, !_options.saveTempFiles());
754 bcFile = xar_add_frombuffer(x, NULL, outFilePath, (char*)bcTemp->getContent(), bcTemp->getSize());
755 delete bcTemp;
756 } else {
757 bcFile = xar_add_frombuffer(x, NULL, outFilePath, (char*)const_cast<uint8_t*>(llvmbc->getContent()), llvmbc->getSize());
758 }
759 if ( bcFile == NULL )
760 throwf("could not add bitcode from %s to bitcode bundle", obj->path());
761 if ( xar_prop_set(bcFile, "file-type", "Bitcode") != 0 )
762 throwf("could not set bitcode property for %s in bitcode bundle", obj->path());
763 // Write commandline options
764 std::string tagName = std::string(llvmbc->getBitcodeName()) + std::string("/cmd");
765 for ( uint32_t i = 0; i < llvmbc->getCmdSize(); ++i ) {
766 if ( i == 0 || llvmbc->getCmdline()[i-1] == '\0' ) {
767 if ( xar_prop_create(bcFile, tagName.c_str(), (const char *)llvmbc->getCmdline() + i) )
768 throwf("could not set cmdline to XAR file");
769 }
770 }
771 }
772 else if ( ld::BundleBitcode* bundlebc = dynamic_cast<ld::BundleBitcode*>(obj->getBitcode()) ) {
773 xar_file_t bundleFile = NULL;
774 if ( _options.hideSymbols() && !bundlebc->isMarker() ) { // dont strip if it is just a marker
775 char tempfile[PATH_MAX];
776 sprintf(tempfile, "%s/%s.xar", tempdir, outFilePath);
777 auto search = handlerMap.find(std::string(obj->path()));
778 assert( search != handlerMap.end() && "Cannot find handler");
779 search->second->obfuscateAndWriteToPath(obfuscator, tempfile);
780 BitcodeTempFile* bundleTemp = new BitcodeTempFile(tempfile, !_options.saveTempFiles());
781 bundleFile = xar_add_frombuffer(x, NULL, outFilePath, (char*)bundleTemp->getContent(), bundleTemp->getSize());
782 delete bundleTemp;
783 } else {
784 bundleFile = xar_add_frombuffer(x, NULL, outFilePath,
785 (char*)const_cast<uint8_t*>(bundlebc->getContent()),
786 bundlebc->getSize());
787 }
788 if ( bundleFile == NULL )
789 throwf("could not add bitcode from the bundle %s to bitcode bundle", obj->path());
790 if ( xar_prop_set(bundleFile, "file-type", "Bundle") != 0 )
791 throwf("could not set bundle property for %s in bitcode bundle", obj->path());
792 }
793 else if ( ld::AsmBitcode* asmbc = dynamic_cast<ld::AsmBitcode*>(obj->getBitcode()) ) {
794 xar_file_t objFile = xar_add_frombuffer(x, NULL, outFilePath, (char*)asmbc->getContent(), asmbc->getSize());
795 if ( objFile == NULL )
796 throwf("could not add obj file %s to bitcode bundle", obj->path());
797 if ( xar_prop_set(objFile, "file-type", "Object") != 0 )
798 throwf("could not set object property for %s in bitcode bundle", obj->path());
799 }
800 else {
801 assert(false && "Unknown bitcode");
802 }
803 }
804
0a8dc3df 805 // Write merged LTO bitcode files
eaf282aa 806 if ( !_state.ltoBitcodePath.empty() ) {
0a8dc3df
A
807 int count = 0;
808 for (auto &path : _state.ltoBitcodePath) {
809 std::string xar_name = "lto.o." + std::to_string(count++);
810 xar_file_t ltoFile = NULL;
811 BitcodeTempFile* ltoTemp = new BitcodeTempFile(path.c_str(), !_options.saveTempFiles());
812 if ( _options.hideSymbols() ) {
eaf282aa
A
813 ld::Bitcode ltoBitcode(ltoTemp->getContent(), ltoTemp->getSize());
814 char ltoTempFile[PATH_MAX];
815 sprintf(ltoTempFile, "%s/lto.bc", tempdir);
0a8dc3df 816 obfuscator->bitcodeHideSymbols(&ltoBitcode, path.c_str(), ltoTempFile);
eaf282aa 817 BitcodeTempFile* ltoStrip = new BitcodeTempFile(ltoTempFile, !_options.saveTempFiles());
0a8dc3df 818 ltoFile = xar_add_frombuffer(x, NULL, xar_name.c_str(), (char*)ltoStrip->getContent(), ltoStrip->getSize());
eaf282aa 819 delete ltoStrip;
0a8dc3df
A
820 } else {
821 ltoFile = xar_add_frombuffer(x, NULL, xar_name.c_str(), (char*)ltoTemp->getContent(), ltoTemp->getSize());
822 }
823 if ( ltoFile == NULL )
824 throwf("could not add lto file %s to bitcode bundle", path.c_str());
825 if ( xar_prop_set(ltoFile, "file-type", "LTO") != 0 )
826 throwf("could not set bitcode property for %s in bitcode bundle", path.c_str());
827 delete ltoTemp;
eaf282aa 828 }
eaf282aa
A
829 }
830
831 // Common LinkOptions
832 std::vector<std::string> linkCmd = _options.writeBitcodeLinkOptions();
833
834 // support -sectcreate option
835 for ( auto extraSect = _options.extraSectionsBegin(); extraSect != _options.extraSectionsEnd(); ++ extraSect ) {
836 std::string sectName = std::string(extraSect->segmentName) + std::string(",") + std::string(extraSect->sectionName);
837 BitcodeTempFile* sectFile = new BitcodeTempFile(extraSect->path, false);
838 xar_file_t sectXar = xar_add_frombuffer(x, NULL, sectName.c_str(), (char*)sectFile->getContent(), sectFile->getSize());
839 if ( sectXar == NULL )
840 throwf("could not encode sectcreate file %s into bitcode bundle", extraSect->path);
841 if ( xar_prop_set(sectXar, "file-type", "Section") != 0 )
842 throwf("could not set bitcode property for %s", sectName.c_str());
843 delete sectFile;
844 linkCmd.push_back("-sectcreate");
845 linkCmd.push_back(extraSect->segmentName);
846 linkCmd.push_back(extraSect->sectionName);
847 linkCmd.push_back(sectName);
848 }
849
850 // Write exports file
fb9a160c 851 // A vector of all the exported symbols.
eaf282aa 852 if ( _options.hasExportMaskList() ) {
fb9a160c
A
853 std::vector<const char*> exportedSymbols;
854 for ( auto &sect : _state.sections ) {
855 for ( auto &atom : sect->atoms ) {
856 // The symbols should be added to the export list is the ones that are:
857 // globalScope, in SymbolTable and should be exported suggested by export file.
858 if ( atom->scope() == ld::Atom::scopeGlobal &&
859 atom->symbolTableInclusion() == ld::Atom::symbolTableIn &&
860 _options.shouldExport(atom->name()) )
861 exportedSymbols.push_back(atom->name());
862 }
863 }
eaf282aa
A
864 linkCmd.push_back("-exported_symbols_list");
865 linkCmd.push_back("exports.exp");
866 const char* exportsPath = "exports.exp";
eaf282aa 867 std::string exps;
fb9a160c
A
868 for (std::vector<const char*>::iterator it = exportedSymbols.begin();
869 it != exportedSymbols.end(); ++ it) {
eaf282aa
A
870 exps += *it;
871 exps += "\n";
872 }
873 // always append an empty line so exps cannot be empty. rdar://problem/22404253
874 exps += "\n";
fb9a160c
A
875 if (xar_opt_set(x, XAR_OPT_COMPRESSION, XAR_OPT_VAL_GZIP) != 0)
876 throwf("could not set compression type for exports list");
eaf282aa
A
877 xar_file_t exportsFile = xar_add_frombuffer(x, NULL, exportsPath, const_cast<char*>(exps.data()), exps.size());
878 if (exportsFile == NULL)
879 throwf("could not add exports list to bitcode bundle");
880 if (xar_prop_set(exportsFile, "file-type", "Exports") != 0)
881 throwf("could not set exports property in bitcode bundle");
fb9a160c
A
882 if (xar_opt_set(x, XAR_OPT_COMPRESSION, XAR_OPT_VAL_NONE) != 0)
883 throwf("could not reset compression type for exports list");
884 } else if ( _options.hasExportRestrictList() ) {
885 // handle unexported list here
886 std::vector<const char*> unexportedSymbols;
887 for ( auto &sect : _state.sections ) {
888 for ( auto &atom : sect->atoms ) {
889 // The unexported symbols should not include anything that is in TranslationUnit scope (static) or
890 // that cannot be in the SymbolTable
891 if ( atom->scope() != ld::Atom::scopeTranslationUnit &&
892 atom->symbolTableInclusion() == ld::Atom::symbolTableIn &&
893 !_options.shouldExport(atom->name()) )
894 unexportedSymbols.push_back(atom->name());
895 }
896 }
897 linkCmd.push_back("-unexported_symbols_list");
898 linkCmd.push_back("unexports.exp");
899 const char* unexportsPath = "unexports.exp";
900 std::string unexps;
901 for (std::vector<const char*>::iterator it = unexportedSymbols.begin();
902 it != unexportedSymbols.end(); ++ it) {
903 // try obfuscate the name for symbols in unexported symbols list. They are likely to be obfsucated.
904 const char* sym_name = NULL;
905 if ( _options.hideSymbols() )
906 sym_name = obfuscator->lookupHiddenName(*it);
907 if ( sym_name )
908 unexps += sym_name;
909 else
910 unexps += *it;
911 unexps += "\n";
912 }
913 unexps += "\n";
914 if (xar_opt_set(x, XAR_OPT_COMPRESSION, XAR_OPT_VAL_GZIP) != 0)
915 throwf("could not set compression type for exports list");
916 xar_file_t unexportsFile = xar_add_frombuffer(x, NULL, unexportsPath, const_cast<char*>(unexps.data()), unexps.size());
917 if (unexportsFile == NULL)
918 throwf("could not add unexports list to bitcode bundle");
919 if (xar_prop_set(unexportsFile, "file-type", "Exports") != 0)
920 throwf("could not set exports property in bitcode bundle");
921 if (xar_opt_set(x, XAR_OPT_COMPRESSION, XAR_OPT_VAL_NONE) != 0)
922 throwf("could not reset compression type for exports list");
923 }
924
925 // Handle order file. We need to obfuscate all the entries in the order file
926 if ( _options.orderedSymbolsCount() > 0 ) {
927 std::string orderFile;
928 for ( auto entry = _options.orderedSymbolsBegin(); entry != _options.orderedSymbolsEnd(); ++ entry ) {
929 std::stringstream line;
930 if ( entry->objectFileName != NULL ) {
931 unsigned index = 0;
932 for ( auto &f : _state.filesWithBitcode ) {
933 const char* atomFullPath = f->path();
934 const char* lastSlash = strrchr(atomFullPath, '/');
935 if ( (lastSlash != NULL && strcmp(&lastSlash[1], entry->objectFileName) == 0) ||
936 strcmp(atomFullPath, entry->objectFileName) == 0 )
937 break;
938 ++ index;
939 }
940 if ( index >= _state.filesWithBitcode.size() )
941 continue;
942 line << index << ".o:";
943 }
944 const char* sym_name = NULL;
945 if ( _options.hideSymbols() )
946 sym_name = obfuscator->lookupHiddenName(entry->symbolName);
947 if ( sym_name )
948 line << sym_name;
949 else
950 line << entry->symbolName;
951 line << "\n";
952 orderFile += line.str();
953 }
954 if (xar_opt_set(x, XAR_OPT_COMPRESSION, XAR_OPT_VAL_GZIP) != 0)
955 throwf("could not set compression type for order file");
956 xar_file_t ordersFile = xar_add_frombuffer(x, NULL, "file.order", const_cast<char*>(orderFile.data()), orderFile.size());
957 if (ordersFile == NULL)
958 throwf("could not add order file to bitcode bundle");
959 if (xar_prop_set(ordersFile, "file-type", "OrderFile") != 0)
960 throwf("could not set order file property in bitcode bundle");
961 if (xar_opt_set(x, XAR_OPT_COMPRESSION, XAR_OPT_VAL_NONE) != 0)
962 throwf("could not reset compression type for order file");
963 linkCmd.push_back("-order_file");
964 linkCmd.push_back("file.order");
eaf282aa
A
965 }
966
967 // Create subdoc to write link information
968 xar_subdoc_t linkXML = xar_subdoc_new(x, "Ld");
969 if ( linkXML == NULL )
970 throwf("could not create XML in bitcode bundle");
971
972 // Write version number
973 if ( xar_prop_create((xar_file_t)linkXML, "version", BITCODE_XAR_VERSION) != 0 )
974 throwf("could not add version number to bitcode bundle");
975
976 // Arch
977 if ( xar_prop_create((xar_file_t)linkXML, "architecture", _options.architectureName()) != 0 )
978 throwf("could not add achitecture name to bitcode bundle");
979
980 // Opt-out symbols
981 if ( _options.hideSymbols() ) {
982 if ( xar_prop_create((xar_file_t)linkXML, "hide-symbols", "1") != 0 )
983 throwf("could not add property to bitcode bundle");
984 }
985
986 // Write SDK version
987 if ( _options.sdkPaths().size() > 1 )
988 throwf("only one -syslibroot is accepted for bitcode bundle");
e456bf10 989 if ( xar_prop_create((xar_file_t)linkXML, "platform", _options.platforms().to_str().c_str()) != 0 )
eaf282aa
A
990 throwf("could not add platform name to bitcode bundle");
991 if ( xar_prop_create((xar_file_t)linkXML, "sdkversion", _options.getSDKVersionStr().c_str()) != 0 )
992 throwf("could not add SDK version to bitcode bundle");
993
82b4b32b
A
994 // Write swift version into header
995 if (_state.swiftVersion != 0) {
996 char swiftVersion[64];
997 Options::userReadableSwiftVersion(_state.swiftVersion, swiftVersion);
998 if ( xar_prop_create((xar_file_t)linkXML, "swift-version", swiftVersion) )
999 throwf("could not add swift version to bitcode bundle");
1000 }
1001
eaf282aa 1002 // Write dylibs
dd9e569f
A
1003 char sdkRoot[PATH_MAX];
1004 if ( _options.sdkPaths().empty() || (realpath(_options.sdkPaths().front(), sdkRoot) == NULL) )
1005 strcpy(sdkRoot, "/");
eaf282aa 1006 if ( !_state.dylibs.empty() ) {
eaf282aa
A
1007 char dylibPath[PATH_MAX];
1008 for ( auto &dylib : _state.dylibs ) {
dd9e569f
A
1009 // For every dylib/framework, figure out if it is coming from a SDK.
1010 // The dylib/framework from SDK must begin with '/' and user framework must begin with '@'.
1011 if (dylib->installPath()[0] == '/') {
1012 // Verify the path of the framework is within the SDK.
1013 char dylibRealPath[PATH_MAX];
1014 if ( realpath(dylib->path(), dylibRealPath) != NULL && strncmp(sdkRoot, dylibRealPath, strlen(sdkRoot)) != 0 )
1015 warning("%s has install name beginning with \"/\" but it is not from the specified SDK", dylib->path());
eaf282aa 1016 // The path start with a string template
dd9e569f 1017 strcpy(dylibPath, "{SDKPATH}");
eaf282aa 1018 // append the path of dylib/frameowrk in the SDK
dd9e569f 1019 strcat(dylibPath, dylib->installPath());
eaf282aa
A
1020 } else {
1021 // Not in any SDKs, then assume it is a user dylib/framework
1022 // strip off all the path in the front
1023 const char* dylib_name = strrchr(dylib->path(), '/');
1024 dylib_name = (dylib_name == NULL) ? dylib->path() : dylib_name + 1;
1025 strcpy(dylibPath, dylib_name);
1026 }
1027 if ( dylib->forcedWeakLinked() ) {
1028 if ( xar_prop_create((xar_file_t)linkXML, "dylibs/weak", dylibPath) != 0)
1029 throwf("could not add dylib options to bitcode bundle");
1030 } else {
1031 if ( xar_prop_create((xar_file_t)linkXML, "dylibs/lib", dylibPath) != 0)
1032 throwf("could not add dylib options to bitcode bundle");
1033 }
1034 }
1035 }
1036
82b4b32b
A
1037 // Write if compiler_rt is force loaded
1038 if (_state.forceLoadCompilerRT) {
1039 if ( xar_prop_create((xar_file_t)linkXML, "rt-forceload", "1") != 0 )
1040 throwf("could not add compiler_rt force_load info to bitcode bundle");
1041 }
1042
eaf282aa
A
1043 // Write link-line into archive
1044 for ( auto &it : linkCmd ) {
1045 if (xar_prop_create((xar_file_t)linkXML, "link-options/option", it.c_str()) != 0)
1046 throwf("could not add link options to bitcode bundle");
1047 }
1048 // Finish writing
1049 xar_close(x);
1050
1051 // Read the file back
1052 BitcodeTempFile* xarTemp = new BitcodeTempFile(outFile, !_options.saveTempFiles());
1053
1054 // Create an Atom and add to the list
1055 BitcodeAtom* bundleAtom = new BitcodeAtom(*xarTemp);
1056 _state.addAtom(*bundleAtom);
1057
1058 // write the reverse mapping file if required
1059 if ( _options.hideSymbols() && !_options.reverseMapTempPath().empty() )
1060 obfuscator->writeSymbolMap(_options.reverseMapTempPath().c_str());
1061
1062 // Clean up local variables
1063 delete xarTemp;
1064 delete obfuscator;
1065 for ( auto &entry: handlerMap )
1066 delete entry.second;
1067 // delete temp directory if not using -save-temps
1068 // only do so after all the BitcodeTempFiles are deleted.
1069 if ( !_options.saveTempFiles() ) {
1070 if ( ::rmdir(tempdir) != 0 )
1071 warning("temp directory cannot be removed: %s", tempdir);
1072 }
1073}
1074
1075
1076
1077// called by linker to write bitcode bundle into a mach-o section
1078void doPass(const Options& opts, ld::Internal& internal) {
1079 BitcodeBundle BB(opts, internal);
1080 BB.doPass();
1081}
1082
1083
1084} // namespace bitcode_bundle
1085} // namespace passes
1086} // namespace ld