1 //===-- gold-plugin.cpp - Plugin to gold for Link Time Optimization ------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This is a gold plugin for LLVM. It provides an LLVM implementation of the 11 // interface described in http://gcc.gnu.org/wiki/whopr/driver . 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "llvm/Config/config.h" // plugin-api.h requires HAVE_STDINT_H 16 #include "llvm-c/lto.h" 17 #include "llvm/ADT/OwningPtr.h" 18 #include "llvm/ADT/StringSet.h" 19 #include "llvm/Support/Errno.h" 20 #include "llvm/Support/FileSystem.h" 21 #include "llvm/Support/MemoryBuffer.h" 22 #include "llvm/Support/Path.h" 23 #include "llvm/Support/Program.h" 24 #include "llvm/Support/ToolOutputFile.h" 25 #include "llvm/Support/system_error.h" 26 #include <cerrno> 27 #include <cstdlib> 28 #include <cstring> 29 #include <fstream> 30 #include <list> 31 #include <plugin-api.h> 32 #include <vector> 33 34 // Support Windows/MinGW crazyness. 35 #ifdef _WIN32 36 # include <io.h> 37 # define lseek _lseek 38 # define read _read 39 #endif 40 41 #ifndef LDPO_PIE 42 // FIXME: remove this declaration when we stop maintaining Ubuntu Quantal and 43 // Precise and Debian Wheezy (binutils 2.23 is required) 44 # define LDPO_PIE 3 45 #endif 46 47 using namespace llvm; 48 49 namespace { 50 ld_plugin_status discard_message(int level, const char *format, ...) { 51 // Die loudly. Recent versions of Gold pass ld_plugin_message as the first 52 // callback in the transfer vector. This should never be called. 53 abort(); 54 } 55 56 ld_plugin_add_symbols add_symbols = NULL; 57 ld_plugin_get_symbols get_symbols = NULL; 58 ld_plugin_add_input_file add_input_file = NULL; 59 ld_plugin_add_input_library add_input_library = NULL; 60 ld_plugin_set_extra_library_path set_extra_library_path = NULL; 61 ld_plugin_get_view get_view = NULL; 62 ld_plugin_message message = discard_message; 63 64 int api_version = 0; 65 int gold_version = 0; 66 67 struct claimed_file { 68 void *handle; 69 std::vector<ld_plugin_symbol> syms; 70 }; 71 72 lto_codegen_model output_type = LTO_CODEGEN_PIC_MODEL_STATIC; 73 std::string output_name = ""; 74 std::list<claimed_file> Modules; 75 std::vector<std::string> Cleanup; 76 lto_code_gen_t code_gen = NULL; 77 StringSet<> CannotBeHidden; 78 } 79 80 namespace options { 81 enum generate_bc { BC_NO, BC_ALSO, BC_ONLY }; 82 static bool generate_api_file = false; 83 static generate_bc generate_bc_file = BC_NO; 84 static std::string bc_path; 85 static std::string obj_path; 86 static std::string extra_library_path; 87 static std::string triple; 88 static std::string mcpu; 89 // Additional options to pass into the code generator. 90 // Note: This array will contain all plugin options which are not claimed 91 // as plugin exclusive to pass to the code generator. 92 // For example, "generate-api-file" and "as"options are for the plugin 93 // use only and will not be passed. 94 static std::vector<std::string> extra; 95 96 static void process_plugin_option(const char* opt_) 97 { 98 if (opt_ == NULL) 99 return; 100 llvm::StringRef opt = opt_; 101 102 if (opt == "generate-api-file") { 103 generate_api_file = true; 104 } else if (opt.startswith("mcpu=")) { 105 mcpu = opt.substr(strlen("mcpu=")); 106 } else if (opt.startswith("extra-library-path=")) { 107 extra_library_path = opt.substr(strlen("extra_library_path=")); 108 } else if (opt.startswith("mtriple=")) { 109 triple = opt.substr(strlen("mtriple=")); 110 } else if (opt.startswith("obj-path=")) { 111 obj_path = opt.substr(strlen("obj-path=")); 112 } else if (opt == "emit-llvm") { 113 generate_bc_file = BC_ONLY; 114 } else if (opt == "also-emit-llvm") { 115 generate_bc_file = BC_ALSO; 116 } else if (opt.startswith("also-emit-llvm=")) { 117 llvm::StringRef path = opt.substr(strlen("also-emit-llvm=")); 118 generate_bc_file = BC_ALSO; 119 if (!bc_path.empty()) { 120 (*message)(LDPL_WARNING, "Path to the output IL file specified twice. " 121 "Discarding %s", opt_); 122 } else { 123 bc_path = path; 124 } 125 } else { 126 // Save this option to pass to the code generator. 127 extra.push_back(opt); 128 } 129 } 130 } 131 132 static ld_plugin_status claim_file_hook(const ld_plugin_input_file *file, 133 int *claimed); 134 static ld_plugin_status all_symbols_read_hook(void); 135 static ld_plugin_status cleanup_hook(void); 136 137 extern "C" ld_plugin_status onload(ld_plugin_tv *tv); 138 ld_plugin_status onload(ld_plugin_tv *tv) { 139 // We're given a pointer to the first transfer vector. We read through them 140 // until we find one where tv_tag == LDPT_NULL. The REGISTER_* tagged values 141 // contain pointers to functions that we need to call to register our own 142 // hooks. The others are addresses of functions we can use to call into gold 143 // for services. 144 145 bool registeredClaimFile = false; 146 147 for (; tv->tv_tag != LDPT_NULL; ++tv) { 148 switch (tv->tv_tag) { 149 case LDPT_API_VERSION: 150 api_version = tv->tv_u.tv_val; 151 break; 152 case LDPT_GOLD_VERSION: // major * 100 + minor 153 gold_version = tv->tv_u.tv_val; 154 break; 155 case LDPT_OUTPUT_NAME: 156 output_name = tv->tv_u.tv_string; 157 break; 158 case LDPT_LINKER_OUTPUT: 159 switch (tv->tv_u.tv_val) { 160 case LDPO_REL: // .o 161 case LDPO_DYN: // .so 162 case LDPO_PIE: // position independent executable 163 output_type = LTO_CODEGEN_PIC_MODEL_DYNAMIC; 164 break; 165 case LDPO_EXEC: // .exe 166 output_type = LTO_CODEGEN_PIC_MODEL_STATIC; 167 break; 168 default: 169 (*message)(LDPL_ERROR, "Unknown output file type %d", 170 tv->tv_u.tv_val); 171 return LDPS_ERR; 172 } 173 // TODO: add an option to disable PIC. 174 //output_type = LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC; 175 break; 176 case LDPT_OPTION: 177 options::process_plugin_option(tv->tv_u.tv_string); 178 break; 179 case LDPT_REGISTER_CLAIM_FILE_HOOK: { 180 ld_plugin_register_claim_file callback; 181 callback = tv->tv_u.tv_register_claim_file; 182 183 if ((*callback)(claim_file_hook) != LDPS_OK) 184 return LDPS_ERR; 185 186 registeredClaimFile = true; 187 } break; 188 case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK: { 189 ld_plugin_register_all_symbols_read callback; 190 callback = tv->tv_u.tv_register_all_symbols_read; 191 192 if ((*callback)(all_symbols_read_hook) != LDPS_OK) 193 return LDPS_ERR; 194 195 code_gen = lto_codegen_create(); 196 } break; 197 case LDPT_REGISTER_CLEANUP_HOOK: { 198 ld_plugin_register_cleanup callback; 199 callback = tv->tv_u.tv_register_cleanup; 200 201 if ((*callback)(cleanup_hook) != LDPS_OK) 202 return LDPS_ERR; 203 } break; 204 case LDPT_ADD_SYMBOLS: 205 add_symbols = tv->tv_u.tv_add_symbols; 206 break; 207 case LDPT_GET_SYMBOLS_V2: 208 get_symbols = tv->tv_u.tv_get_symbols; 209 break; 210 case LDPT_ADD_INPUT_FILE: 211 add_input_file = tv->tv_u.tv_add_input_file; 212 break; 213 case LDPT_ADD_INPUT_LIBRARY: 214 add_input_library = tv->tv_u.tv_add_input_file; 215 break; 216 case LDPT_SET_EXTRA_LIBRARY_PATH: 217 set_extra_library_path = tv->tv_u.tv_set_extra_library_path; 218 break; 219 case LDPT_GET_VIEW: 220 get_view = tv->tv_u.tv_get_view; 221 break; 222 case LDPT_MESSAGE: 223 message = tv->tv_u.tv_message; 224 break; 225 default: 226 break; 227 } 228 } 229 230 if (!registeredClaimFile) { 231 (*message)(LDPL_ERROR, "register_claim_file not passed to LLVMgold."); 232 return LDPS_ERR; 233 } 234 if (!add_symbols) { 235 (*message)(LDPL_ERROR, "add_symbols not passed to LLVMgold."); 236 return LDPS_ERR; 237 } 238 239 return LDPS_OK; 240 } 241 242 /// claim_file_hook - called by gold to see whether this file is one that 243 /// our plugin can handle. We'll try to open it and register all the symbols 244 /// with add_symbol if possible. 245 static ld_plugin_status claim_file_hook(const ld_plugin_input_file *file, 246 int *claimed) { 247 lto_module_t M; 248 const void *view; 249 OwningPtr<MemoryBuffer> buffer; 250 if (get_view) { 251 if (get_view(file->handle, &view) != LDPS_OK) { 252 (*message)(LDPL_ERROR, "Failed to get a view of %s", file->name); 253 return LDPS_ERR; 254 } 255 } else { 256 int64_t offset = 0; 257 // Gold has found what might be IR part-way inside of a file, such as 258 // an .a archive. 259 if (file->offset) { 260 offset = file->offset; 261 } 262 if (error_code ec = MemoryBuffer::getOpenFileSlice( 263 file->fd, file->name, buffer, file->filesize, offset)) { 264 (*message)(LDPL_ERROR, ec.message().c_str()); 265 return LDPS_ERR; 266 } 267 view = buffer->getBufferStart(); 268 } 269 270 if (!lto_module_is_object_file_in_memory(view, file->filesize)) 271 return LDPS_OK; 272 273 M = lto_module_create_from_memory(view, file->filesize); 274 if (!M) { 275 if (const char* msg = lto_get_error_message()) { 276 (*message)(LDPL_ERROR, 277 "LLVM gold plugin has failed to create LTO module: %s", 278 msg); 279 return LDPS_ERR; 280 } 281 return LDPS_OK; 282 } 283 284 *claimed = 1; 285 Modules.resize(Modules.size() + 1); 286 claimed_file &cf = Modules.back(); 287 288 if (!options::triple.empty()) 289 lto_module_set_target_triple(M, options::triple.c_str()); 290 291 cf.handle = file->handle; 292 unsigned sym_count = lto_module_get_num_symbols(M); 293 cf.syms.reserve(sym_count); 294 295 for (unsigned i = 0; i != sym_count; ++i) { 296 lto_symbol_attributes attrs = lto_module_get_symbol_attribute(M, i); 297 if ((attrs & LTO_SYMBOL_SCOPE_MASK) == LTO_SYMBOL_SCOPE_INTERNAL) 298 continue; 299 300 cf.syms.push_back(ld_plugin_symbol()); 301 ld_plugin_symbol &sym = cf.syms.back(); 302 sym.name = const_cast<char *>(lto_module_get_symbol_name(M, i)); 303 sym.name = strdup(sym.name); 304 sym.version = NULL; 305 306 int scope = attrs & LTO_SYMBOL_SCOPE_MASK; 307 bool CanBeHidden = scope == LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN; 308 if (!CanBeHidden) 309 CannotBeHidden.insert(sym.name); 310 switch (scope) { 311 case LTO_SYMBOL_SCOPE_HIDDEN: 312 sym.visibility = LDPV_HIDDEN; 313 break; 314 case LTO_SYMBOL_SCOPE_PROTECTED: 315 sym.visibility = LDPV_PROTECTED; 316 break; 317 case 0: // extern 318 case LTO_SYMBOL_SCOPE_DEFAULT: 319 case LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN: 320 sym.visibility = LDPV_DEFAULT; 321 break; 322 default: 323 (*message)(LDPL_ERROR, "Unknown scope attribute: %d", scope); 324 return LDPS_ERR; 325 } 326 327 int definition = attrs & LTO_SYMBOL_DEFINITION_MASK; 328 sym.comdat_key = NULL; 329 switch (definition) { 330 case LTO_SYMBOL_DEFINITION_REGULAR: 331 sym.def = LDPK_DEF; 332 break; 333 case LTO_SYMBOL_DEFINITION_UNDEFINED: 334 sym.def = LDPK_UNDEF; 335 break; 336 case LTO_SYMBOL_DEFINITION_TENTATIVE: 337 sym.def = LDPK_COMMON; 338 break; 339 case LTO_SYMBOL_DEFINITION_WEAK: 340 sym.comdat_key = sym.name; 341 sym.def = LDPK_WEAKDEF; 342 break; 343 case LTO_SYMBOL_DEFINITION_WEAKUNDEF: 344 sym.def = LDPK_WEAKUNDEF; 345 break; 346 default: 347 (*message)(LDPL_ERROR, "Unknown definition attribute: %d", definition); 348 return LDPS_ERR; 349 } 350 351 sym.size = 0; 352 353 sym.resolution = LDPR_UNKNOWN; 354 } 355 356 cf.syms.reserve(cf.syms.size()); 357 358 if (!cf.syms.empty()) { 359 if ((*add_symbols)(cf.handle, cf.syms.size(), &cf.syms[0]) != LDPS_OK) { 360 (*message)(LDPL_ERROR, "Unable to add symbols!"); 361 return LDPS_ERR; 362 } 363 } 364 365 if (code_gen) { 366 if (lto_codegen_add_module(code_gen, M)) { 367 (*message)(LDPL_ERROR, "Error linking module: %s", 368 lto_get_error_message()); 369 return LDPS_ERR; 370 } 371 } 372 373 lto_module_dispose(M); 374 375 return LDPS_OK; 376 } 377 378 static bool mustPreserve(const claimed_file &F, int i) { 379 if (F.syms[i].resolution == LDPR_PREVAILING_DEF) 380 return true; 381 if (F.syms[i].resolution == LDPR_PREVAILING_DEF_IRONLY_EXP) 382 return CannotBeHidden.count(F.syms[i].name); 383 return false; 384 } 385 386 /// all_symbols_read_hook - gold informs us that all symbols have been read. 387 /// At this point, we use get_symbols to see if any of our definitions have 388 /// been overridden by a native object file. Then, perform optimization and 389 /// codegen. 390 static ld_plugin_status all_symbols_read_hook(void) { 391 std::ofstream api_file; 392 assert(code_gen); 393 394 if (options::generate_api_file) { 395 api_file.open("apifile.txt", std::ofstream::out | std::ofstream::trunc); 396 if (!api_file.is_open()) { 397 (*message)(LDPL_FATAL, "Unable to open apifile.txt for writing."); 398 abort(); 399 } 400 } 401 402 for (std::list<claimed_file>::iterator I = Modules.begin(), 403 E = Modules.end(); I != E; ++I) { 404 if (I->syms.empty()) 405 continue; 406 (*get_symbols)(I->handle, I->syms.size(), &I->syms[0]); 407 for (unsigned i = 0, e = I->syms.size(); i != e; i++) { 408 if (mustPreserve(*I, i)) { 409 lto_codegen_add_must_preserve_symbol(code_gen, I->syms[i].name); 410 411 if (options::generate_api_file) 412 api_file << I->syms[i].name << "\n"; 413 } 414 } 415 } 416 417 if (options::generate_api_file) 418 api_file.close(); 419 420 lto_codegen_set_pic_model(code_gen, output_type); 421 lto_codegen_set_debug_model(code_gen, LTO_DEBUG_MODEL_DWARF); 422 if (!options::mcpu.empty()) 423 lto_codegen_set_cpu(code_gen, options::mcpu.c_str()); 424 425 // Pass through extra options to the code generator. 426 if (!options::extra.empty()) { 427 for (std::vector<std::string>::iterator it = options::extra.begin(); 428 it != options::extra.end(); ++it) { 429 lto_codegen_debug_options(code_gen, (*it).c_str()); 430 } 431 } 432 433 if (options::generate_bc_file != options::BC_NO) { 434 std::string path; 435 if (options::generate_bc_file == options::BC_ONLY) 436 path = output_name; 437 else if (!options::bc_path.empty()) 438 path = options::bc_path; 439 else 440 path = output_name + ".bc"; 441 bool err = lto_codegen_write_merged_modules(code_gen, path.c_str()); 442 if (err) 443 (*message)(LDPL_FATAL, "Failed to write the output file."); 444 if (options::generate_bc_file == options::BC_ONLY) { 445 lto_codegen_dispose(code_gen); 446 exit(0); 447 } 448 } 449 450 std::string ObjPath; 451 { 452 const char *Temp; 453 if (lto_codegen_compile_to_file(code_gen, &Temp)) { 454 (*message)(LDPL_ERROR, "Could not produce a combined object file\n"); 455 } 456 ObjPath = Temp; 457 } 458 459 lto_codegen_dispose(code_gen); 460 for (std::list<claimed_file>::iterator I = Modules.begin(), 461 E = Modules.end(); I != E; ++I) { 462 for (unsigned i = 0; i != I->syms.size(); ++i) { 463 ld_plugin_symbol &sym = I->syms[i]; 464 free(sym.name); 465 } 466 } 467 468 if ((*add_input_file)(ObjPath.c_str()) != LDPS_OK) { 469 (*message)(LDPL_ERROR, "Unable to add .o file to the link."); 470 (*message)(LDPL_ERROR, "File left behind in: %s", ObjPath.c_str()); 471 return LDPS_ERR; 472 } 473 474 if (!options::extra_library_path.empty() && 475 set_extra_library_path(options::extra_library_path.c_str()) != LDPS_OK) { 476 (*message)(LDPL_ERROR, "Unable to set the extra library path."); 477 return LDPS_ERR; 478 } 479 480 if (options::obj_path.empty()) 481 Cleanup.push_back(ObjPath); 482 483 return LDPS_OK; 484 } 485 486 static ld_plugin_status cleanup_hook(void) { 487 for (int i = 0, e = Cleanup.size(); i != e; ++i) { 488 error_code EC = sys::fs::remove(Cleanup[i]); 489 if (EC) 490 (*message)(LDPL_ERROR, "Failed to delete '%s': %s", Cleanup[i].c_str(), 491 EC.message().c_str()); 492 } 493 494 return LDPS_OK; 495 } 496