gold-plugin.cpp revision c1da8864a9a47329af6255567097f01d352eb311
13e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky//===-- gold-plugin.cpp - Plugin to gold for Link Time Optimization ------===// 23e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky// 33e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky// The LLVM Compiler Infrastructure 43e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky// 53e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky// This file is distributed under the University of Illinois Open Source 63e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky// License. See LICENSE.TXT for details. 73e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky// 83e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky//===----------------------------------------------------------------------===// 93e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky// 103e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky// This is a gold plugin for LLVM. It provides an LLVM implementation of the 113e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky// interface described in http://gcc.gnu.org/wiki/whopr/driver . 123e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky// 133e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky//===----------------------------------------------------------------------===// 143e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 153e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky#include "plugin-api.h" 163e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 173e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky#include "llvm-c/lto.h" 183e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 193e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky#include "llvm/Support/raw_ostream.h" 203e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky#include "llvm/System/Path.h" 213e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 226cbbdfd2e900164beeb34513a25d88cc58e582b0Torok Edwin#include <cerrno> 233e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky#include <cstdlib> 243e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky#include <cstring> 253e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky#include <list> 263e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky#include <vector> 273e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 283e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewyckyusing namespace llvm; 293e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 303e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewyckynamespace { 313e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky ld_plugin_status discard_message(int level, const char *format, ...) { 323e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky // Die loudly. Recent versions of Gold pass ld_plugin_message as the first 333e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky // callback in the transfer vector. This should never be called. 343e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky abort(); 353e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky } 363e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 373e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky ld_plugin_add_symbols add_symbols = NULL; 383e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky ld_plugin_get_symbols get_symbols = NULL; 393e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky ld_plugin_add_input_file add_input_file = NULL; 403e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky ld_plugin_message message = discard_message; 413e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 423e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky int api_version = 0; 433e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky int gold_version = 0; 443e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 453e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky struct claimed_file { 463e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky lto_module_t M; 473e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky void *handle; 483e5a0d8b0b848d1b0deb8976924703787b221e31Torok Edwin void *buf; 493e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky std::vector<ld_plugin_symbol> syms; 503e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky }; 513e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 523e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky lto_codegen_model output_type = LTO_CODEGEN_PIC_MODEL_STATIC; 533e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky std::list<claimed_file> Modules; 543e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky std::vector<sys::Path> Cleanup; 553e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky} 563e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 573e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewyckyld_plugin_status claim_file_hook(const ld_plugin_input_file *file, 583e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky int *claimed); 593e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewyckyld_plugin_status all_symbols_read_hook(void); 603e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewyckyld_plugin_status cleanup_hook(void); 613e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 623e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewyckyextern "C" ld_plugin_status onload(ld_plugin_tv *tv); 633e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewyckyld_plugin_status onload(ld_plugin_tv *tv) { 643e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky // We're given a pointer to the first transfer vector. We read through them 653e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky // until we find one where tv_tag == LDPT_NULL. The REGISTER_* tagged values 663e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky // contain pointers to functions that we need to call to register our own 673e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky // hooks. The others are addresses of functions we can use to call into gold 683e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky // for services. 693e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 703e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky bool registeredClaimFile = false; 713e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky bool registeredAllSymbolsRead = false; 723e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky bool registeredCleanup = false; 733e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 743e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky for (; tv->tv_tag != LDPT_NULL; ++tv) { 753e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky switch (tv->tv_tag) { 763e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky case LDPT_API_VERSION: 773e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky api_version = tv->tv_u.tv_val; 783e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky break; 793e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky case LDPT_GOLD_VERSION: // major * 100 + minor 803e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky gold_version = tv->tv_u.tv_val; 813e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky break; 823e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky case LDPT_LINKER_OUTPUT: 833e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky switch (tv->tv_u.tv_val) { 843e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky case LDPO_REL: // .o 853e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky case LDPO_DYN: // .so 863e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky output_type = LTO_CODEGEN_PIC_MODEL_DYNAMIC; 873e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky break; 883e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky case LDPO_EXEC: // .exe 893e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky output_type = LTO_CODEGEN_PIC_MODEL_STATIC; 903e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky break; 913e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky default: 923e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky (*message)(LDPL_ERROR, "Unknown output file type %d", 933e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky tv->tv_u.tv_val); 943e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky return LDPS_ERR; 953e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky } 963e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky // TODO: add an option to disable PIC. 973e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky //output_type = LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC; 983e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky break; 993e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky case LDPT_OPTION: 1003e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky (*message)(LDPL_WARNING, "Ignoring flag %s", tv->tv_u.tv_string); 1013e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky break; 1023e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky case LDPT_REGISTER_CLAIM_FILE_HOOK: { 1033e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky ld_plugin_register_claim_file callback; 1043e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky callback = tv->tv_u.tv_register_claim_file; 1053e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 1063e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky if ((*callback)(claim_file_hook) != LDPS_OK) 1073e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky return LDPS_ERR; 1083e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 1093e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky registeredClaimFile = true; 1103e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky } break; 1113e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK: { 1123e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky ld_plugin_register_all_symbols_read callback; 1133e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky callback = tv->tv_u.tv_register_all_symbols_read; 1143e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 1153e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky if ((*callback)(all_symbols_read_hook) != LDPS_OK) 1163e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky return LDPS_ERR; 1173e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 1183e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky registeredAllSymbolsRead = true; 1193e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky } break; 1203e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky case LDPT_REGISTER_CLEANUP_HOOK: { 1213e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky ld_plugin_register_cleanup callback; 1223e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky callback = tv->tv_u.tv_register_cleanup; 1233e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 1243e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky if ((*callback)(cleanup_hook) != LDPS_OK) 1253e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky return LDPS_ERR; 1263e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 1273e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky registeredCleanup = true; 1283e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky } break; 1293e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky case LDPT_ADD_SYMBOLS: 1303e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky add_symbols = tv->tv_u.tv_add_symbols; 1313e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky break; 1323e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky case LDPT_GET_SYMBOLS: 1333e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky get_symbols = tv->tv_u.tv_get_symbols; 1343e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky break; 1353e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky case LDPT_ADD_INPUT_FILE: 1363e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky add_input_file = tv->tv_u.tv_add_input_file; 1373e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky break; 1383e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky case LDPT_MESSAGE: 1393e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky message = tv->tv_u.tv_message; 1403e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky break; 1413e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky default: 1423e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky break; 1433e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky } 1443e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky } 1453e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 1463e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky if (!registeredClaimFile || !registeredAllSymbolsRead || !registeredCleanup || 1473e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky !add_symbols || !get_symbols || !add_input_file) { 1483e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky (*message)(LDPL_ERROR, "Not all hooks registered for LLVMgold."); 1493e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky return LDPS_ERR; 1503e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky } 1513e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 1523e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky return LDPS_OK; 1533e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky} 1543e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 1553e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky/// claim_file_hook - called by gold to see whether this file is one that 1563e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky/// our plugin can handle. We'll try to open it and register all the symbols 1573e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky/// with add_symbol if possible. 1583e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewyckyld_plugin_status claim_file_hook(const ld_plugin_input_file *file, 1593e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky int *claimed) { 1603e5a0d8b0b848d1b0deb8976924703787b221e31Torok Edwin void *buf = NULL; 1613e5a0d8b0b848d1b0deb8976924703787b221e31Torok Edwin if (file->offset) { 162c1da8864a9a47329af6255567097f01d352eb311Nick Lewycky // Gold has found what might be IR part-way inside of a file, such as 163c1da8864a9a47329af6255567097f01d352eb311Nick Lewycky // an .a archive. 1643e5a0d8b0b848d1b0deb8976924703787b221e31Torok Edwin if (lseek(file->fd, file->offset, SEEK_SET) == -1) { 1653e5a0d8b0b848d1b0deb8976924703787b221e31Torok Edwin (*message)(LDPL_ERROR, 1663e5a0d8b0b848d1b0deb8976924703787b221e31Torok Edwin "Failed to seek to archive member of %s at offset %d: %s\n", 1673e5a0d8b0b848d1b0deb8976924703787b221e31Torok Edwin file->name, 1683e5a0d8b0b848d1b0deb8976924703787b221e31Torok Edwin file->offset, strerror(errno)); 1693e5a0d8b0b848d1b0deb8976924703787b221e31Torok Edwin return LDPS_ERR; 1703e5a0d8b0b848d1b0deb8976924703787b221e31Torok Edwin } 1713e5a0d8b0b848d1b0deb8976924703787b221e31Torok Edwin buf = malloc(file->filesize); 1723e5a0d8b0b848d1b0deb8976924703787b221e31Torok Edwin if (!buf) { 1733e5a0d8b0b848d1b0deb8976924703787b221e31Torok Edwin (*message)(LDPL_ERROR, 1743e5a0d8b0b848d1b0deb8976924703787b221e31Torok Edwin "Failed to allocate buffer for archive member of size: %d\n", 1753e5a0d8b0b848d1b0deb8976924703787b221e31Torok Edwin file->filesize); 1763e5a0d8b0b848d1b0deb8976924703787b221e31Torok Edwin return LDPS_ERR; 1773e5a0d8b0b848d1b0deb8976924703787b221e31Torok Edwin } 1783e5a0d8b0b848d1b0deb8976924703787b221e31Torok Edwin if (read(file->fd, buf, file->filesize) != file->filesize) { 1793e5a0d8b0b848d1b0deb8976924703787b221e31Torok Edwin (*message)(LDPL_ERROR, 1803e5a0d8b0b848d1b0deb8976924703787b221e31Torok Edwin "Failed to read archive member of %s at offset %d: %s\n", 1813e5a0d8b0b848d1b0deb8976924703787b221e31Torok Edwin file->name, 1823e5a0d8b0b848d1b0deb8976924703787b221e31Torok Edwin file->offset, 1833e5a0d8b0b848d1b0deb8976924703787b221e31Torok Edwin strerror(errno)); 1843e5a0d8b0b848d1b0deb8976924703787b221e31Torok Edwin free(buf); 1853e5a0d8b0b848d1b0deb8976924703787b221e31Torok Edwin return LDPS_ERR; 1863e5a0d8b0b848d1b0deb8976924703787b221e31Torok Edwin } 1873e5a0d8b0b848d1b0deb8976924703787b221e31Torok Edwin if (!lto_module_is_object_file_in_memory(buf, file->filesize)) { 1883e5a0d8b0b848d1b0deb8976924703787b221e31Torok Edwin free(buf); 1893e5a0d8b0b848d1b0deb8976924703787b221e31Torok Edwin return LDPS_OK; 1903e5a0d8b0b848d1b0deb8976924703787b221e31Torok Edwin } 1913e5a0d8b0b848d1b0deb8976924703787b221e31Torok Edwin } else if (!lto_module_is_object_file(file->name)) 1923e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky return LDPS_OK; 1933e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 1943e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky *claimed = 1; 1953e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky Modules.resize(Modules.size() + 1); 1963e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky claimed_file &cf = Modules.back(); 1973e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 198c1da8864a9a47329af6255567097f01d352eb311Nick Lewycky cf.M = buf ? lto_module_create_from_memory(buf, file->filesize) : 199c1da8864a9a47329af6255567097f01d352eb311Nick Lewycky lto_module_create(file->name); 2003e5a0d8b0b848d1b0deb8976924703787b221e31Torok Edwin cf.buf = buf; 2013e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky if (!cf.M) { 2023e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky (*message)(LDPL_ERROR, "Failed to create LLVM module: %s", 2033e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky lto_get_error_message()); 2043e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky return LDPS_ERR; 2053e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky } 2063e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky cf.handle = file->handle; 2073e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky unsigned sym_count = lto_module_get_num_symbols(cf.M); 2083e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky cf.syms.reserve(sym_count); 2093e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 2103e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky for (unsigned i = 0; i != sym_count; ++i) { 2113e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky lto_symbol_attributes attrs = lto_module_get_symbol_attribute(cf.M, i); 2123e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky if ((attrs & LTO_SYMBOL_SCOPE_MASK) == LTO_SYMBOL_SCOPE_INTERNAL) 2133e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky continue; 2143e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 2153e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky cf.syms.push_back(ld_plugin_symbol()); 2163e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky ld_plugin_symbol &sym = cf.syms.back(); 2173e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky sym.name = const_cast<char *>(lto_module_get_symbol_name(cf.M, i)); 2183e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky sym.version = NULL; 2193e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 2203e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky int scope = attrs & LTO_SYMBOL_SCOPE_MASK; 2213e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky switch (scope) { 2223e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky case LTO_SYMBOL_SCOPE_HIDDEN: 2233e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky sym.visibility = LDPV_HIDDEN; 2243e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky break; 2253e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky case LTO_SYMBOL_SCOPE_PROTECTED: 2263e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky sym.visibility = LDPV_PROTECTED; 2273e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky break; 2283e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky case 0: // extern 2293e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky case LTO_SYMBOL_SCOPE_DEFAULT: 2303e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky sym.visibility = LDPV_DEFAULT; 2313e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky break; 2323e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky default: 2333e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky (*message)(LDPL_ERROR, "Unknown scope attribute: %d", scope); 2343e5a0d8b0b848d1b0deb8976924703787b221e31Torok Edwin free(buf); 2353e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky return LDPS_ERR; 2363e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky } 2373e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 2383e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky int definition = attrs & LTO_SYMBOL_DEFINITION_MASK; 2393e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky switch (definition) { 2403e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky case LTO_SYMBOL_DEFINITION_REGULAR: 2413e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky sym.def = LDPK_DEF; 2423e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky break; 2433e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky case LTO_SYMBOL_DEFINITION_UNDEFINED: 2443e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky sym.def = LDPK_UNDEF; 2453e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky break; 2463e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky case LTO_SYMBOL_DEFINITION_TENTATIVE: 2473e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky sym.def = LDPK_COMMON; 2483e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky break; 2493e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky case LTO_SYMBOL_DEFINITION_WEAK: 2503e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky sym.def = LDPK_WEAKDEF; 2513e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky break; 2523e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky default: 2533e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky (*message)(LDPL_ERROR, "Unknown definition attribute: %d", definition); 2543e5a0d8b0b848d1b0deb8976924703787b221e31Torok Edwin free(buf); 2553e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky return LDPS_ERR; 2563e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky } 2573e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 2583e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky // LLVM never emits COMDAT. 2593e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky sym.size = 0; 2603e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky sym.comdat_key = NULL; 2613e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 2623e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky sym.resolution = LDPR_UNKNOWN; 2633e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky } 2643e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 2653e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky cf.syms.reserve(cf.syms.size()); 2663e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 2673e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky if (!cf.syms.empty()) { 2683e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky if ((*add_symbols)(cf.handle, cf.syms.size(), &cf.syms[0]) != LDPS_OK) { 2693e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky (*message)(LDPL_ERROR, "Unable to add symbols!"); 2703e5a0d8b0b848d1b0deb8976924703787b221e31Torok Edwin free(buf); 2713e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky return LDPS_ERR; 2723e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky } 2733e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky } 2743e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 2753e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky return LDPS_OK; 2763e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky} 2773e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 2783e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky/// all_symbols_read_hook - gold informs us that all symbols have been read. 2793e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky/// At this point, we use get_symbols to see if any of our definitions have 2803e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky/// been overridden by a native object file. Then, perform optimization and 2813e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky/// codegen. 2823e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewyckyld_plugin_status all_symbols_read_hook(void) { 2833e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky lto_code_gen_t cg = lto_codegen_create(); 2843e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 2853e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky for (std::list<claimed_file>::iterator I = Modules.begin(), 2863e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky E = Modules.end(); I != E; ++I) 2873e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky lto_codegen_add_module(cg, I->M); 2883e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 2893e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky // If we don't preserve any symbols, libLTO will assume that all symbols are 2903e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky // needed. Keep all symbols unless we're producing a final executable. 2913e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky if (output_type == LTO_CODEGEN_PIC_MODEL_STATIC) { 2923e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky bool anySymbolsPreserved = false; 2933e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky for (std::list<claimed_file>::iterator I = Modules.begin(), 2943e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky E = Modules.end(); I != E; ++I) { 2953e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky (*get_symbols)(I->handle, I->syms.size(), &I->syms[0]); 2963e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky for (unsigned i = 0, e = I->syms.size(); i != e; i++) { 2973e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky if (I->syms[i].resolution == LDPR_PREVAILING_DEF) { 2983e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky lto_codegen_add_must_preserve_symbol(cg, I->syms[i].name); 2993e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky anySymbolsPreserved = true; 3003e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky } 3013e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky } 3023e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky } 3033e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 3043e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky if (!anySymbolsPreserved) { 3053e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky // This entire file is unnecessary! 3063e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky lto_codegen_dispose(cg); 3073e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky return LDPS_OK; 3083e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky } 3093e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky } 3103e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 3113e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky lto_codegen_set_pic_model(cg, output_type); 3123e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky lto_codegen_set_debug_model(cg, LTO_DEBUG_MODEL_DWARF); 3133e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 3143e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky size_t bufsize = 0; 3153e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky const char *buffer = static_cast<const char *>(lto_codegen_compile(cg, 3163e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky &bufsize)); 3173e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 3183e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky std::string ErrMsg; 3193e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 3203e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky sys::Path uniqueObjPath("/tmp/llvmgold.o"); 3213e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky if (uniqueObjPath.createTemporaryFileOnDisk(true, &ErrMsg)) { 3223e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky (*message)(LDPL_ERROR, "%s", ErrMsg.c_str()); 3233e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky return LDPS_ERR; 3243e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky } 3253e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky raw_fd_ostream *objFile = new raw_fd_ostream(uniqueObjPath.c_str(), true, 3263e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky ErrMsg); 3273e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky if (!ErrMsg.empty()) { 3283e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky delete objFile; 3293e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky (*message)(LDPL_ERROR, "%s", ErrMsg.c_str()); 3303e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky return LDPS_ERR; 3313e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky } 3323e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 3333e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky objFile->write(buffer, bufsize); 3343e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky objFile->close(); 3353e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 3363e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky lto_codegen_dispose(cg); 3373e5a0d8b0b848d1b0deb8976924703787b221e31Torok Edwin for (std::list<claimed_file>::iterator I = Modules.begin(), 3383e5a0d8b0b848d1b0deb8976924703787b221e31Torok Edwin E = Modules.end(); I != E; ++I) { 3393e5a0d8b0b848d1b0deb8976924703787b221e31Torok Edwin free(I->buf); 3403e5a0d8b0b848d1b0deb8976924703787b221e31Torok Edwin } 3413e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 3423e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky if ((*add_input_file)(const_cast<char*>(uniqueObjPath.c_str())) != LDPS_OK) { 3433e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky (*message)(LDPL_ERROR, "Unable to add .o file to the link."); 3443e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky (*message)(LDPL_ERROR, "File left behind in: %s", uniqueObjPath.c_str()); 3453e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky return LDPS_ERR; 3463e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky } 3473e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 3483e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky Cleanup.push_back(uniqueObjPath); 3493e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 3503e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky return LDPS_OK; 3513e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky} 3523e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 3533e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewyckyld_plugin_status cleanup_hook(void) { 3543e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky std::string ErrMsg; 3553e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 3563e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky for (int i = 0, e = Cleanup.size(); i != e; ++i) 3573e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky if (Cleanup[i].eraseFromDisk(false, &ErrMsg)) 3583e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky (*message)(LDPL_ERROR, "Failed to delete '%s': %s", Cleanup[i].c_str(), 3593e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky ErrMsg.c_str()); 3603e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 3613e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky return LDPS_OK; 3623e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky} 363