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