gold-plugin.cpp revision 5c00b4af61bb6abff2fb28ddd904808623a7db23
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 1509b5d90429258f92f5e5ac98411a71460bcd9230Duncan Sands#include "llvm/Config/config.h" 163e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky#include "plugin-api.h" 173e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 183e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky#include "llvm-c/lto.h" 193e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 203e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky#include "llvm/Support/raw_ostream.h" 21ed1c0ffe0b2287deaee7cba7506c93aa34c6d4b7Jeffrey Yasskin#include "llvm/System/Errno.h" 223e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky#include "llvm/System/Path.h" 2342de34f013ee15377dd78aa0d827100166cb66c9Rafael Espindola#include "llvm/System/Program.h" 243e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 256cbbdfd2e900164beeb34513a25d88cc58e582b0Torok Edwin#include <cerrno> 263e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky#include <cstdlib> 273e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky#include <cstring> 28ca4286295f7db200724cb488a04ad15441a8ba99Nick Lewycky#include <fstream> 293e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky#include <list> 303e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky#include <vector> 313e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 323e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewyckyusing namespace llvm; 333e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 343e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewyckynamespace { 353e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky ld_plugin_status discard_message(int level, const char *format, ...) { 363e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky // Die loudly. Recent versions of Gold pass ld_plugin_message as the first 373e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky // callback in the transfer vector. This should never be called. 383e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky abort(); 393e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky } 403e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 413e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky ld_plugin_add_symbols add_symbols = NULL; 423e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky ld_plugin_get_symbols get_symbols = NULL; 433e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky ld_plugin_add_input_file add_input_file = NULL; 443e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky ld_plugin_message message = discard_message; 453e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 463e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky int api_version = 0; 473e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky int gold_version = 0; 483e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 493e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky struct claimed_file { 503e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky lto_module_t M; 513e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky void *handle; 523e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky std::vector<ld_plugin_symbol> syms; 533e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky }; 543e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 553e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky lto_codegen_model output_type = LTO_CODEGEN_PIC_MODEL_STATIC; 563e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky std::list<claimed_file> Modules; 573e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky std::vector<sys::Path> Cleanup; 583e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky} 593e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 605c00b4af61bb6abff2fb28ddd904808623a7db23Viktor Kutuzovnamespace options { 615c00b4af61bb6abff2fb28ddd904808623a7db23Viktor Kutuzov bool generate_api_file = false; 625c00b4af61bb6abff2fb28ddd904808623a7db23Viktor Kutuzov const char *as_path = NULL; 635c00b4af61bb6abff2fb28ddd904808623a7db23Viktor Kutuzov // Additional options to pass into the code generator. 645c00b4af61bb6abff2fb28ddd904808623a7db23Viktor Kutuzov // Note: This array will contain all plugin options which are not claimed 655c00b4af61bb6abff2fb28ddd904808623a7db23Viktor Kutuzov // as plugin exclusive to pass to the code generator. 665c00b4af61bb6abff2fb28ddd904808623a7db23Viktor Kutuzov // For example, "generate-api-file" and "as"options are for the plugin 675c00b4af61bb6abff2fb28ddd904808623a7db23Viktor Kutuzov // use only and will not be passed. 685c00b4af61bb6abff2fb28ddd904808623a7db23Viktor Kutuzov std::vector<std::string> extra; 695c00b4af61bb6abff2fb28ddd904808623a7db23Viktor Kutuzov 705c00b4af61bb6abff2fb28ddd904808623a7db23Viktor Kutuzov void process_plugin_option(const char* opt) 715c00b4af61bb6abff2fb28ddd904808623a7db23Viktor Kutuzov { 725c00b4af61bb6abff2fb28ddd904808623a7db23Viktor Kutuzov if (opt == NULL) 735c00b4af61bb6abff2fb28ddd904808623a7db23Viktor Kutuzov return; 745c00b4af61bb6abff2fb28ddd904808623a7db23Viktor Kutuzov 755c00b4af61bb6abff2fb28ddd904808623a7db23Viktor Kutuzov if (strcmp("generate-api-file", opt) == 0) { 765c00b4af61bb6abff2fb28ddd904808623a7db23Viktor Kutuzov generate_api_file = true; 775c00b4af61bb6abff2fb28ddd904808623a7db23Viktor Kutuzov } else if (strncmp("as=", opt, 3) == 0) { 785c00b4af61bb6abff2fb28ddd904808623a7db23Viktor Kutuzov if (as_path) { 795c00b4af61bb6abff2fb28ddd904808623a7db23Viktor Kutuzov (*message)(LDPL_WARNING, "Path to as specified twice. " 805c00b4af61bb6abff2fb28ddd904808623a7db23Viktor Kutuzov "Discarding %s", opt); 815c00b4af61bb6abff2fb28ddd904808623a7db23Viktor Kutuzov } else { 825c00b4af61bb6abff2fb28ddd904808623a7db23Viktor Kutuzov as_path = strdup(opt + 3); 835c00b4af61bb6abff2fb28ddd904808623a7db23Viktor Kutuzov } 845c00b4af61bb6abff2fb28ddd904808623a7db23Viktor Kutuzov } else { 855c00b4af61bb6abff2fb28ddd904808623a7db23Viktor Kutuzov // Save this option to pass to the code generator. 865c00b4af61bb6abff2fb28ddd904808623a7db23Viktor Kutuzov extra.push_back(std::string(opt)); 875c00b4af61bb6abff2fb28ddd904808623a7db23Viktor Kutuzov } 885c00b4af61bb6abff2fb28ddd904808623a7db23Viktor Kutuzov } 895c00b4af61bb6abff2fb28ddd904808623a7db23Viktor Kutuzov} 905c00b4af61bb6abff2fb28ddd904808623a7db23Viktor Kutuzov 913e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewyckyld_plugin_status claim_file_hook(const ld_plugin_input_file *file, 923e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky int *claimed); 933e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewyckyld_plugin_status all_symbols_read_hook(void); 943e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewyckyld_plugin_status cleanup_hook(void); 953e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 963e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewyckyextern "C" ld_plugin_status onload(ld_plugin_tv *tv); 973e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewyckyld_plugin_status onload(ld_plugin_tv *tv) { 983e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky // We're given a pointer to the first transfer vector. We read through them 993e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky // until we find one where tv_tag == LDPT_NULL. The REGISTER_* tagged values 1003e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky // contain pointers to functions that we need to call to register our own 1013e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky // hooks. The others are addresses of functions we can use to call into gold 1023e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky // for services. 1033e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 1043e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky bool registeredClaimFile = false; 1053e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky bool registeredAllSymbolsRead = false; 1063e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky bool registeredCleanup = false; 1073e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 1083e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky for (; tv->tv_tag != LDPT_NULL; ++tv) { 1093e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky switch (tv->tv_tag) { 1103e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky case LDPT_API_VERSION: 1113e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky api_version = tv->tv_u.tv_val; 1123e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky break; 1133e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky case LDPT_GOLD_VERSION: // major * 100 + minor 1143e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky gold_version = tv->tv_u.tv_val; 1153e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky break; 1163e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky case LDPT_LINKER_OUTPUT: 1173e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky switch (tv->tv_u.tv_val) { 1183e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky case LDPO_REL: // .o 1193e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky case LDPO_DYN: // .so 1203e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky output_type = LTO_CODEGEN_PIC_MODEL_DYNAMIC; 1213e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky break; 1223e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky case LDPO_EXEC: // .exe 1233e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky output_type = LTO_CODEGEN_PIC_MODEL_STATIC; 1243e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky break; 1253e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky default: 1263e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky (*message)(LDPL_ERROR, "Unknown output file type %d", 1273e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky tv->tv_u.tv_val); 1283e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky return LDPS_ERR; 1293e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky } 1303e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky // TODO: add an option to disable PIC. 1313e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky //output_type = LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC; 1323e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky break; 1333e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky case LDPT_OPTION: 1345c00b4af61bb6abff2fb28ddd904808623a7db23Viktor Kutuzov options::process_plugin_option(tv->tv_u.tv_string); 1353e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky break; 1363e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky case LDPT_REGISTER_CLAIM_FILE_HOOK: { 1373e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky ld_plugin_register_claim_file callback; 1383e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky callback = tv->tv_u.tv_register_claim_file; 1393e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 1403e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky if ((*callback)(claim_file_hook) != LDPS_OK) 1413e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky return LDPS_ERR; 1423e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 1433e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky registeredClaimFile = true; 1443e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky } break; 1453e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK: { 1463e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky ld_plugin_register_all_symbols_read callback; 1473e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky callback = tv->tv_u.tv_register_all_symbols_read; 1483e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 1493e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky if ((*callback)(all_symbols_read_hook) != LDPS_OK) 1503e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky return LDPS_ERR; 1513e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 1523e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky registeredAllSymbolsRead = true; 1533e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky } break; 1543e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky case LDPT_REGISTER_CLEANUP_HOOK: { 1553e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky ld_plugin_register_cleanup callback; 1563e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky callback = tv->tv_u.tv_register_cleanup; 1573e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 1583e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky if ((*callback)(cleanup_hook) != LDPS_OK) 1593e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky return LDPS_ERR; 1603e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 1613e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky registeredCleanup = true; 1623e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky } break; 1633e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky case LDPT_ADD_SYMBOLS: 1643e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky add_symbols = tv->tv_u.tv_add_symbols; 1653e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky break; 1663e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky case LDPT_GET_SYMBOLS: 1673e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky get_symbols = tv->tv_u.tv_get_symbols; 1683e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky break; 1693e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky case LDPT_ADD_INPUT_FILE: 1703e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky add_input_file = tv->tv_u.tv_add_input_file; 1713e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky break; 1723e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky case LDPT_MESSAGE: 1733e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky message = tv->tv_u.tv_message; 1743e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky break; 1753e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky default: 1763e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky break; 1773e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky } 1783e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky } 1793e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 18098c507ed5c2883bc8ef487d952e851da37f8b32fRafael Espindola if (!registeredClaimFile) { 1816210a9493a25a9f97f4f0ec62a3ed8ca00f72423Rafael Espindola (*message)(LDPL_ERROR, "register_claim_file not passed to LLVMgold."); 1826210a9493a25a9f97f4f0ec62a3ed8ca00f72423Rafael Espindola return LDPS_ERR; 1836210a9493a25a9f97f4f0ec62a3ed8ca00f72423Rafael Espindola } 18498c507ed5c2883bc8ef487d952e851da37f8b32fRafael Espindola if (!add_symbols) { 1856210a9493a25a9f97f4f0ec62a3ed8ca00f72423Rafael Espindola (*message)(LDPL_ERROR, "add_symbols not passed to LLVMgold."); 1866210a9493a25a9f97f4f0ec62a3ed8ca00f72423Rafael Espindola return LDPS_ERR; 1876210a9493a25a9f97f4f0ec62a3ed8ca00f72423Rafael Espindola } 1883e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 1893e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky return LDPS_OK; 1903e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky} 1913e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 1923e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky/// claim_file_hook - called by gold to see whether this file is one that 1933e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky/// our plugin can handle. We'll try to open it and register all the symbols 1943e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky/// with add_symbol if possible. 1953e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewyckyld_plugin_status claim_file_hook(const ld_plugin_input_file *file, 1963e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky int *claimed) { 1973e5a0d8b0b848d1b0deb8976924703787b221e31Torok Edwin void *buf = NULL; 1983e5a0d8b0b848d1b0deb8976924703787b221e31Torok Edwin if (file->offset) { 199c1da8864a9a47329af6255567097f01d352eb311Nick Lewycky // Gold has found what might be IR part-way inside of a file, such as 200c1da8864a9a47329af6255567097f01d352eb311Nick Lewycky // an .a archive. 2013e5a0d8b0b848d1b0deb8976924703787b221e31Torok Edwin if (lseek(file->fd, file->offset, SEEK_SET) == -1) { 2020df91b2c8677f3f8fd25b46953051c9d95c1c1aeNick Lewycky (*message)(LDPL_ERROR, 2033e5a0d8b0b848d1b0deb8976924703787b221e31Torok Edwin "Failed to seek to archive member of %s at offset %d: %s\n", 2043e5a0d8b0b848d1b0deb8976924703787b221e31Torok Edwin file->name, 205ed1c0ffe0b2287deaee7cba7506c93aa34c6d4b7Jeffrey Yasskin file->offset, sys::StrError(errno).c_str()); 2063e5a0d8b0b848d1b0deb8976924703787b221e31Torok Edwin return LDPS_ERR; 2073e5a0d8b0b848d1b0deb8976924703787b221e31Torok Edwin } 2083e5a0d8b0b848d1b0deb8976924703787b221e31Torok Edwin buf = malloc(file->filesize); 2093e5a0d8b0b848d1b0deb8976924703787b221e31Torok Edwin if (!buf) { 2100df91b2c8677f3f8fd25b46953051c9d95c1c1aeNick Lewycky (*message)(LDPL_ERROR, 2113e5a0d8b0b848d1b0deb8976924703787b221e31Torok Edwin "Failed to allocate buffer for archive member of size: %d\n", 2123e5a0d8b0b848d1b0deb8976924703787b221e31Torok Edwin file->filesize); 2133e5a0d8b0b848d1b0deb8976924703787b221e31Torok Edwin return LDPS_ERR; 2143e5a0d8b0b848d1b0deb8976924703787b221e31Torok Edwin } 2153e5a0d8b0b848d1b0deb8976924703787b221e31Torok Edwin if (read(file->fd, buf, file->filesize) != file->filesize) { 2160df91b2c8677f3f8fd25b46953051c9d95c1c1aeNick Lewycky (*message)(LDPL_ERROR, 2170df91b2c8677f3f8fd25b46953051c9d95c1c1aeNick Lewycky "Failed to read archive member of %s at offset %d: %s\n", 2183e5a0d8b0b848d1b0deb8976924703787b221e31Torok Edwin file->name, 2190df91b2c8677f3f8fd25b46953051c9d95c1c1aeNick Lewycky file->offset, 220ed1c0ffe0b2287deaee7cba7506c93aa34c6d4b7Jeffrey Yasskin sys::StrError(errno).c_str()); 2210df91b2c8677f3f8fd25b46953051c9d95c1c1aeNick Lewycky free(buf); 2223e5a0d8b0b848d1b0deb8976924703787b221e31Torok Edwin return LDPS_ERR; 2233e5a0d8b0b848d1b0deb8976924703787b221e31Torok Edwin } 2240df91b2c8677f3f8fd25b46953051c9d95c1c1aeNick Lewycky if (!lto_module_is_object_file_in_memory(buf, file->filesize)) { 2250df91b2c8677f3f8fd25b46953051c9d95c1c1aeNick Lewycky free(buf); 2263e5a0d8b0b848d1b0deb8976924703787b221e31Torok Edwin return LDPS_OK; 2270df91b2c8677f3f8fd25b46953051c9d95c1c1aeNick Lewycky } 2283e5a0d8b0b848d1b0deb8976924703787b221e31Torok Edwin } else if (!lto_module_is_object_file(file->name)) 2293e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky return LDPS_OK; 2303e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 2313e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky *claimed = 1; 2323e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky Modules.resize(Modules.size() + 1); 2333e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky claimed_file &cf = Modules.back(); 2343e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 235c1da8864a9a47329af6255567097f01d352eb311Nick Lewycky cf.M = buf ? lto_module_create_from_memory(buf, file->filesize) : 236c1da8864a9a47329af6255567097f01d352eb311Nick Lewycky lto_module_create(file->name); 237ea97aa6129fc89292e215d01fa66504195f1a969Nick Lewycky free(buf); 2383e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky if (!cf.M) { 2393e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky (*message)(LDPL_ERROR, "Failed to create LLVM module: %s", 2403e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky lto_get_error_message()); 2413e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky return LDPS_ERR; 2423e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky } 2433e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky cf.handle = file->handle; 2443e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky unsigned sym_count = lto_module_get_num_symbols(cf.M); 2453e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky cf.syms.reserve(sym_count); 2463e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 2473e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky for (unsigned i = 0; i != sym_count; ++i) { 2483e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky lto_symbol_attributes attrs = lto_module_get_symbol_attribute(cf.M, i); 2493e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky if ((attrs & LTO_SYMBOL_SCOPE_MASK) == LTO_SYMBOL_SCOPE_INTERNAL) 2503e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky continue; 2513e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 2523e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky cf.syms.push_back(ld_plugin_symbol()); 2533e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky ld_plugin_symbol &sym = cf.syms.back(); 2543e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky sym.name = const_cast<char *>(lto_module_get_symbol_name(cf.M, i)); 2553e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky sym.version = NULL; 2563e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 2573e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky int scope = attrs & LTO_SYMBOL_SCOPE_MASK; 2583e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky switch (scope) { 2593e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky case LTO_SYMBOL_SCOPE_HIDDEN: 2603e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky sym.visibility = LDPV_HIDDEN; 2613e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky break; 2623e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky case LTO_SYMBOL_SCOPE_PROTECTED: 2633e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky sym.visibility = LDPV_PROTECTED; 2643e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky break; 2653e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky case 0: // extern 2663e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky case LTO_SYMBOL_SCOPE_DEFAULT: 2673e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky sym.visibility = LDPV_DEFAULT; 2683e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky break; 2693e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky default: 2703e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky (*message)(LDPL_ERROR, "Unknown scope attribute: %d", scope); 2713e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky return LDPS_ERR; 2723e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky } 2733e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 2743e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky int definition = attrs & LTO_SYMBOL_DEFINITION_MASK; 2753e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky switch (definition) { 2763e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky case LTO_SYMBOL_DEFINITION_REGULAR: 2773e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky sym.def = LDPK_DEF; 2783e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky break; 2793e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky case LTO_SYMBOL_DEFINITION_UNDEFINED: 2803e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky sym.def = LDPK_UNDEF; 2813e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky break; 2823e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky case LTO_SYMBOL_DEFINITION_TENTATIVE: 2833e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky sym.def = LDPK_COMMON; 2843e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky break; 2853e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky case LTO_SYMBOL_DEFINITION_WEAK: 2863e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky sym.def = LDPK_WEAKDEF; 2873e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky break; 2887431af050f287011fd52e64034ede6dd98193febRafael Espindola case LTO_SYMBOL_DEFINITION_WEAKUNDEF: 2897431af050f287011fd52e64034ede6dd98193febRafael Espindola sym.def = LDPK_WEAKUNDEF; 2907431af050f287011fd52e64034ede6dd98193febRafael Espindola break; 2913e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky default: 2923e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky (*message)(LDPL_ERROR, "Unknown definition attribute: %d", definition); 2933e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky return LDPS_ERR; 2943e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky } 2953e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 2963e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky // LLVM never emits COMDAT. 2973e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky sym.size = 0; 2983e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky sym.comdat_key = NULL; 2993e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 3003e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky sym.resolution = LDPR_UNKNOWN; 3013e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky } 3023e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 3033e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky cf.syms.reserve(cf.syms.size()); 3043e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 3053e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky if (!cf.syms.empty()) { 3063e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky if ((*add_symbols)(cf.handle, cf.syms.size(), &cf.syms[0]) != LDPS_OK) { 3073e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky (*message)(LDPL_ERROR, "Unable to add symbols!"); 3083e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky return LDPS_ERR; 3093e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky } 3103e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky } 3113e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 3123e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky return LDPS_OK; 3133e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky} 3143e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 3153e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky/// all_symbols_read_hook - gold informs us that all symbols have been read. 3163e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky/// At this point, we use get_symbols to see if any of our definitions have 3173e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky/// been overridden by a native object file. Then, perform optimization and 3183e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky/// codegen. 3193e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewyckyld_plugin_status all_symbols_read_hook(void) { 3203e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky lto_code_gen_t cg = lto_codegen_create(); 3213e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 3223e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky for (std::list<claimed_file>::iterator I = Modules.begin(), 3233e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky E = Modules.end(); I != E; ++I) 3243e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky lto_codegen_add_module(cg, I->M); 3253e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 326ca4286295f7db200724cb488a04ad15441a8ba99Nick Lewycky std::ofstream api_file; 3275c00b4af61bb6abff2fb28ddd904808623a7db23Viktor Kutuzov if (options::generate_api_file) { 328ca4286295f7db200724cb488a04ad15441a8ba99Nick Lewycky api_file.open("apifile.txt", std::ofstream::out | std::ofstream::trunc); 329ca4286295f7db200724cb488a04ad15441a8ba99Nick Lewycky if (!api_file.is_open()) { 330ca4286295f7db200724cb488a04ad15441a8ba99Nick Lewycky (*message)(LDPL_FATAL, "Unable to open apifile.txt for writing."); 331ca4286295f7db200724cb488a04ad15441a8ba99Nick Lewycky abort(); 332ca4286295f7db200724cb488a04ad15441a8ba99Nick Lewycky } 333ca4286295f7db200724cb488a04ad15441a8ba99Nick Lewycky } 334ca4286295f7db200724cb488a04ad15441a8ba99Nick Lewycky 3353e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky // If we don't preserve any symbols, libLTO will assume that all symbols are 3363e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky // needed. Keep all symbols unless we're producing a final executable. 3373e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky if (output_type == LTO_CODEGEN_PIC_MODEL_STATIC) { 3383e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky bool anySymbolsPreserved = false; 3393e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky for (std::list<claimed_file>::iterator I = Modules.begin(), 3403e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky E = Modules.end(); I != E; ++I) { 3413e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky (*get_symbols)(I->handle, I->syms.size(), &I->syms[0]); 3423e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky for (unsigned i = 0, e = I->syms.size(); i != e; i++) { 343e0afaa301d763096af400ef44714b0f4deb5b68bNick Lewycky if (I->syms[i].resolution == LDPR_PREVAILING_DEF || 344e0afaa301d763096af400ef44714b0f4deb5b68bNick Lewycky (I->syms[i].def == LDPK_COMMON && 345e0afaa301d763096af400ef44714b0f4deb5b68bNick Lewycky I->syms[i].resolution == LDPR_RESOLVED_IR)) { 3463e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky lto_codegen_add_must_preserve_symbol(cg, I->syms[i].name); 3473e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky anySymbolsPreserved = true; 348ca4286295f7db200724cb488a04ad15441a8ba99Nick Lewycky 3495c00b4af61bb6abff2fb28ddd904808623a7db23Viktor Kutuzov if (options::generate_api_file) 350ca4286295f7db200724cb488a04ad15441a8ba99Nick Lewycky api_file << I->syms[i].name << "\n"; 3513e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky } 3523e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky } 3533e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky } 3543e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 3555c00b4af61bb6abff2fb28ddd904808623a7db23Viktor Kutuzov if (options::generate_api_file) 356ca4286295f7db200724cb488a04ad15441a8ba99Nick Lewycky api_file.close(); 357ca4286295f7db200724cb488a04ad15441a8ba99Nick Lewycky 3583e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky if (!anySymbolsPreserved) { 3593e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky // This entire file is unnecessary! 3603e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky lto_codegen_dispose(cg); 3613e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky return LDPS_OK; 3623e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky } 3633e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky } 3643e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 3653e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky lto_codegen_set_pic_model(cg, output_type); 3663e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky lto_codegen_set_debug_model(cg, LTO_DEBUG_MODEL_DWARF); 3675c00b4af61bb6abff2fb28ddd904808623a7db23Viktor Kutuzov if (options::as_path) { 3685c00b4af61bb6abff2fb28ddd904808623a7db23Viktor Kutuzov sys::Path p = sys::Program::FindProgramByName(options::as_path); 36942de34f013ee15377dd78aa0d827100166cb66c9Rafael Espindola lto_codegen_set_assembler_path(cg, p.c_str()); 37042de34f013ee15377dd78aa0d827100166cb66c9Rafael Espindola } 3715c00b4af61bb6abff2fb28ddd904808623a7db23Viktor Kutuzov // Pass through extra options to the code generator. 3725c00b4af61bb6abff2fb28ddd904808623a7db23Viktor Kutuzov if (!options::extra.empty()) { 3735c00b4af61bb6abff2fb28ddd904808623a7db23Viktor Kutuzov for (std::vector<std::string>::iterator it = options::extra.begin(); 3745c00b4af61bb6abff2fb28ddd904808623a7db23Viktor Kutuzov it != options::extra.end(); ++it) { 3755c00b4af61bb6abff2fb28ddd904808623a7db23Viktor Kutuzov lto_codegen_debug_options(cg, (*it).c_str()); 3765c00b4af61bb6abff2fb28ddd904808623a7db23Viktor Kutuzov } 3775c00b4af61bb6abff2fb28ddd904808623a7db23Viktor Kutuzov } 3783e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 3793e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky size_t bufsize = 0; 3803e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky const char *buffer = static_cast<const char *>(lto_codegen_compile(cg, 3813e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky &bufsize)); 3823e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 3833e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky std::string ErrMsg; 3843e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 3853e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky sys::Path uniqueObjPath("/tmp/llvmgold.o"); 3863e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky if (uniqueObjPath.createTemporaryFileOnDisk(true, &ErrMsg)) { 3873e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky (*message)(LDPL_ERROR, "%s", ErrMsg.c_str()); 3883e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky return LDPS_ERR; 3893e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky } 39017e9edc4a7bbeadf756494cf39fcacc9eff72202Chris Lattner raw_fd_ostream *objFile = 39117e9edc4a7bbeadf756494cf39fcacc9eff72202Chris Lattner new raw_fd_ostream(uniqueObjPath.c_str(), ErrMsg, 392baa26395ccf17fc988bb9cf62d6659ca8415ece9Dan Gohman raw_fd_ostream::F_Binary); 3933e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky if (!ErrMsg.empty()) { 3943e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky delete objFile; 3953e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky (*message)(LDPL_ERROR, "%s", ErrMsg.c_str()); 3963e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky return LDPS_ERR; 3973e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky } 3983e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 3993e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky objFile->write(buffer, bufsize); 4003e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky objFile->close(); 4013e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 4023e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky lto_codegen_dispose(cg); 4033e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 4043e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky if ((*add_input_file)(const_cast<char*>(uniqueObjPath.c_str())) != LDPS_OK) { 4053e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky (*message)(LDPL_ERROR, "Unable to add .o file to the link."); 4063e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky (*message)(LDPL_ERROR, "File left behind in: %s", uniqueObjPath.c_str()); 4073e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky return LDPS_ERR; 4083e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky } 4093e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 4103e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky Cleanup.push_back(uniqueObjPath); 4113e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 4123e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky return LDPS_OK; 4133e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky} 4143e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 4153e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewyckyld_plugin_status cleanup_hook(void) { 4163e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky std::string ErrMsg; 4173e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 4183e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky for (int i = 0, e = Cleanup.size(); i != e; ++i) 4193e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky if (Cleanup[i].eraseFromDisk(false, &ErrMsg)) 4203e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky (*message)(LDPL_ERROR, "Failed to delete '%s': %s", Cleanup[i].c_str(), 4213e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky ErrMsg.c_str()); 4223e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky 4233e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky return LDPS_OK; 4243e62b2dc93dae6904f0717612782ab6ebf413e1dNick Lewycky} 425