├── .clang-format ├── .clang-tidy ├── .gitignore ├── CMakeLists.txt ├── CODE_OWNERS.TXT ├── Common ├── Args.cpp ├── CMakeLists.txt ├── DWARF.cpp ├── ErrorHandler.cpp ├── Filesystem.cpp ├── Memory.cpp ├── Reproduce.cpp ├── Strings.cpp └── Version.cpp ├── ELF ├── Arch │ ├── AArch64.cpp │ ├── ARM.cpp │ ├── PPC.cpp │ ├── PPC64.cpp │ ├── RISCV.cpp │ ├── X86.cpp │ └── X86_64.cpp ├── CMakeLists.txt ├── Config.h ├── DWARF.cpp ├── DWARF.h ├── Driver.cpp ├── Driver.h ├── DriverUtils.cpp ├── EhFrame.cpp ├── EhFrame.h ├── ICF.cpp ├── ICF.h ├── InputFiles.cpp ├── InputFiles.h ├── InputSection.cpp ├── InputSection.h ├── LinkerScript.cpp ├── LinkerScript.h ├── MapFile.cpp ├── MapFile.h ├── MarkLive.cpp ├── MarkLive.h ├── Options.td ├── OutputSections.cpp ├── OutputSections.h ├── README.md ├── Relocations.cpp ├── Relocations.h ├── ScriptLexer.cpp ├── ScriptLexer.h ├── ScriptParser.cpp ├── ScriptParser.h ├── SymbolTable.cpp ├── SymbolTable.h ├── Symbols.cpp ├── Symbols.h ├── SyntheticSections.cpp ├── SyntheticSections.h ├── Target.cpp ├── Target.h ├── Thunks.cpp ├── Thunks.h ├── Writer.cpp └── Writer.h ├── LICENSE.TXT ├── README.md ├── cmake └── modules │ ├── AddLLD.cmake │ └── FindVTune.cmake ├── include └── lld │ └── Common │ ├── Args.h │ ├── DWARF.h │ ├── Driver.h │ ├── ErrorHandler.h │ ├── Filesystem.h │ ├── LLVM.h │ ├── Memory.h │ ├── Reproduce.h │ ├── Strings.h │ ├── Threads.h │ ├── Version.h │ └── Version.inc.in └── tools └── lld ├── CMakeLists.txt └── lld.cpp /.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: LLVM 2 | -------------------------------------------------------------------------------- /.clang-tidy: -------------------------------------------------------------------------------- 1 | # Almost identical to the top-level .clang-tidy, except that {Member,Parameter,Variable}Case use camelBack. 2 | Checks: '-*,clang-diagnostic-*,llvm-*,misc-*,-misc-unused-parameters,-misc-non-private-member-variables-in-classes,readability-identifier-naming' 3 | CheckOptions: 4 | - key: readability-identifier-naming.ClassCase 5 | value: CamelCase 6 | - key: readability-identifier-naming.EnumCase 7 | value: CamelCase 8 | - key: readability-identifier-naming.FunctionCase 9 | value: camelBack 10 | - key: readability-identifier-naming.MemberCase 11 | value: camelBack 12 | - key: readability-identifier-naming.ParameterCase 13 | value: camelBack 14 | - key: readability-identifier-naming.UnionCase 15 | value: CamelCase 16 | - key: readability-identifier-naming.VariableCase 17 | value: camelBack 18 | - key: readability-identifier-naming.IgnoreMainLikeFunctions 19 | value: 1 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | #==============================================================================# 2 | # This file specifies intentionally untracked files that git should ignore. 3 | # See: http://www.kernel.org/pub/software/scm/git/docs/gitignore.html 4 | #==============================================================================# 5 | 6 | #==============================================================================# 7 | # File extensions to be ignored anywhere in the tree. 8 | #==============================================================================# 9 | # Temp files created by most text editors. 10 | *~ 11 | # Merge files created by git. 12 | *.orig 13 | # Byte compiled python modules. 14 | *.pyc 15 | # vim swap files 16 | .*.swp 17 | # Mac OS X Finder layout info 18 | .DS_Store 19 | 20 | #==============================================================================# 21 | # Directories to be ignored. 22 | #==============================================================================# 23 | # Sphinx build files. 24 | docs/_build 25 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Check if lld is built as a standalone project. 2 | if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) 3 | project(lld) 4 | cmake_minimum_required(VERSION 3.4.3) 5 | 6 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 7 | set(LLD_BUILT_STANDALONE TRUE) 8 | 9 | find_program(LLVM_CONFIG_PATH "llvm-config" DOC "Path to llvm-config binary") 10 | if(NOT LLVM_CONFIG_PATH) 11 | message(FATAL_ERROR "llvm-config not found: specify LLVM_CONFIG_PATH") 12 | endif() 13 | 14 | execute_process(COMMAND "${LLVM_CONFIG_PATH}" 15 | "--obj-root" 16 | "--includedir" 17 | "--cmakedir" 18 | "--src-root" 19 | RESULT_VARIABLE HAD_ERROR 20 | OUTPUT_VARIABLE LLVM_CONFIG_OUTPUT 21 | OUTPUT_STRIP_TRAILING_WHITESPACE) 22 | if(HAD_ERROR) 23 | message(FATAL_ERROR "llvm-config failed with status ${HAD_ERROR}") 24 | endif() 25 | 26 | string(REGEX REPLACE "[ \t]*[\r\n]+[ \t]*" ";" LLVM_CONFIG_OUTPUT "${LLVM_CONFIG_OUTPUT}") 27 | 28 | list(GET LLVM_CONFIG_OUTPUT 0 OBJ_ROOT) 29 | list(GET LLVM_CONFIG_OUTPUT 1 MAIN_INCLUDE_DIR) 30 | list(GET LLVM_CONFIG_OUTPUT 2 LLVM_CMAKE_PATH) 31 | list(GET LLVM_CONFIG_OUTPUT 3 MAIN_SRC_DIR) 32 | 33 | set(LLVM_OBJ_ROOT ${OBJ_ROOT} CACHE PATH "path to LLVM build tree") 34 | set(LLVM_MAIN_INCLUDE_DIR ${MAIN_INCLUDE_DIR} CACHE PATH "path to llvm/include") 35 | set(LLVM_MAIN_SRC_DIR ${MAIN_SRC_DIR} CACHE PATH "Path to LLVM source tree") 36 | 37 | file(TO_CMAKE_PATH ${LLVM_OBJ_ROOT} LLVM_BINARY_DIR) 38 | 39 | if(NOT EXISTS "${LLVM_CMAKE_PATH}/LLVMConfig.cmake") 40 | message(FATAL_ERROR "LLVMConfig.cmake not found") 41 | endif() 42 | include("${LLVM_CMAKE_PATH}/LLVMConfig.cmake") 43 | 44 | list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_PATH}") 45 | 46 | set(PACKAGE_VERSION "${LLVM_PACKAGE_VERSION}") 47 | include_directories("${LLVM_BINARY_DIR}/include" ${LLVM_INCLUDE_DIRS}) 48 | link_directories(${LLVM_LIBRARY_DIRS}) 49 | 50 | set(LLVM_LIBRARY_OUTPUT_INTDIR ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/lib${LLVM_LIBDIR_SUFFIX}) 51 | set(LLVM_RUNTIME_OUTPUT_INTDIR ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin) 52 | find_program(LLVM_TABLEGEN_EXE "llvm-tblgen" ${LLVM_TOOLS_BINARY_DIR} NO_DEFAULT_PATH) 53 | 54 | include(AddLLVM) 55 | include(TableGen) 56 | include(HandleLLVMOptions) 57 | 58 | if(LLVM_INCLUDE_TESTS) 59 | include(FindPythonInterp) 60 | if(NOT PYTHONINTERP_FOUND) 61 | message(FATAL_ERROR 62 | "Unable to find Python interpreter, required for testing. 63 | 64 | Please install Python or specify the PYTHON_EXECUTABLE CMake variable.") 65 | endif() 66 | 67 | if(${PYTHON_VERSION_STRING} VERSION_LESS 2.7) 68 | message(FATAL_ERROR "Python 2.7 or newer is required") 69 | endif() 70 | 71 | # Check prebuilt llvm/utils. 72 | if(EXISTS ${LLVM_TOOLS_BINARY_DIR}/FileCheck${CMAKE_EXECUTABLE_SUFFIX} 73 | AND EXISTS ${LLVM_TOOLS_BINARY_DIR}/not${CMAKE_EXECUTABLE_SUFFIX}) 74 | set(LLVM_UTILS_PROVIDED ON) 75 | endif() 76 | 77 | if(EXISTS ${LLVM_MAIN_SRC_DIR}/utils/lit/lit.py) 78 | # Note: path not really used, except for checking if lit was found 79 | set(LLVM_LIT ${LLVM_MAIN_SRC_DIR}/utils/lit/lit.py) 80 | if(NOT LLVM_UTILS_PROVIDED) 81 | add_subdirectory(${LLVM_MAIN_SRC_DIR}/utils/FileCheck utils/FileCheck) 82 | add_subdirectory(${LLVM_MAIN_SRC_DIR}/utils/not utils/not) 83 | set(LLVM_UTILS_PROVIDED ON) 84 | set(LLD_TEST_DEPS FileCheck not) 85 | endif() 86 | set(UNITTEST_DIR ${LLVM_MAIN_SRC_DIR}/utils/unittest) 87 | if(EXISTS ${UNITTEST_DIR}/googletest/include/gtest/gtest.h 88 | AND NOT EXISTS ${LLVM_LIBRARY_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}gtest${CMAKE_STATIC_LIBRARY_SUFFIX} 89 | AND EXISTS ${UNITTEST_DIR}/CMakeLists.txt) 90 | add_subdirectory(${UNITTEST_DIR} utils/unittest) 91 | endif() 92 | else() 93 | # Seek installed Lit. 94 | find_program(LLVM_LIT 95 | NAMES llvm-lit lit.py lit 96 | PATHS "${LLVM_MAIN_SRC_DIR}/utils/lit" 97 | DOC "Path to lit.py") 98 | endif() 99 | 100 | if(LLVM_LIT) 101 | # Define the default arguments to use with 'lit', and an option for the user 102 | # to override. 103 | set(LIT_ARGS_DEFAULT "-sv") 104 | if (MSVC OR XCODE) 105 | set(LIT_ARGS_DEFAULT "${LIT_ARGS_DEFAULT} --no-progress-bar") 106 | endif() 107 | set(LLVM_LIT_ARGS "${LIT_ARGS_DEFAULT}" CACHE STRING "Default options for lit") 108 | 109 | # On Win32 hosts, provide an option to specify the path to the GnuWin32 tools. 110 | if(WIN32 AND NOT CYGWIN) 111 | set(LLVM_LIT_TOOLS_DIR "" CACHE PATH "Path to GnuWin32 tools") 112 | endif() 113 | else() 114 | set(LLVM_INCLUDE_TESTS OFF) 115 | endif() 116 | endif() 117 | endif() 118 | 119 | set(LLD_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) 120 | set(LLD_INCLUDE_DIR ${LLD_SOURCE_DIR}/include ) 121 | set(LLD_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}) 122 | 123 | # Compute the LLD version from the LLVM version. 124 | string(REGEX MATCH "[0-9]+\\.[0-9]+(\\.[0-9]+)?" LLD_VERSION 125 | ${PACKAGE_VERSION}) 126 | message(STATUS "LLD version: ${LLD_VERSION}") 127 | 128 | string(REGEX REPLACE "([0-9]+)\\.[0-9]+(\\.[0-9]+)?" "\\1" LLD_VERSION_MAJOR 129 | ${LLD_VERSION}) 130 | string(REGEX REPLACE "[0-9]+\\.([0-9]+)(\\.[0-9]+)?" "\\1" LLD_VERSION_MINOR 131 | ${LLD_VERSION}) 132 | 133 | # Configure the Version.inc file. 134 | configure_file( 135 | ${CMAKE_CURRENT_SOURCE_DIR}/include/lld/Common/Version.inc.in 136 | ${CMAKE_CURRENT_BINARY_DIR}/include/lld/Common/Version.inc) 137 | 138 | 139 | if (CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR) 140 | message(FATAL_ERROR "In-source builds are not allowed. CMake would overwrite " 141 | "the makefiles distributed with LLVM. Please create a directory and run cmake " 142 | "from there, passing the path to this source directory as the last argument. " 143 | "This process created the file `CMakeCache.txt' and the directory " 144 | "`CMakeFiles'. Please delete them.") 145 | endif() 146 | 147 | list (APPEND CMAKE_MODULE_PATH "${LLD_SOURCE_DIR}/cmake/modules") 148 | 149 | include(AddLLD) 150 | 151 | option(LLD_BUILD_TOOLS 152 | "Build the lld tools. If OFF, just generate build targets." ON) 153 | 154 | include_directories(BEFORE 155 | ${CMAKE_CURRENT_BINARY_DIR}/include 156 | ${CMAKE_CURRENT_SOURCE_DIR}/include 157 | ) 158 | 159 | if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY) 160 | install(DIRECTORY include/ 161 | DESTINATION include 162 | FILES_MATCHING 163 | PATTERN "*.h" 164 | PATTERN ".svn" EXCLUDE 165 | ) 166 | endif() 167 | 168 | add_subdirectory(Common) 169 | add_subdirectory(tools/lld) 170 | 171 | add_subdirectory(ELF) 172 | -------------------------------------------------------------------------------- /CODE_OWNERS.TXT: -------------------------------------------------------------------------------- 1 | This file is a list of the people responsible for ensuring that patches for a 2 | particular part of LLD are reviewed, either by themself or by someone else. 3 | They are also the gatekeepers for their part of LLD, with the final word on 4 | what goes in or not. 5 | 6 | The list is sorted by surname and formatted to allow easy grepping and 7 | beautification by scripts. The fields are: name (N), email (E), web-address 8 | (W), PGP key ID and fingerprint (P), description (D), and snail-mail address 9 | (S). Each entry should contain at least the (N), (E) and (D) fields. 10 | 11 | 12 | N: Rui Ueyama 13 | E: ruiu@google.com 14 | D: COFF, ELF backends (COFF/* ELF/*) 15 | 16 | N: Lang Hames, Nick Kledzik 17 | E: lhames@gmail.com, kledzik@apple.com 18 | D: Mach-O backend 19 | 20 | N: Sam Clegg 21 | E: sbc@chromium.org 22 | D: WebAssembly backend (wasm/*) 23 | -------------------------------------------------------------------------------- /Common/Args.cpp: -------------------------------------------------------------------------------- 1 | //===- Args.cpp -----------------------------------------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | #include "lld/Common/Args.h" 10 | #include "lld/Common/ErrorHandler.h" 11 | #include "llvm/ADT/SmallVector.h" 12 | #include "llvm/ADT/StringExtras.h" 13 | #include "llvm/ADT/StringRef.h" 14 | #include "llvm/Option/ArgList.h" 15 | #include "llvm/Support/Path.h" 16 | 17 | using namespace llvm; 18 | using namespace lld; 19 | 20 | // TODO(sbc): Remove this once CGOptLevel can be set completely based on bitcode 21 | // function metadata. 22 | CodeGenOpt::Level lld::args::getCGOptLevel(int optLevelLTO) { 23 | if (optLevelLTO == 3) 24 | return CodeGenOpt::Aggressive; 25 | assert(optLevelLTO < 3); 26 | return CodeGenOpt::Default; 27 | } 28 | 29 | int64_t lld::args::getInteger(opt::InputArgList &args, unsigned key, 30 | int64_t Default) { 31 | auto *a = args.getLastArg(key); 32 | if (!a) 33 | return Default; 34 | 35 | int64_t v; 36 | if (to_integer(a->getValue(), v, 10)) 37 | return v; 38 | 39 | StringRef spelling = args.getArgString(a->getIndex()); 40 | error(spelling + ": number expected, but got '" + a->getValue() + "'"); 41 | return 0; 42 | } 43 | 44 | std::vector lld::args::getStrings(opt::InputArgList &args, int id) { 45 | std::vector v; 46 | for (auto *arg : args.filtered(id)) 47 | v.push_back(arg->getValue()); 48 | return v; 49 | } 50 | 51 | uint64_t lld::args::getZOptionValue(opt::InputArgList &args, int id, 52 | StringRef key, uint64_t Default) { 53 | for (auto *arg : args.filtered_reverse(id)) { 54 | std::pair kv = StringRef(arg->getValue()).split('='); 55 | if (kv.first == key) { 56 | uint64_t result = Default; 57 | if (!to_integer(kv.second, result)) 58 | error("invalid " + key + ": " + kv.second); 59 | return result; 60 | } 61 | } 62 | return Default; 63 | } 64 | 65 | std::vector lld::args::getLines(MemoryBufferRef mb) { 66 | SmallVector arr; 67 | mb.getBuffer().split(arr, '\n'); 68 | 69 | std::vector ret; 70 | for (StringRef s : arr) { 71 | s = s.trim(); 72 | if (!s.empty() && s[0] != '#') 73 | ret.push_back(s); 74 | } 75 | return ret; 76 | } 77 | 78 | StringRef lld::args::getFilenameWithoutExe(StringRef path) { 79 | if (path.endswith_lower(".exe")) 80 | return sys::path::stem(path); 81 | return sys::path::filename(path); 82 | } 83 | -------------------------------------------------------------------------------- /Common/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | if(NOT LLD_BUILT_STANDALONE) 2 | set(tablegen_deps intrinsics_gen) 3 | endif() 4 | 5 | find_first_existing_vc_file("${LLVM_MAIN_SRC_DIR}" llvm_vc) 6 | find_first_existing_vc_file("${LLD_SOURCE_DIR}" lld_vc) 7 | 8 | set(version_inc "${CMAKE_CURRENT_BINARY_DIR}/VCSVersion.inc") 9 | set(generate_vcs_version_script "${LLVM_CMAKE_PATH}/GenerateVersionFromVCS.cmake") 10 | 11 | if(lld_vc AND LLVM_APPEND_VC_REV) 12 | set(lld_source_dir ${LLD_SOURCE_DIR}) 13 | endif() 14 | 15 | add_custom_command(OUTPUT "${version_inc}" 16 | DEPENDS "${lld_vc}" "${generate_vcs_version_script}" 17 | COMMAND ${CMAKE_COMMAND} "-DNAMES=LLD" 18 | "-DLLD_SOURCE_DIR=${lld_source_dir}" 19 | "-DHEADER_FILE=${version_inc}" 20 | -P "${generate_vcs_version_script}") 21 | 22 | # Mark the generated header as being generated. 23 | set_source_files_properties("${version_inc}" 24 | PROPERTIES GENERATED TRUE 25 | HEADER_FILE_ONLY TRUE) 26 | 27 | set_property(SOURCE Version.cpp APPEND PROPERTY 28 | COMPILE_DEFINITIONS "HAVE_VCS_VERSION_INC") 29 | 30 | add_lld_library(lldCommon 31 | Args.cpp 32 | DWARF.cpp 33 | ErrorHandler.cpp 34 | Filesystem.cpp 35 | Memory.cpp 36 | Reproduce.cpp 37 | Strings.cpp 38 | VCSVersion.inc 39 | Version.cpp 40 | 41 | ADDITIONAL_HEADER_DIRS 42 | ${LLD_INCLUDE_DIR}/lld/Common 43 | 44 | LINK_COMPONENTS 45 | Codegen 46 | Core 47 | DebugInfoDWARF 48 | Demangle 49 | MC 50 | Option 51 | Support 52 | Target 53 | 54 | LINK_LIBS 55 | ${LLVM_PTHREAD_LIB} 56 | 57 | DEPENDS 58 | ${tablegen_deps} 59 | ) 60 | -------------------------------------------------------------------------------- /Common/DWARF.cpp: -------------------------------------------------------------------------------- 1 | //===- DWARF.cpp ----------------------------------------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | #include "lld/Common/DWARF.h" 10 | #include "lld/Common/ErrorHandler.h" 11 | 12 | using namespace llvm; 13 | 14 | namespace lld { 15 | 16 | DWARFCache::DWARFCache(std::unique_ptr d) 17 | : dwarf(std::move(d)) { 18 | for (std::unique_ptr &cu : dwarf->compile_units()) { 19 | auto report = [](Error err) { 20 | handleAllErrors(std::move(err), 21 | [](ErrorInfoBase &info) { warn(info.message()); }); 22 | }; 23 | Expected expectedLT = 24 | dwarf->getLineTableForUnit(cu.get(), report); 25 | const DWARFDebugLine::LineTable *lt = nullptr; 26 | if (expectedLT) 27 | lt = *expectedLT; 28 | else 29 | report(expectedLT.takeError()); 30 | if (!lt) 31 | continue; 32 | lineTables.push_back(lt); 33 | 34 | // Loop over variable records and insert them to variableLoc. 35 | for (const auto &entry : cu->dies()) { 36 | DWARFDie die(cu.get(), &entry); 37 | // Skip all tags that are not variables. 38 | if (die.getTag() != dwarf::DW_TAG_variable) 39 | continue; 40 | 41 | // Skip if a local variable because we don't need them for generating 42 | // error messages. In general, only non-local symbols can fail to be 43 | // linked. 44 | if (!dwarf::toUnsigned(die.find(dwarf::DW_AT_external), 0)) 45 | continue; 46 | 47 | // Get the source filename index for the variable. 48 | unsigned file = dwarf::toUnsigned(die.find(dwarf::DW_AT_decl_file), 0); 49 | if (!lt->hasFileAtIndex(file)) 50 | continue; 51 | 52 | // Get the line number on which the variable is declared. 53 | unsigned line = dwarf::toUnsigned(die.find(dwarf::DW_AT_decl_line), 0); 54 | 55 | // Here we want to take the variable name to add it into variableLoc. 56 | // Variable can have regular and linkage name associated. At first, we try 57 | // to get linkage name as it can be different, for example when we have 58 | // two variables in different namespaces of the same object. Use common 59 | // name otherwise, but handle the case when it also absent in case if the 60 | // input object file lacks some debug info. 61 | StringRef name = 62 | dwarf::toString(die.find(dwarf::DW_AT_linkage_name), 63 | dwarf::toString(die.find(dwarf::DW_AT_name), "")); 64 | if (!name.empty()) 65 | variableLoc.insert({name, {lt, file, line}}); 66 | } 67 | } 68 | } 69 | 70 | // Returns the pair of file name and line number describing location of data 71 | // object (variable, array, etc) definition. 72 | Optional> 73 | DWARFCache::getVariableLoc(StringRef name) { 74 | // Return if we have no debug information about data object. 75 | auto it = variableLoc.find(name); 76 | if (it == variableLoc.end()) 77 | return None; 78 | 79 | // Take file name string from line table. 80 | std::string fileName; 81 | if (!it->second.lt->getFileNameByIndex( 82 | it->second.file, {}, 83 | DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, fileName)) 84 | return None; 85 | 86 | return std::make_pair(fileName, it->second.line); 87 | } 88 | 89 | // Returns source line information for a given offset 90 | // using DWARF debug info. 91 | Optional DWARFCache::getDILineInfo(uint64_t offset, 92 | uint64_t sectionIndex) { 93 | DILineInfo info; 94 | for (const llvm::DWARFDebugLine::LineTable *lt : lineTables) { 95 | if (lt->getFileLineInfoForAddress( 96 | {offset, sectionIndex}, nullptr, 97 | DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, info)) 98 | return info; 99 | } 100 | return None; 101 | } 102 | 103 | } // namespace lld 104 | -------------------------------------------------------------------------------- /Common/ErrorHandler.cpp: -------------------------------------------------------------------------------- 1 | //===- ErrorHandler.cpp ---------------------------------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | #include "lld/Common/ErrorHandler.h" 10 | 11 | #include "lld/Common/Threads.h" 12 | 13 | #include "llvm/ADT/Twine.h" 14 | #include "llvm/IR/DiagnosticInfo.h" 15 | #include "llvm/IR/DiagnosticPrinter.h" 16 | #include "llvm/Support/ManagedStatic.h" 17 | #include "llvm/Support/raw_ostream.h" 18 | #include 19 | #include 20 | 21 | #if !defined(_MSC_VER) && !defined(__MINGW32__) 22 | #include 23 | #endif 24 | 25 | using namespace llvm; 26 | using namespace lld; 27 | 28 | // The functions defined in this file can be called from multiple threads, 29 | // but lld::outs() or lld::errs() are not thread-safe. We protect them using a 30 | // mutex. 31 | static std::mutex mu; 32 | 33 | // We want to separate multi-line messages with a newline. `sep` is "\n" 34 | // if the last messages was multi-line. Otherwise "". 35 | static StringRef sep; 36 | 37 | static StringRef getSeparator(const Twine &msg) { 38 | if (StringRef(msg.str()).contains('\n')) 39 | return "\n"; 40 | return ""; 41 | } 42 | 43 | raw_ostream *lld::stdoutOS; 44 | raw_ostream *lld::stderrOS; 45 | 46 | raw_ostream &lld::outs() { return stdoutOS ? *stdoutOS : llvm::outs(); } 47 | raw_ostream &lld::errs() { return stderrOS ? *stderrOS : llvm::errs(); } 48 | 49 | ErrorHandler &lld::errorHandler() { 50 | static ErrorHandler handler; 51 | return handler; 52 | } 53 | 54 | void lld::exitLld(int val) { 55 | // Delete any temporary file, while keeping the memory mapping open. 56 | if (errorHandler().outputBuffer) 57 | errorHandler().outputBuffer->discard(); 58 | 59 | // Dealloc/destroy ManagedStatic variables before calling _exit(). 60 | // In an LTO build, allows us to get the output of -time-passes. 61 | // Ensures that the thread pool for the parallel algorithms is stopped to 62 | // avoid intermittent crashes on Windows when exiting. 63 | llvm_shutdown(); 64 | 65 | { 66 | std::lock_guard lock(mu); 67 | lld::outs().flush(); 68 | lld::errs().flush(); 69 | } 70 | _exit(val); 71 | } 72 | 73 | void lld::diagnosticHandler(const DiagnosticInfo &di) { 74 | SmallString<128> s; 75 | raw_svector_ostream os(s); 76 | DiagnosticPrinterRawOStream dp(os); 77 | di.print(dp); 78 | switch (di.getSeverity()) { 79 | case DS_Error: 80 | error(s); 81 | break; 82 | case DS_Warning: 83 | warn(s); 84 | break; 85 | case DS_Remark: 86 | case DS_Note: 87 | message(s); 88 | break; 89 | } 90 | } 91 | 92 | void lld::checkError(Error e) { 93 | handleAllErrors(std::move(e), 94 | [&](ErrorInfoBase &eib) { error(eib.message()); }); 95 | } 96 | 97 | // This is for --vs-diagnostics. 98 | // 99 | // Normally, lld's error message starts with argv[0]. Therefore, it usually 100 | // looks like this: 101 | // 102 | // ld.lld: error: ... 103 | // 104 | // This error message style is unfortunately unfriendly to Visual Studio 105 | // IDE. VS interprets the first word of the first line as an error location 106 | // and make it clickable, thus "ld.lld" in the above message would become a 107 | // clickable text. When you click it, VS opens "ld.lld" executable file with 108 | // a binary editor. 109 | // 110 | // As a workaround, we print out an error location instead of "ld.lld" if 111 | // lld is running in VS diagnostics mode. As a result, error message will 112 | // look like this: 113 | // 114 | // src/foo.c(35): error: ... 115 | // 116 | // This function returns an error location string. An error location is 117 | // extracted from an error message using regexps. 118 | std::string ErrorHandler::getLocation(const Twine &msg) { 119 | if (!vsDiagnostics) 120 | return std::string(logName); 121 | 122 | static std::regex regexes[] = { 123 | std::regex( 124 | R"(^undefined (?:\S+ )?symbol:.*\n)" 125 | R"(>>> referenced by .+\((\S+):(\d+)\))"), 126 | std::regex( 127 | R"(^undefined (?:\S+ )?symbol:.*\n>>> referenced by (\S+):(\d+))"), 128 | std::regex(R"(^undefined symbol:.*\n>>> referenced by (.*):)"), 129 | std::regex( 130 | R"(^duplicate symbol: .*\n>>> defined in (\S+)\n>>> defined in.*)"), 131 | std::regex( 132 | R"(^duplicate symbol: .*\n>>> defined at .+\((\S+):(\d+)\))"), 133 | std::regex(R"(^duplicate symbol: .*\n>>> defined at (\S+):(\d+))"), 134 | std::regex( 135 | R"(.*\n>>> defined in .*\n>>> referenced by .+\((\S+):(\d+)\))"), 136 | std::regex(R"(.*\n>>> defined in .*\n>>> referenced by (\S+):(\d+))"), 137 | std::regex(R"((\S+):(\d+): unclosed quote)"), 138 | }; 139 | 140 | std::string str = msg.str(); 141 | for (std::regex &re : regexes) { 142 | std::smatch m; 143 | if (!std::regex_search(str, m, re)) 144 | continue; 145 | 146 | assert(m.size() == 2 || m.size() == 3); 147 | if (m.size() == 2) 148 | return m.str(1); 149 | return m.str(1) + "(" + m.str(2) + ")"; 150 | } 151 | 152 | return std::string(logName); 153 | } 154 | 155 | void ErrorHandler::log(const Twine &msg) { 156 | if (!verbose) 157 | return; 158 | std::lock_guard lock(mu); 159 | lld::errs() << logName << ": " << msg << "\n"; 160 | } 161 | 162 | void ErrorHandler::message(const Twine &msg) { 163 | std::lock_guard lock(mu); 164 | lld::outs() << msg << "\n"; 165 | lld::outs().flush(); 166 | } 167 | 168 | void ErrorHandler::warn(const Twine &msg) { 169 | if (fatalWarnings) { 170 | error(msg); 171 | return; 172 | } 173 | 174 | std::lock_guard lock(mu); 175 | lld::errs() << sep << getLocation(msg) << ": " << Colors::MAGENTA 176 | << "warning: " << Colors::RESET << msg << "\n"; 177 | sep = getSeparator(msg); 178 | } 179 | 180 | void ErrorHandler::error(const Twine &msg) { 181 | // If Visual Studio-style error message mode is enabled, 182 | // this particular error is printed out as two errors. 183 | if (vsDiagnostics) { 184 | static std::regex re(R"(^(duplicate symbol: .*))" 185 | R"((\n>>> defined at \S+:\d+.*\n>>>.*))" 186 | R"((\n>>> defined at \S+:\d+.*\n>>>.*))"); 187 | std::string str = msg.str(); 188 | std::smatch m; 189 | 190 | if (std::regex_match(str, m, re)) { 191 | error(m.str(1) + m.str(2)); 192 | error(m.str(1) + m.str(3)); 193 | return; 194 | } 195 | } 196 | 197 | bool exit = false; 198 | { 199 | std::lock_guard lock(mu); 200 | 201 | if (errorLimit == 0 || errorCount < errorLimit) { 202 | lld::errs() << sep << getLocation(msg) << ": " << Colors::RED 203 | << "error: " << Colors::RESET << msg << "\n"; 204 | } else if (errorCount == errorLimit) { 205 | lld::errs() << sep << getLocation(msg) << ": " << Colors::RED 206 | << "error: " << Colors::RESET << errorLimitExceededMsg 207 | << "\n"; 208 | exit = exitEarly; 209 | } 210 | 211 | sep = getSeparator(msg); 212 | ++errorCount; 213 | } 214 | 215 | if (exit) 216 | exitLld(1); 217 | } 218 | 219 | void ErrorHandler::fatal(const Twine &msg) { 220 | error(msg); 221 | exitLld(1); 222 | } 223 | -------------------------------------------------------------------------------- /Common/Filesystem.cpp: -------------------------------------------------------------------------------- 1 | //===- Filesystem.cpp -----------------------------------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // 9 | // This file contains a few utility functions to handle files. 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #include "lld/Common/Filesystem.h" 14 | #include "lld/Common/Threads.h" 15 | #include "llvm/Config/llvm-config.h" 16 | #include "llvm/Support/FileOutputBuffer.h" 17 | #include "llvm/Support/FileSystem.h" 18 | #if LLVM_ON_UNIX 19 | #include 20 | #endif 21 | #include 22 | 23 | using namespace llvm; 24 | using namespace lld; 25 | 26 | // Removes a given file asynchronously. This is a performance hack, 27 | // so remove this when operating systems are improved. 28 | // 29 | // On Linux (and probably on other Unix-like systems), unlink(2) is a 30 | // noticeably slow system call. As of 2016, unlink takes 250 31 | // milliseconds to remove a 1 GB file on ext4 filesystem on my machine. 32 | // 33 | // To create a new result file, we first remove existing file. So, if 34 | // you repeatedly link a 1 GB program in a regular compile-link-debug 35 | // cycle, every cycle wastes 250 milliseconds only to remove a file. 36 | // Since LLD can link a 1 GB binary in about 5 seconds, that waste 37 | // actually counts. 38 | // 39 | // This function spawns a background thread to remove the file. 40 | // The calling thread returns almost immediately. 41 | void lld::unlinkAsync(StringRef path) { 42 | // Removing a file is async on windows. 43 | #if defined(_WIN32) 44 | sys::fs::remove(path); 45 | #else 46 | if (parallel::strategy.ThreadsRequested == 1 || !sys::fs::exists(path) || 47 | !sys::fs::is_regular_file(path)) 48 | return; 49 | 50 | // We cannot just remove path from a different thread because we are now going 51 | // to create path as a new file. 52 | // Instead we open the file and unlink it on this thread. The unlink is fast 53 | // since the open fd guarantees that it is not removing the last reference. 54 | int fd; 55 | std::error_code ec = sys::fs::openFileForRead(path, fd); 56 | sys::fs::remove(path); 57 | 58 | if (ec) 59 | return; 60 | 61 | // close and therefore remove TempPath in background. 62 | std::mutex m; 63 | std::condition_variable cv; 64 | bool started = false; 65 | std::thread([&, fd] { 66 | { 67 | std::lock_guard l(m); 68 | started = true; 69 | cv.notify_all(); 70 | } 71 | ::close(fd); 72 | }).detach(); 73 | 74 | // GLIBC 2.26 and earlier have race condition that crashes an entire process 75 | // if the main thread calls exit(2) while other thread is starting up. 76 | std::unique_lock l(m); 77 | cv.wait(l, [&] { return started; }); 78 | #endif 79 | } 80 | 81 | // Simulate file creation to see if Path is writable. 82 | // 83 | // Determining whether a file is writable or not is amazingly hard, 84 | // and after all the only reliable way of doing that is to actually 85 | // create a file. But we don't want to do that in this function 86 | // because LLD shouldn't update any file if it will end in a failure. 87 | // We also don't want to reimplement heuristics to determine if a 88 | // file is writable. So we'll let FileOutputBuffer do the work. 89 | // 90 | // FileOutputBuffer doesn't touch a destination file until commit() 91 | // is called. We use that class without calling commit() to predict 92 | // if the given file is writable. 93 | std::error_code lld::tryCreateFile(StringRef path) { 94 | if (path.empty()) 95 | return std::error_code(); 96 | if (path == "-") 97 | return std::error_code(); 98 | return errorToErrorCode(FileOutputBuffer::create(path, 1).takeError()); 99 | } 100 | -------------------------------------------------------------------------------- /Common/Memory.cpp: -------------------------------------------------------------------------------- 1 | //===- Memory.cpp ---------------------------------------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | #include "lld/Common/Memory.h" 10 | 11 | using namespace llvm; 12 | using namespace lld; 13 | 14 | BumpPtrAllocator lld::bAlloc; 15 | StringSaver lld::saver{bAlloc}; 16 | std::vector lld::SpecificAllocBase::instances; 17 | 18 | void lld::freeArena() { 19 | for (SpecificAllocBase *alloc : SpecificAllocBase::instances) 20 | alloc->reset(); 21 | bAlloc.Reset(); 22 | } 23 | -------------------------------------------------------------------------------- /Common/Reproduce.cpp: -------------------------------------------------------------------------------- 1 | //===- Reproduce.cpp - Utilities for creating reproducers -----------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | #include "lld/Common/Reproduce.h" 10 | #include "llvm/Option/Arg.h" 11 | #include "llvm/Support/Error.h" 12 | #include "llvm/Support/FileSystem.h" 13 | #include "llvm/Support/Path.h" 14 | 15 | using namespace lld; 16 | using namespace llvm; 17 | using namespace llvm::sys; 18 | 19 | // Makes a given pathname an absolute path first, and then remove 20 | // beginning /. For example, "../foo.o" is converted to "home/john/foo.o", 21 | // assuming that the current directory is "/home/john/bar". 22 | // Returned string is a forward slash separated path even on Windows to avoid 23 | // a mess with backslash-as-escape and backslash-as-path-separator. 24 | std::string lld::relativeToRoot(StringRef path) { 25 | SmallString<128> abs = path; 26 | if (fs::make_absolute(abs)) 27 | return std::string(path); 28 | path::remove_dots(abs, /*remove_dot_dot=*/true); 29 | 30 | // This is Windows specific. root_name() returns a drive letter 31 | // (e.g. "c:") or a UNC name (//net). We want to keep it as part 32 | // of the result. 33 | SmallString<128> res; 34 | StringRef root = path::root_name(abs); 35 | if (root.endswith(":")) 36 | res = root.drop_back(); 37 | else if (root.startswith("//")) 38 | res = root.substr(2); 39 | 40 | path::append(res, path::relative_path(abs)); 41 | return path::convert_to_slash(res); 42 | } 43 | 44 | // Quote a given string if it contains a space character. 45 | std::string lld::quote(StringRef s) { 46 | if (s.contains(' ')) 47 | return ("\"" + s + "\"").str(); 48 | return std::string(s); 49 | } 50 | 51 | // Converts an Arg to a string representation suitable for a response file. 52 | // To show an Arg in a diagnostic, use Arg::getAsString() instead. 53 | std::string lld::toString(const opt::Arg &arg) { 54 | std::string k = std::string(arg.getSpelling()); 55 | if (arg.getNumValues() == 0) 56 | return k; 57 | std::string v = quote(arg.getValue()); 58 | if (arg.getOption().getRenderStyle() == opt::Option::RenderJoinedStyle) 59 | return k + v; 60 | return k + " " + v; 61 | } 62 | -------------------------------------------------------------------------------- /Common/Strings.cpp: -------------------------------------------------------------------------------- 1 | //===- Strings.cpp -------------------------------------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | #include "lld/Common/Strings.h" 10 | #include "lld/Common/ErrorHandler.h" 11 | #include "lld/Common/LLVM.h" 12 | #include "llvm/Demangle/Demangle.h" 13 | #include "llvm/Support/GlobPattern.h" 14 | #include 15 | #include 16 | #include 17 | 18 | using namespace llvm; 19 | using namespace lld; 20 | 21 | // Returns the demangled C++ symbol name for name. 22 | std::string lld::demangleItanium(StringRef name) { 23 | // itaniumDemangle can be used to demangle strings other than symbol 24 | // names which do not necessarily start with "_Z". Name can be 25 | // either a C or C++ symbol. Don't call demangle if the name 26 | // does not look like a C++ symbol name to avoid getting unexpected 27 | // result for a C symbol that happens to match a mangled type name. 28 | if (!name.startswith("_Z")) 29 | return std::string(name); 30 | 31 | return demangle(std::string(name)); 32 | } 33 | 34 | SingleStringMatcher::SingleStringMatcher(StringRef Pattern) { 35 | if (Pattern.size() > 2 && Pattern.startswith("\"") && 36 | Pattern.endswith("\"")) { 37 | ExactMatch = true; 38 | ExactPattern = Pattern.substr(1, Pattern.size() - 2); 39 | } else { 40 | Expected Glob = GlobPattern::create(Pattern); 41 | if (!Glob) { 42 | error(toString(Glob.takeError())); 43 | return; 44 | } 45 | ExactMatch = false; 46 | GlobPatternMatcher = *Glob; 47 | } 48 | } 49 | 50 | bool SingleStringMatcher::match(StringRef s) const { 51 | return ExactMatch ? (ExactPattern == s) : GlobPatternMatcher.match(s); 52 | } 53 | 54 | bool StringMatcher::match(StringRef s) const { 55 | for (const SingleStringMatcher &pat : patterns) 56 | if (pat.match(s)) 57 | return true; 58 | return false; 59 | } 60 | 61 | // Converts a hex string (e.g. "deadbeef") to a vector. 62 | std::vector lld::parseHex(StringRef s) { 63 | std::vector hex; 64 | while (!s.empty()) { 65 | StringRef b = s.substr(0, 2); 66 | s = s.substr(2); 67 | uint8_t h; 68 | if (!to_integer(b, h, 16)) { 69 | error("not a hexadecimal value: " + b); 70 | return {}; 71 | } 72 | hex.push_back(h); 73 | } 74 | return hex; 75 | } 76 | 77 | // Returns true if S is valid as a C language identifier. 78 | bool lld::isValidCIdentifier(StringRef s) { 79 | return !s.empty() && (isAlpha(s[0]) || s[0] == '_') && 80 | std::all_of(s.begin() + 1, s.end(), 81 | [](char c) { return c == '_' || isAlnum(c); }); 82 | } 83 | 84 | // Write the contents of the a buffer to a file 85 | void lld::saveBuffer(StringRef buffer, const Twine &path) { 86 | std::error_code ec; 87 | raw_fd_ostream os(path.str(), ec, sys::fs::OpenFlags::OF_None); 88 | if (ec) 89 | error("cannot create " + path + ": " + ec.message()); 90 | os << buffer; 91 | } 92 | -------------------------------------------------------------------------------- /Common/Version.cpp: -------------------------------------------------------------------------------- 1 | //===- lib/Common/Version.cpp - LLD Version Number ---------------*- C++-=====// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // 9 | // This file defines several version-related utility functions for LLD. 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #include "lld/Common/Version.h" 14 | 15 | #ifdef HAVE_VCS_VERSION_INC 16 | #include "VCSVersion.inc" 17 | #endif 18 | 19 | // Returns a version string, e.g.: 20 | // lld 9.0.0 (https://github.com/llvm/llvm-project.git 9efdd7ac5e914d3c9fa1ef) 21 | std::string lld::getLLDVersion() { 22 | #if defined(LLD_REPOSITORY) && defined(LLD_REVISION) 23 | return "LLD " LLD_VERSION_STRING " (" LLD_REPOSITORY " " LLD_REVISION ")"; 24 | #else 25 | return "LLD " LLD_VERSION_STRING; 26 | #endif 27 | } 28 | -------------------------------------------------------------------------------- /ELF/Arch/RISCV.cpp: -------------------------------------------------------------------------------- 1 | //===- RISCV.cpp ----------------------------------------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | #include "InputFiles.h" 10 | #include "Symbols.h" 11 | #include "SyntheticSections.h" 12 | #include "Target.h" 13 | 14 | using namespace llvm; 15 | using namespace llvm::object; 16 | using namespace llvm::support::endian; 17 | using namespace llvm::ELF; 18 | 19 | namespace lld { 20 | namespace elf { 21 | 22 | namespace { 23 | 24 | class RISCV final : public TargetInfo { 25 | public: 26 | RISCV(); 27 | uint32_t calcEFlags() const override; 28 | void writeGotHeader(uint8_t *buf) const override; 29 | void writeGotPlt(uint8_t *buf, const Symbol &s) const override; 30 | void writePltHeader(uint8_t *buf) const override; 31 | void writePlt(uint8_t *buf, const Symbol &sym, 32 | uint64_t pltEntryAddr) const override; 33 | RelType getDynRel(RelType type) const override; 34 | RelExpr getRelExpr(RelType type, const Symbol &s, 35 | const uint8_t *loc) const override; 36 | void relocate(uint8_t *loc, const Relocation &rel, 37 | uint64_t val) const override; 38 | }; 39 | 40 | } // end anonymous namespace 41 | 42 | const uint64_t dtpOffset = 0x800; 43 | 44 | enum Op { 45 | ADDI = 0x13, 46 | AUIPC = 0x17, 47 | JALR = 0x67, 48 | LD = 0x3003, 49 | LW = 0x2003, 50 | SRLI = 0x5013, 51 | SUB = 0x40000033, 52 | }; 53 | 54 | enum Reg { 55 | X_RA = 1, 56 | X_T0 = 5, 57 | X_T1 = 6, 58 | X_T2 = 7, 59 | X_T3 = 28, 60 | }; 61 | 62 | static uint32_t hi20(uint32_t val) { return (val + 0x800) >> 12; } 63 | static uint32_t lo12(uint32_t val) { return val & 4095; } 64 | 65 | static uint32_t itype(uint32_t op, uint32_t rd, uint32_t rs1, uint32_t imm) { 66 | return op | (rd << 7) | (rs1 << 15) | (imm << 20); 67 | } 68 | static uint32_t rtype(uint32_t op, uint32_t rd, uint32_t rs1, uint32_t rs2) { 69 | return op | (rd << 7) | (rs1 << 15) | (rs2 << 20); 70 | } 71 | static uint32_t utype(uint32_t op, uint32_t rd, uint32_t imm) { 72 | return op | (rd << 7) | (imm << 12); 73 | } 74 | 75 | RISCV::RISCV() { 76 | copyRel = R_RISCV_COPY; 77 | noneRel = R_RISCV_NONE; 78 | pltRel = R_RISCV_JUMP_SLOT; 79 | relativeRel = R_RISCV_RELATIVE; 80 | iRelativeRel = R_RISCV_IRELATIVE; 81 | if (config->is64) { 82 | symbolicRel = R_RISCV_64; 83 | tlsModuleIndexRel = R_RISCV_TLS_DTPMOD64; 84 | tlsOffsetRel = R_RISCV_TLS_DTPREL64; 85 | tlsGotRel = R_RISCV_TLS_TPREL64; 86 | } else { 87 | symbolicRel = R_RISCV_32; 88 | tlsModuleIndexRel = R_RISCV_TLS_DTPMOD32; 89 | tlsOffsetRel = R_RISCV_TLS_DTPREL32; 90 | tlsGotRel = R_RISCV_TLS_TPREL32; 91 | } 92 | gotRel = symbolicRel; 93 | 94 | // .got[0] = _DYNAMIC 95 | gotBaseSymInGotPlt = false; 96 | gotHeaderEntriesNum = 1; 97 | 98 | // .got.plt[0] = _dl_runtime_resolve, .got.plt[1] = link_map 99 | gotPltHeaderEntriesNum = 2; 100 | 101 | pltHeaderSize = 32; 102 | pltEntrySize = 16; 103 | ipltEntrySize = 16; 104 | } 105 | 106 | static uint32_t getEFlags(InputFile *f) { 107 | if (config->is64) 108 | return cast>(f)->getObj().getHeader()->e_flags; 109 | return cast>(f)->getObj().getHeader()->e_flags; 110 | } 111 | 112 | uint32_t RISCV::calcEFlags() const { 113 | // If there are only binary input files (from -b binary), use a 114 | // value of 0 for the ELF header flags. 115 | if (objectFiles.empty()) 116 | return 0; 117 | 118 | uint32_t target = getEFlags(objectFiles.front()); 119 | 120 | for (InputFile *f : objectFiles) { 121 | uint32_t eflags = getEFlags(f); 122 | if (eflags & EF_RISCV_RVC) 123 | target |= EF_RISCV_RVC; 124 | 125 | if ((eflags & EF_RISCV_FLOAT_ABI) != (target & EF_RISCV_FLOAT_ABI)) 126 | error(toString(f) + 127 | ": cannot link object files with different floating-point ABI"); 128 | 129 | if ((eflags & EF_RISCV_RVE) != (target & EF_RISCV_RVE)) 130 | error(toString(f) + 131 | ": cannot link object files with different EF_RISCV_RVE"); 132 | } 133 | 134 | return target; 135 | } 136 | 137 | void RISCV::writeGotHeader(uint8_t *buf) const { 138 | if (config->is64) 139 | write64le(buf, mainPart->dynamic->getVA()); 140 | else 141 | write32le(buf, mainPart->dynamic->getVA()); 142 | } 143 | 144 | void RISCV::writeGotPlt(uint8_t *buf, const Symbol &s) const { 145 | if (config->is64) 146 | write64le(buf, in.plt->getVA()); 147 | else 148 | write32le(buf, in.plt->getVA()); 149 | } 150 | 151 | void RISCV::writePltHeader(uint8_t *buf) const { 152 | // 1: auipc t2, %pcrel_hi(.got.plt) 153 | // sub t1, t1, t3 154 | // l[wd] t3, %pcrel_lo(1b)(t2); t3 = _dl_runtime_resolve 155 | // addi t1, t1, -pltHeaderSize-12; t1 = &.plt[i] - &.plt[0] 156 | // addi t0, t2, %pcrel_lo(1b) 157 | // srli t1, t1, (rv64?1:2); t1 = &.got.plt[i] - &.got.plt[0] 158 | // l[wd] t0, Wordsize(t0); t0 = link_map 159 | // jr t3 160 | uint32_t offset = in.gotPlt->getVA() - in.plt->getVA(); 161 | uint32_t load = config->is64 ? LD : LW; 162 | write32le(buf + 0, utype(AUIPC, X_T2, hi20(offset))); 163 | write32le(buf + 4, rtype(SUB, X_T1, X_T1, X_T3)); 164 | write32le(buf + 8, itype(load, X_T3, X_T2, lo12(offset))); 165 | write32le(buf + 12, itype(ADDI, X_T1, X_T1, -target->pltHeaderSize - 12)); 166 | write32le(buf + 16, itype(ADDI, X_T0, X_T2, lo12(offset))); 167 | write32le(buf + 20, itype(SRLI, X_T1, X_T1, config->is64 ? 1 : 2)); 168 | write32le(buf + 24, itype(load, X_T0, X_T0, config->wordsize)); 169 | write32le(buf + 28, itype(JALR, 0, X_T3, 0)); 170 | } 171 | 172 | void RISCV::writePlt(uint8_t *buf, const Symbol &sym, 173 | uint64_t pltEntryAddr) const { 174 | // 1: auipc t3, %pcrel_hi(f@.got.plt) 175 | // l[wd] t3, %pcrel_lo(1b)(t3) 176 | // jalr t1, t3 177 | // nop 178 | uint32_t offset = sym.getGotPltVA() - pltEntryAddr; 179 | write32le(buf + 0, utype(AUIPC, X_T3, hi20(offset))); 180 | write32le(buf + 4, itype(config->is64 ? LD : LW, X_T3, X_T3, lo12(offset))); 181 | write32le(buf + 8, itype(JALR, X_T1, X_T3, 0)); 182 | write32le(buf + 12, itype(ADDI, 0, 0, 0)); 183 | } 184 | 185 | RelType RISCV::getDynRel(RelType type) const { 186 | return type == target->symbolicRel ? type 187 | : static_cast(R_RISCV_NONE); 188 | } 189 | 190 | RelExpr RISCV::getRelExpr(const RelType type, const Symbol &s, 191 | const uint8_t *loc) const { 192 | switch (type) { 193 | case R_RISCV_NONE: 194 | return R_NONE; 195 | case R_RISCV_32: 196 | case R_RISCV_64: 197 | case R_RISCV_HI20: 198 | case R_RISCV_LO12_I: 199 | case R_RISCV_LO12_S: 200 | case R_RISCV_RVC_LUI: 201 | return R_ABS; 202 | case R_RISCV_ADD8: 203 | case R_RISCV_ADD16: 204 | case R_RISCV_ADD32: 205 | case R_RISCV_ADD64: 206 | case R_RISCV_SET6: 207 | case R_RISCV_SET8: 208 | case R_RISCV_SET16: 209 | case R_RISCV_SET32: 210 | case R_RISCV_SUB6: 211 | case R_RISCV_SUB8: 212 | case R_RISCV_SUB16: 213 | case R_RISCV_SUB32: 214 | case R_RISCV_SUB64: 215 | return R_RISCV_ADD; 216 | case R_RISCV_JAL: 217 | case R_RISCV_BRANCH: 218 | case R_RISCV_PCREL_HI20: 219 | case R_RISCV_RVC_BRANCH: 220 | case R_RISCV_RVC_JUMP: 221 | case R_RISCV_32_PCREL: 222 | return R_PC; 223 | case R_RISCV_CALL: 224 | case R_RISCV_CALL_PLT: 225 | return R_PLT_PC; 226 | case R_RISCV_GOT_HI20: 227 | return R_GOT_PC; 228 | case R_RISCV_PCREL_LO12_I: 229 | case R_RISCV_PCREL_LO12_S: 230 | return R_RISCV_PC_INDIRECT; 231 | case R_RISCV_TLS_GD_HI20: 232 | return R_TLSGD_PC; 233 | case R_RISCV_TLS_GOT_HI20: 234 | config->hasStaticTlsModel = true; 235 | return R_GOT_PC; 236 | case R_RISCV_TPREL_HI20: 237 | case R_RISCV_TPREL_LO12_I: 238 | case R_RISCV_TPREL_LO12_S: 239 | return R_TLS; 240 | case R_RISCV_RELAX: 241 | case R_RISCV_TPREL_ADD: 242 | return R_NONE; 243 | case R_RISCV_ALIGN: 244 | // Not just a hint; always padded to the worst-case number of NOPs, so may 245 | // not currently be aligned, and without linker relaxation support we can't 246 | // delete NOPs to realign. 247 | errorOrWarn(getErrorLocation(loc) + "relocation R_RISCV_ALIGN requires " 248 | "unimplemented linker relaxation; recompile with -mno-relax"); 249 | return R_NONE; 250 | default: 251 | error(getErrorLocation(loc) + "unknown relocation (" + Twine(type) + 252 | ") against symbol " + toString(s)); 253 | return R_NONE; 254 | } 255 | } 256 | 257 | // Extract bits V[Begin:End], where range is inclusive, and Begin must be < 63. 258 | static uint32_t extractBits(uint64_t v, uint32_t begin, uint32_t end) { 259 | return (v & ((1ULL << (begin + 1)) - 1)) >> end; 260 | } 261 | 262 | void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const { 263 | const unsigned bits = config->wordsize * 8; 264 | 265 | switch (rel.type) { 266 | case R_RISCV_32: 267 | write32le(loc, val); 268 | return; 269 | case R_RISCV_64: 270 | write64le(loc, val); 271 | return; 272 | 273 | case R_RISCV_RVC_BRANCH: { 274 | checkInt(loc, static_cast(val) >> 1, 8, rel); 275 | checkAlignment(loc, val, 2, rel); 276 | uint16_t insn = read16le(loc) & 0xE383; 277 | uint16_t imm8 = extractBits(val, 8, 8) << 12; 278 | uint16_t imm4_3 = extractBits(val, 4, 3) << 10; 279 | uint16_t imm7_6 = extractBits(val, 7, 6) << 5; 280 | uint16_t imm2_1 = extractBits(val, 2, 1) << 3; 281 | uint16_t imm5 = extractBits(val, 5, 5) << 2; 282 | insn |= imm8 | imm4_3 | imm7_6 | imm2_1 | imm5; 283 | 284 | write16le(loc, insn); 285 | return; 286 | } 287 | 288 | case R_RISCV_RVC_JUMP: { 289 | checkInt(loc, static_cast(val) >> 1, 11, rel); 290 | checkAlignment(loc, val, 2, rel); 291 | uint16_t insn = read16le(loc) & 0xE003; 292 | uint16_t imm11 = extractBits(val, 11, 11) << 12; 293 | uint16_t imm4 = extractBits(val, 4, 4) << 11; 294 | uint16_t imm9_8 = extractBits(val, 9, 8) << 9; 295 | uint16_t imm10 = extractBits(val, 10, 10) << 8; 296 | uint16_t imm6 = extractBits(val, 6, 6) << 7; 297 | uint16_t imm7 = extractBits(val, 7, 7) << 6; 298 | uint16_t imm3_1 = extractBits(val, 3, 1) << 3; 299 | uint16_t imm5 = extractBits(val, 5, 5) << 2; 300 | insn |= imm11 | imm4 | imm9_8 | imm10 | imm6 | imm7 | imm3_1 | imm5; 301 | 302 | write16le(loc, insn); 303 | return; 304 | } 305 | 306 | case R_RISCV_RVC_LUI: { 307 | int64_t imm = SignExtend64(val + 0x800, bits) >> 12; 308 | checkInt(loc, imm, 6, rel); 309 | if (imm == 0) { // `c.lui rd, 0` is illegal, convert to `c.li rd, 0` 310 | write16le(loc, (read16le(loc) & 0x0F83) | 0x4000); 311 | } else { 312 | uint16_t imm17 = extractBits(val + 0x800, 17, 17) << 12; 313 | uint16_t imm16_12 = extractBits(val + 0x800, 16, 12) << 2; 314 | write16le(loc, (read16le(loc) & 0xEF83) | imm17 | imm16_12); 315 | } 316 | return; 317 | } 318 | 319 | case R_RISCV_JAL: { 320 | checkInt(loc, static_cast(val) >> 1, 20, rel); 321 | checkAlignment(loc, val, 2, rel); 322 | 323 | uint32_t insn = read32le(loc) & 0xFFF; 324 | uint32_t imm20 = extractBits(val, 20, 20) << 31; 325 | uint32_t imm10_1 = extractBits(val, 10, 1) << 21; 326 | uint32_t imm11 = extractBits(val, 11, 11) << 20; 327 | uint32_t imm19_12 = extractBits(val, 19, 12) << 12; 328 | insn |= imm20 | imm10_1 | imm11 | imm19_12; 329 | 330 | write32le(loc, insn); 331 | return; 332 | } 333 | 334 | case R_RISCV_BRANCH: { 335 | checkInt(loc, static_cast(val) >> 1, 12, rel); 336 | checkAlignment(loc, val, 2, rel); 337 | 338 | uint32_t insn = read32le(loc) & 0x1FFF07F; 339 | uint32_t imm12 = extractBits(val, 12, 12) << 31; 340 | uint32_t imm10_5 = extractBits(val, 10, 5) << 25; 341 | uint32_t imm4_1 = extractBits(val, 4, 1) << 8; 342 | uint32_t imm11 = extractBits(val, 11, 11) << 7; 343 | insn |= imm12 | imm10_5 | imm4_1 | imm11; 344 | 345 | write32le(loc, insn); 346 | return; 347 | } 348 | 349 | // auipc + jalr pair 350 | case R_RISCV_CALL: 351 | case R_RISCV_CALL_PLT: { 352 | int64_t hi = SignExtend64(val + 0x800, bits) >> 12; 353 | checkInt(loc, hi, 20, rel); 354 | if (isInt<20>(hi)) { 355 | relocateNoSym(loc, R_RISCV_PCREL_HI20, val); 356 | relocateNoSym(loc + 4, R_RISCV_PCREL_LO12_I, val); 357 | } 358 | return; 359 | } 360 | 361 | case R_RISCV_GOT_HI20: 362 | case R_RISCV_PCREL_HI20: 363 | case R_RISCV_TLS_GD_HI20: 364 | case R_RISCV_TLS_GOT_HI20: 365 | case R_RISCV_TPREL_HI20: 366 | case R_RISCV_HI20: { 367 | uint64_t hi = val + 0x800; 368 | checkInt(loc, SignExtend64(hi, bits) >> 12, 20, rel); 369 | write32le(loc, (read32le(loc) & 0xFFF) | (hi & 0xFFFFF000)); 370 | return; 371 | } 372 | 373 | case R_RISCV_PCREL_LO12_I: 374 | case R_RISCV_TPREL_LO12_I: 375 | case R_RISCV_LO12_I: { 376 | uint64_t hi = (val + 0x800) >> 12; 377 | uint64_t lo = val - (hi << 12); 378 | write32le(loc, (read32le(loc) & 0xFFFFF) | ((lo & 0xFFF) << 20)); 379 | return; 380 | } 381 | 382 | case R_RISCV_PCREL_LO12_S: 383 | case R_RISCV_TPREL_LO12_S: 384 | case R_RISCV_LO12_S: { 385 | uint64_t hi = (val + 0x800) >> 12; 386 | uint64_t lo = val - (hi << 12); 387 | uint32_t imm11_5 = extractBits(lo, 11, 5) << 25; 388 | uint32_t imm4_0 = extractBits(lo, 4, 0) << 7; 389 | write32le(loc, (read32le(loc) & 0x1FFF07F) | imm11_5 | imm4_0); 390 | return; 391 | } 392 | 393 | case R_RISCV_ADD8: 394 | *loc += val; 395 | return; 396 | case R_RISCV_ADD16: 397 | write16le(loc, read16le(loc) + val); 398 | return; 399 | case R_RISCV_ADD32: 400 | write32le(loc, read32le(loc) + val); 401 | return; 402 | case R_RISCV_ADD64: 403 | write64le(loc, read64le(loc) + val); 404 | return; 405 | case R_RISCV_SUB6: 406 | *loc = (*loc & 0xc0) | (((*loc & 0x3f) - val) & 0x3f); 407 | return; 408 | case R_RISCV_SUB8: 409 | *loc -= val; 410 | return; 411 | case R_RISCV_SUB16: 412 | write16le(loc, read16le(loc) - val); 413 | return; 414 | case R_RISCV_SUB32: 415 | write32le(loc, read32le(loc) - val); 416 | return; 417 | case R_RISCV_SUB64: 418 | write64le(loc, read64le(loc) - val); 419 | return; 420 | case R_RISCV_SET6: 421 | *loc = (*loc & 0xc0) | (val & 0x3f); 422 | return; 423 | case R_RISCV_SET8: 424 | *loc = val; 425 | return; 426 | case R_RISCV_SET16: 427 | write16le(loc, val); 428 | return; 429 | case R_RISCV_SET32: 430 | case R_RISCV_32_PCREL: 431 | write32le(loc, val); 432 | return; 433 | 434 | case R_RISCV_TLS_DTPREL32: 435 | write32le(loc, val - dtpOffset); 436 | break; 437 | case R_RISCV_TLS_DTPREL64: 438 | write64le(loc, val - dtpOffset); 439 | break; 440 | 441 | case R_RISCV_RELAX: 442 | return; // Ignored (for now) 443 | 444 | default: 445 | llvm_unreachable("unknown relocation"); 446 | } 447 | } 448 | 449 | TargetInfo *getRISCVTargetInfo() { 450 | static RISCV target; 451 | return ⌖ 452 | } 453 | 454 | } // namespace elf 455 | } // namespace lld 456 | -------------------------------------------------------------------------------- /ELF/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(LLVM_TARGET_DEFINITIONS Options.td) 2 | tablegen(LLVM Options.inc -gen-opt-parser-defs) 3 | add_public_tablegen_target(ELFOptionsTableGen) 4 | 5 | if(NOT LLD_BUILT_STANDALONE) 6 | set(tablegen_deps intrinsics_gen) 7 | endif() 8 | 9 | add_lld_library(lldELF 10 | Arch/AArch64.cpp 11 | Arch/ARM.cpp 12 | Arch/PPC.cpp 13 | Arch/PPC64.cpp 14 | Arch/RISCV.cpp 15 | Arch/X86.cpp 16 | Arch/X86_64.cpp 17 | DWARF.cpp 18 | Driver.cpp 19 | DriverUtils.cpp 20 | EhFrame.cpp 21 | ICF.cpp 22 | InputFiles.cpp 23 | InputSection.cpp 24 | LinkerScript.cpp 25 | MapFile.cpp 26 | MarkLive.cpp 27 | OutputSections.cpp 28 | Relocations.cpp 29 | ScriptLexer.cpp 30 | ScriptParser.cpp 31 | SymbolTable.cpp 32 | Symbols.cpp 33 | SyntheticSections.cpp 34 | Target.cpp 35 | Thunks.cpp 36 | Writer.cpp 37 | 38 | LINK_COMPONENTS 39 | Object 40 | Option 41 | Support 42 | 43 | LINK_LIBS 44 | lldCommon 45 | ${LLVM_PTHREAD_LIB} 46 | 47 | DEPENDS 48 | ELFOptionsTableGen 49 | ${tablegen_deps} 50 | ) 51 | -------------------------------------------------------------------------------- /ELF/Config.h: -------------------------------------------------------------------------------- 1 | //===- Config.h -------------------------------------------------*- C++ -*-===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | #ifndef LLD_ELF_CONFIG_H 10 | #define LLD_ELF_CONFIG_H 11 | 12 | #include "lld/Common/ErrorHandler.h" 13 | #include "llvm/ADT/MapVector.h" 14 | #include "llvm/ADT/StringRef.h" 15 | #include "llvm/ADT/StringSet.h" 16 | #include "llvm/BinaryFormat/ELF.h" 17 | #include "llvm/Support/CachePruning.h" 18 | #include "llvm/Support/CodeGen.h" 19 | #include "llvm/Support/Endian.h" 20 | #include 21 | #include 22 | 23 | namespace lld { 24 | namespace elf { 25 | 26 | class InputFile; 27 | class InputSectionBase; 28 | 29 | enum ELFKind { 30 | ELFNoneKind, 31 | ELF32LEKind, 32 | ELF32BEKind, 33 | ELF64LEKind, 34 | ELF64BEKind 35 | }; 36 | 37 | // For --build-id. 38 | enum class BuildIdKind { None, Fast, Md5, Sha1, Hexstring, Uuid }; 39 | 40 | // For --discard-{all,locals,none}. 41 | enum class DiscardPolicy { Default, All, Locals, None }; 42 | 43 | // For --icf={none,safe,all}. 44 | enum class ICFLevel { None, Safe, All }; 45 | 46 | // For --strip-{all,debug}. 47 | enum class StripPolicy { None, All, Debug }; 48 | 49 | // For --unresolved-symbols. 50 | enum class UnresolvedPolicy { ReportError, Warn, Ignore }; 51 | 52 | // For --orphan-handling. 53 | enum class OrphanHandlingPolicy { Place, Warn, Error }; 54 | 55 | // For --sort-section and linkerscript sorting rules. 56 | enum class SortSectionPolicy { Default, None, Alignment, Name, Priority }; 57 | 58 | // For --target2 59 | enum class Target2Policy { Abs, Rel, GotRel }; 60 | 61 | // For tracking ARM Float Argument PCS 62 | enum class ARMVFPArgKind { Default, Base, VFP, ToolChain }; 63 | 64 | // For -z noseparate-code, -z separate-code and -z separate-loadable-segments. 65 | enum class SeparateSegmentKind { None, Code, Loadable }; 66 | 67 | // For -z *stack 68 | enum class GnuStackKind { None, Exec, NoExec }; 69 | 70 | struct SymbolVersion { 71 | llvm::StringRef name; 72 | bool isExternCpp; 73 | bool hasWildcard; 74 | }; 75 | 76 | // This struct contains symbols version definition that 77 | // can be found in version script if it is used for link. 78 | struct VersionDefinition { 79 | llvm::StringRef name; 80 | uint16_t id; 81 | std::vector patterns; 82 | }; 83 | 84 | // This struct contains the global configuration for the linker. 85 | // Most fields are direct mapping from the command line options 86 | // and such fields have the same name as the corresponding options. 87 | // Most fields are initialized by the driver. 88 | struct Configuration { 89 | uint8_t osabi = 0; 90 | uint32_t andFeatures = 0; 91 | llvm::StringMap sectionStartMap; 92 | llvm::StringRef bfdname; 93 | llvm::StringRef chroot; 94 | llvm::StringRef dynamicLinker; 95 | llvm::StringRef entry; 96 | llvm::StringRef emulation; 97 | llvm::StringRef fini; 98 | llvm::StringRef init; 99 | llvm::StringRef mapFile; 100 | llvm::StringRef outputFile; 101 | llvm::StringRef progName; 102 | llvm::StringRef soName; 103 | llvm::StringRef sysroot; 104 | std::string rpath; 105 | std::vector versionDefinitions; 106 | std::vector auxiliaryList; 107 | std::vector filterList; 108 | std::vector searchPaths; 109 | std::vector symbolOrderingFile; 110 | std::vector undefined; 111 | std::vector dynamicList; 112 | std::vector buildIdVector; 113 | bool allowMultipleDefinition; 114 | bool allowShlibUndefined; 115 | bool androidPackDynRelocs; 116 | bool armHasBlx = false; 117 | bool armHasMovtMovw = false; 118 | bool armJ1J2BranchEncoding = false; 119 | bool asNeeded = false; 120 | bool bsymbolic; 121 | bool bsymbolicFunctions; 122 | bool checkSections; 123 | bool compressDebugSections; 124 | bool cref; 125 | bool defineCommon; 126 | bool demangle = true; 127 | bool dependentLibraries; 128 | bool disableVerify; 129 | bool ehFrameHdr; 130 | bool emitLLVM; 131 | bool emitRelocs; 132 | bool enableNewDtags; 133 | bool executeOnly; 134 | bool exportDynamic; 135 | bool formatBinary = false; 136 | bool gcSections; 137 | bool gnuHash = false; 138 | bool gnuUnique; 139 | bool hasDynamicList = false; 140 | bool hasDynSymTab; 141 | bool ignoreDataAddressEquality; 142 | bool ignoreFunctionAddressEquality; 143 | bool mergeArmExidx; 144 | bool mipsN32Abi = false; 145 | bool mmapOutputFile; 146 | bool nmagic; 147 | bool noDynamicLinker = false; 148 | bool noinhibitExec; 149 | bool nostdlib; 150 | bool oFormatBinary; 151 | bool omagic; 152 | bool optimizeBBJumps; 153 | bool optRemarksWithHotness; 154 | bool picThunk; 155 | bool pie; 156 | bool printGcSections; 157 | bool printIcfSections; 158 | bool relocatable; 159 | bool relrPackDynRelocs; 160 | bool saveTemps; 161 | llvm::Optional shuffleSectionSeed; 162 | bool singleRoRx; 163 | bool shared; 164 | bool isStatic = false; 165 | bool sysvHash = false; 166 | bool target1Rel; 167 | bool trace; 168 | bool tocOptimize; 169 | bool undefinedVersion; 170 | bool unique; 171 | bool useAndroidRelrTags = false; 172 | bool warnBackrefs; 173 | bool warnCommon; 174 | bool warnIfuncTextrel; 175 | bool warnMissingEntry; 176 | bool warnSymbolOrdering; 177 | bool writeAddends; 178 | bool zCombreloc; 179 | bool zCopyreloc; 180 | bool zGlobal; 181 | bool zHazardplt; 182 | bool zIfuncNoplt; 183 | bool zInitfirst; 184 | bool zInterpose; 185 | bool zKeepTextSectionPrefix; 186 | bool zNodefaultlib; 187 | bool zNodelete; 188 | bool zNodlopen; 189 | bool zNow; 190 | bool zOrigin; 191 | bool zRelro; 192 | bool zRodynamic; 193 | bool zShstk; 194 | bool zText; 195 | bool zWxneeded; 196 | DiscardPolicy discard; 197 | GnuStackKind zGnustack; 198 | ICFLevel icf; 199 | OrphanHandlingPolicy orphanHandling; 200 | SortSectionPolicy sortSection; 201 | StripPolicy strip; 202 | UnresolvedPolicy unresolvedSymbols; 203 | Target2Policy target2; 204 | ARMVFPArgKind armVFPArgs = ARMVFPArgKind::Default; 205 | BuildIdKind buildId = BuildIdKind::None; 206 | SeparateSegmentKind zSeparate; 207 | ELFKind ekind = ELFNoneKind; 208 | uint16_t emachine = llvm::ELF::EM_NONE; 209 | llvm::Optional imageBase; 210 | uint64_t commonPageSize; 211 | uint64_t maxPageSize; 212 | uint64_t mipsGotSize; 213 | uint64_t zStackSize; 214 | unsigned optimize; 215 | 216 | // The following config options do not directly correspond to any 217 | // particular command line options. 218 | 219 | // True if we need to pass through relocations in input files to the 220 | // output file. Usually false because we consume relocations. 221 | bool copyRelocs; 222 | 223 | // True if the target is ELF64. False if ELF32. 224 | bool is64; 225 | 226 | // True if the target is little-endian. False if big-endian. 227 | bool isLE; 228 | 229 | // endianness::little if isLE is true. endianness::big otherwise. 230 | llvm::support::endianness endianness; 231 | 232 | // True if the target is the little-endian MIPS64. 233 | // 234 | // The reason why we have this variable only for the MIPS is because 235 | // we use this often. Some ELF headers for MIPS64EL are in a 236 | // mixed-endian (which is horrible and I'd say that's a serious spec 237 | // bug), and we need to know whether we are reading MIPS ELF files or 238 | // not in various places. 239 | // 240 | // (Note that MIPS64EL is not a typo for MIPS64LE. This is the official 241 | // name whatever that means. A fun hypothesis is that "EL" is short for 242 | // little-endian written in the little-endian order, but I don't know 243 | // if that's true.) 244 | bool isMips64EL; 245 | 246 | // True if we need to set the DF_STATIC_TLS flag to an output file, 247 | // which works as a hint to the dynamic loader that the file contains 248 | // code compiled with the static TLS model. The thread-local variable 249 | // compiled with the static TLS model is faster but less flexible, and 250 | // it may not be loaded using dlopen(). 251 | // 252 | // We set this flag to true when we see a relocation for the static TLS 253 | // model. Once this becomes true, it will never become false. 254 | // 255 | // Since the flag is updated by multi-threaded code, we use std::atomic. 256 | // (Writing to a variable is not considered thread-safe even if the 257 | // variable is boolean and we always set the same value from all threads.) 258 | std::atomic hasStaticTlsModel{false}; 259 | 260 | // Holds set of ELF header flags for the target. 261 | uint32_t eflags = 0; 262 | 263 | // The ELF spec defines two types of relocation table entries, RELA and 264 | // REL. RELA is a triplet of (offset, info, addend) while REL is a 265 | // tuple of (offset, info). Addends for REL are implicit and read from 266 | // the location where the relocations are applied. So, REL is more 267 | // compact than RELA but requires a bit of more work to process. 268 | // 269 | // (From the linker writer's view, this distinction is not necessary. 270 | // If the ELF had chosen whichever and sticked with it, it would have 271 | // been easier to write code to process relocations, but it's too late 272 | // to change the spec.) 273 | // 274 | // Each ABI defines its relocation type. IsRela is true if target 275 | // uses RELA. As far as we know, all 64-bit ABIs are using RELA. A 276 | // few 32-bit ABIs are using RELA too. 277 | bool isRela; 278 | 279 | // True if we are creating position-independent code. 280 | bool isPic; 281 | 282 | // 4 for ELF32, 8 for ELF64. 283 | int wordsize; 284 | }; 285 | 286 | // The only instance of Configuration struct. 287 | extern Configuration *config; 288 | 289 | // The first two elements of versionDefinitions represent VER_NDX_LOCAL and 290 | // VER_NDX_GLOBAL. This helper returns other elements. 291 | static inline ArrayRef namedVersionDefs() { 292 | return llvm::makeArrayRef(config->versionDefinitions).slice(2); 293 | } 294 | 295 | static inline void errorOrWarn(const Twine &msg) { 296 | if (!config->noinhibitExec) 297 | error(msg); 298 | else 299 | warn(msg); 300 | } 301 | } // namespace elf 302 | } // namespace lld 303 | 304 | #endif 305 | -------------------------------------------------------------------------------- /ELF/DWARF.cpp: -------------------------------------------------------------------------------- 1 | //===- DWARF.cpp ----------------------------------------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // 9 | // The -gdb-index option instructs the linker to emit a .gdb_index section. 10 | // The section contains information to make gdb startup faster. 11 | // The format of the section is described at 12 | // https://sourceware.org/gdb/onlinedocs/gdb/Index-Section-Format.html. 13 | // 14 | //===----------------------------------------------------------------------===// 15 | 16 | #include "DWARF.h" 17 | #include "Symbols.h" 18 | #include "Target.h" 19 | #include "lld/Common/Memory.h" 20 | #include "llvm/DebugInfo/DWARF/DWARFDebugPubTable.h" 21 | #include "llvm/Object/ELFObjectFile.h" 22 | 23 | using namespace llvm; 24 | using namespace llvm::object; 25 | 26 | namespace lld { 27 | namespace elf { 28 | template LLDDwarfObj::LLDDwarfObj(ObjFile *obj) { 29 | for (InputSectionBase *sec : obj->getSections()) { 30 | if (!sec) 31 | continue; 32 | 33 | if (LLDDWARFSection *m = 34 | StringSwitch(sec->name) 35 | .Case(".debug_addr", &addrSection) 36 | .Case(".debug_gnu_pubnames", &gnuPubnamesSection) 37 | .Case(".debug_gnu_pubtypes", &gnuPubtypesSection) 38 | .Case(".debug_info", &infoSection) 39 | .Case(".debug_ranges", &rangesSection) 40 | .Case(".debug_rnglists", &rnglistsSection) 41 | .Case(".debug_str_offsets", &strOffsetsSection) 42 | .Case(".debug_line", &lineSection) 43 | .Default(nullptr)) { 44 | m->Data = toStringRef(sec->data()); 45 | m->sec = sec; 46 | continue; 47 | } 48 | 49 | if (sec->name == ".debug_abbrev") 50 | abbrevSection = toStringRef(sec->data()); 51 | else if (sec->name == ".debug_str") 52 | strSection = toStringRef(sec->data()); 53 | else if (sec->name == ".debug_line_str") 54 | lineStrSection = toStringRef(sec->data()); 55 | } 56 | } 57 | 58 | namespace { 59 | template struct LLDRelocationResolver { 60 | // In the ELF ABIs, S sepresents the value of the symbol in the relocation 61 | // entry. For Rela, the addend is stored as part of the relocation entry. 62 | static uint64_t resolve(object::RelocationRef ref, uint64_t s, 63 | uint64_t /* A */) { 64 | return s + ref.getRawDataRefImpl().p; 65 | } 66 | }; 67 | 68 | template struct LLDRelocationResolver> { 69 | // For Rel, the addend A is supplied by the caller. 70 | static uint64_t resolve(object::RelocationRef /*Ref*/, uint64_t s, 71 | uint64_t a) { 72 | return s + a; 73 | } 74 | }; 75 | } // namespace 76 | 77 | // Find if there is a relocation at Pos in Sec. The code is a bit 78 | // more complicated than usual because we need to pass a section index 79 | // to llvm since it has no idea about InputSection. 80 | template 81 | template 82 | Optional 83 | LLDDwarfObj::findAux(const InputSectionBase &sec, uint64_t pos, 84 | ArrayRef rels) const { 85 | auto it = 86 | partition_point(rels, [=](const RelTy &a) { return a.r_offset < pos; }); 87 | if (it == rels.end() || it->r_offset != pos) 88 | return None; 89 | const RelTy &rel = *it; 90 | 91 | const ObjFile *file = sec.getFile(); 92 | uint32_t symIndex = rel.getSymbol(config->isMips64EL); 93 | const typename ELFT::Sym &sym = file->template getELFSyms()[symIndex]; 94 | uint32_t secIndex = file->getSectionIndex(sym); 95 | 96 | // An undefined symbol may be a symbol defined in a discarded section. We 97 | // shall still resolve it. This is important for --gdb-index: the end address 98 | // offset of an entry in .debug_ranges is relocated. If it is not resolved, 99 | // its zero value will terminate the decoding of .debug_ranges prematurely. 100 | Symbol &s = file->getRelocTargetSym(rel); 101 | uint64_t val = 0; 102 | if (auto *dr = dyn_cast(&s)) 103 | val = dr->value; 104 | 105 | DataRefImpl d; 106 | d.p = getAddend(rel); 107 | return RelocAddrEntry{secIndex, RelocationRef(d, nullptr), 108 | val, Optional(), 109 | 0, LLDRelocationResolver::resolve}; 110 | } 111 | 112 | template 113 | Optional LLDDwarfObj::find(const llvm::DWARFSection &s, 114 | uint64_t pos) const { 115 | auto &sec = static_cast(s); 116 | if (sec.sec->areRelocsRela) 117 | return findAux(*sec.sec, pos, sec.sec->template relas()); 118 | return findAux(*sec.sec, pos, sec.sec->template rels()); 119 | } 120 | 121 | template class LLDDwarfObj; 122 | template class LLDDwarfObj; 123 | template class LLDDwarfObj; 124 | template class LLDDwarfObj; 125 | 126 | } // namespace elf 127 | } // namespace lld 128 | -------------------------------------------------------------------------------- /ELF/DWARF.h: -------------------------------------------------------------------------------- 1 | //===- DWARF.h -----------------------------------------------*- C++ -*-===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===-------------------------------------------------------------------===// 8 | 9 | #ifndef LLD_ELF_DWARF_H 10 | #define LLD_ELF_DWARF_H 11 | 12 | #include "InputFiles.h" 13 | #include "llvm/ADT/STLExtras.h" 14 | #include "llvm/DebugInfo/DWARF/DWARFContext.h" 15 | #include "llvm/Object/ELF.h" 16 | 17 | namespace lld { 18 | namespace elf { 19 | 20 | class InputSection; 21 | 22 | struct LLDDWARFSection final : public llvm::DWARFSection { 23 | InputSectionBase *sec = nullptr; 24 | }; 25 | 26 | template class LLDDwarfObj final : public llvm::DWARFObject { 27 | public: 28 | explicit LLDDwarfObj(ObjFile *obj); 29 | 30 | void forEachInfoSections( 31 | llvm::function_ref f) const override { 32 | f(infoSection); 33 | } 34 | 35 | const llvm::DWARFSection &getRangesSection() const override { 36 | return rangesSection; 37 | } 38 | 39 | const llvm::DWARFSection &getRnglistsSection() const override { 40 | return rnglistsSection; 41 | } 42 | 43 | const llvm::DWARFSection &getStrOffsetsSection() const override { 44 | return strOffsetsSection; 45 | } 46 | 47 | const llvm::DWARFSection &getLineSection() const override { 48 | return lineSection; 49 | } 50 | 51 | const llvm::DWARFSection &getAddrSection() const override { 52 | return addrSection; 53 | } 54 | 55 | const llvm::DWARFSection &getGnuPubnamesSection() const override { 56 | return gnuPubnamesSection; 57 | } 58 | 59 | const llvm::DWARFSection &getGnuPubtypesSection() const override { 60 | return gnuPubtypesSection; 61 | } 62 | 63 | StringRef getFileName() const override { return ""; } 64 | StringRef getAbbrevSection() const override { return abbrevSection; } 65 | StringRef getStrSection() const override { return strSection; } 66 | StringRef getLineStrSection() const override { return lineStrSection; } 67 | 68 | bool isLittleEndian() const override { 69 | return ELFT::TargetEndianness == llvm::support::little; 70 | } 71 | 72 | llvm::Optional find(const llvm::DWARFSection &sec, 73 | uint64_t pos) const override; 74 | 75 | private: 76 | template 77 | llvm::Optional findAux(const InputSectionBase &sec, 78 | uint64_t pos, 79 | ArrayRef rels) const; 80 | 81 | LLDDWARFSection gnuPubnamesSection; 82 | LLDDWARFSection gnuPubtypesSection; 83 | LLDDWARFSection infoSection; 84 | LLDDWARFSection rangesSection; 85 | LLDDWARFSection rnglistsSection; 86 | LLDDWARFSection strOffsetsSection; 87 | LLDDWARFSection lineSection; 88 | LLDDWARFSection addrSection; 89 | StringRef abbrevSection; 90 | StringRef strSection; 91 | StringRef lineStrSection; 92 | }; 93 | 94 | } // namespace elf 95 | } // namespace lld 96 | 97 | #endif 98 | -------------------------------------------------------------------------------- /ELF/Driver.h: -------------------------------------------------------------------------------- 1 | //===- Driver.h -------------------------------------------------*- C++ -*-===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | #ifndef LLD_ELF_DRIVER_H 10 | #define LLD_ELF_DRIVER_H 11 | 12 | #include "SymbolTable.h" 13 | #include "lld/Common/LLVM.h" 14 | #include "lld/Common/Reproduce.h" 15 | #include "llvm/ADT/Optional.h" 16 | #include "llvm/ADT/StringRef.h" 17 | #include "llvm/ADT/StringSet.h" 18 | #include "llvm/Option/ArgList.h" 19 | #include "llvm/Support/raw_ostream.h" 20 | 21 | namespace lld { 22 | namespace elf { 23 | 24 | extern class LinkerDriver *driver; 25 | 26 | class LinkerDriver { 27 | public: 28 | void main(ArrayRef args); 29 | void addFile(StringRef path, bool withLOption); 30 | void addLibrary(StringRef name); 31 | 32 | private: 33 | void createFiles(llvm::opt::InputArgList &args); 34 | void inferMachineType(); 35 | template void link(llvm::opt::InputArgList &args); 36 | 37 | // True if we are in --whole-archive and --no-whole-archive. 38 | bool inWholeArchive = false; 39 | 40 | // True if we are in --start-lib and --end-lib. 41 | bool inLib = false; 42 | 43 | std::vector files; 44 | }; 45 | 46 | // Parses command line options. 47 | class ELFOptTable : public llvm::opt::OptTable { 48 | public: 49 | ELFOptTable(); 50 | llvm::opt::InputArgList parse(ArrayRef argv); 51 | }; 52 | 53 | // Create enum with OPT_xxx values for each option in Options.td 54 | enum { 55 | OPT_INVALID = 0, 56 | #define OPTION(_1, _2, ID, _4, _5, _6, _7, _8, _9, _10, _11, _12) OPT_##ID, 57 | #include "Options.inc" 58 | #undef OPTION 59 | }; 60 | 61 | void printHelp(); 62 | std::string createResponseFile(const llvm::opt::InputArgList &args); 63 | 64 | llvm::Optional findFromSearchPaths(StringRef path); 65 | llvm::Optional searchScript(StringRef path); 66 | llvm::Optional searchLibraryBaseName(StringRef path); 67 | llvm::Optional searchLibrary(StringRef path); 68 | 69 | } // namespace elf 70 | } // namespace lld 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /ELF/DriverUtils.cpp: -------------------------------------------------------------------------------- 1 | //===- DriverUtils.cpp ----------------------------------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // 9 | // This file contains utility functions for the driver. Because there 10 | // are so many small functions, we created this separate file to make 11 | // Driver.cpp less cluttered. 12 | // 13 | //===----------------------------------------------------------------------===// 14 | 15 | #include "Driver.h" 16 | #include "lld/Common/ErrorHandler.h" 17 | #include "lld/Common/Memory.h" 18 | #include "lld/Common/Reproduce.h" 19 | #include "lld/Common/Version.h" 20 | #include "llvm/ADT/Optional.h" 21 | #include "llvm/ADT/STLExtras.h" 22 | #include "llvm/ADT/Triple.h" 23 | #include "llvm/Option/Option.h" 24 | #include "llvm/Support/CommandLine.h" 25 | #include "llvm/Support/FileSystem.h" 26 | #include "llvm/Support/Host.h" 27 | #include "llvm/Support/Path.h" 28 | #include "llvm/Support/Process.h" 29 | 30 | using namespace llvm; 31 | using namespace llvm::sys; 32 | using namespace llvm::opt; 33 | 34 | namespace lld { 35 | namespace elf { 36 | 37 | // Create OptTable 38 | 39 | // Create prefix string literals used in Options.td 40 | #define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE; 41 | #include "Options.inc" 42 | #undef PREFIX 43 | 44 | // Create table mapping all options defined in Options.td 45 | static const opt::OptTable::Info optInfo[] = { 46 | #define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X7, X8, X9, X10, X11, X12) \ 47 | {X1, X2, X10, X11, OPT_##ID, opt::Option::KIND##Class, \ 48 | X9, X8, OPT_##GROUP, OPT_##ALIAS, X7, X12}, 49 | #include "Options.inc" 50 | #undef OPTION 51 | }; 52 | 53 | ELFOptTable::ELFOptTable() : OptTable(optInfo) {} 54 | 55 | // Set color diagnostics according to -color-diagnostics={auto,always,never} 56 | // or -no-color-diagnostics flags. 57 | static void handleColorDiagnostics(opt::InputArgList &args) { 58 | auto *arg = args.getLastArg(OPT_color_diagnostics, OPT_color_diagnostics_eq, 59 | OPT_no_color_diagnostics); 60 | if (!arg) 61 | return; 62 | if (arg->getOption().getID() == OPT_color_diagnostics) { 63 | lld::errs().enable_colors(true); 64 | } else if (arg->getOption().getID() == OPT_no_color_diagnostics) { 65 | lld::errs().enable_colors(false); 66 | } else { 67 | StringRef s = arg->getValue(); 68 | if (s == "always") 69 | lld::errs().enable_colors(true); 70 | else if (s == "never") 71 | lld::errs().enable_colors(false); 72 | else if (s != "auto") 73 | error("unknown option: --color-diagnostics=" + s); 74 | } 75 | } 76 | 77 | static cl::TokenizerCallback getQuotingStyle(opt::InputArgList &args) { 78 | if (auto *arg = args.getLastArg(OPT_rsp_quoting)) { 79 | StringRef s = arg->getValue(); 80 | if (s != "windows" && s != "posix") 81 | error("invalid response file quoting: " + s); 82 | if (s == "windows") 83 | return cl::TokenizeWindowsCommandLine; 84 | return cl::TokenizeGNUCommandLine; 85 | } 86 | if (Triple(sys::getProcessTriple()).isOSWindows()) 87 | return cl::TokenizeWindowsCommandLine; 88 | return cl::TokenizeGNUCommandLine; 89 | } 90 | 91 | // Gold LTO plugin takes a `--plugin-opt foo=bar` option as an alias for 92 | // `--plugin-opt=foo=bar`. We want to handle `--plugin-opt=foo=` as an 93 | // option name and `bar` as a value. Unfortunately, OptParser cannot 94 | // handle an option with a space in it. 95 | // 96 | // In this function, we concatenate command line arguments so that 97 | // `--plugin-opt ` is converted to `--plugin-opt=`. This is a 98 | // bit hacky, but looks like it is still better than handling --plugin-opt 99 | // options by hand. 100 | static void concatLTOPluginOptions(SmallVectorImpl &args) { 101 | SmallVector v; 102 | for (size_t i = 0, e = args.size(); i != e; ++i) { 103 | StringRef s = args[i]; 104 | if ((s == "-plugin-opt" || s == "--plugin-opt") && i + 1 != e) { 105 | v.push_back(saver.save(s + "=" + args[i + 1]).data()); 106 | ++i; 107 | } else { 108 | v.push_back(args[i]); 109 | } 110 | } 111 | args = std::move(v); 112 | } 113 | 114 | // Parses a given list of options. 115 | opt::InputArgList ELFOptTable::parse(ArrayRef argv) { 116 | // Make InputArgList from string vectors. 117 | unsigned missingIndex; 118 | unsigned missingCount; 119 | SmallVector vec(argv.data(), argv.data() + argv.size()); 120 | 121 | // We need to get the quoting style for response files before parsing all 122 | // options so we parse here before and ignore all the options but 123 | // --rsp-quoting. 124 | opt::InputArgList args = this->ParseArgs(vec, missingIndex, missingCount); 125 | 126 | // Expand response files (arguments in the form of @) 127 | // and then parse the argument again. 128 | cl::ExpandResponseFiles(saver, getQuotingStyle(args), vec); 129 | concatLTOPluginOptions(vec); 130 | args = this->ParseArgs(vec, missingIndex, missingCount); 131 | 132 | handleColorDiagnostics(args); 133 | if (missingCount) 134 | error(Twine(args.getArgString(missingIndex)) + ": missing argument"); 135 | 136 | for (auto *arg : args.filtered(OPT_UNKNOWN)) { 137 | std::string nearest; 138 | if (findNearest(arg->getAsString(args), nearest) > 1) 139 | error("unknown argument '" + arg->getAsString(args) + "'"); 140 | else 141 | error("unknown argument '" + arg->getAsString(args) + 142 | "', did you mean '" + nearest + "'"); 143 | } 144 | return args; 145 | } 146 | 147 | void printHelp() { 148 | ELFOptTable().PrintHelp( 149 | lld::outs(), (config->progName + " [options] file...").str().c_str(), 150 | "lld", false /*ShowHidden*/, true /*ShowAllAliases*/); 151 | lld::outs() << "\n"; 152 | 153 | // Scripts generated by Libtool versions up to at least 2.4.6 (the most 154 | // recent version as of March 2017) expect /: supported targets:.* elf/ 155 | // in a message for the -help option. If it doesn't match, the scripts 156 | // assume that the linker doesn't support very basic features such as 157 | // shared libraries. Therefore, we need to print out at least "elf". 158 | lld::outs() << config->progName << ": supported targets: elf\n"; 159 | } 160 | 161 | static std::string rewritePath(StringRef s) { 162 | if (fs::exists(s)) 163 | return relativeToRoot(s); 164 | return std::string(s); 165 | } 166 | 167 | // Reconstructs command line arguments so that so that you can re-run 168 | // the same command with the same inputs. This is for --reproduce. 169 | std::string createResponseFile(const opt::InputArgList &args) { 170 | SmallString<0> data; 171 | raw_svector_ostream os(data); 172 | os << "--chroot .\n"; 173 | 174 | // Copy the command line to the output while rewriting paths. 175 | for (auto *arg : args) { 176 | switch (arg->getOption().getID()) { 177 | case OPT_reproduce: 178 | break; 179 | case OPT_INPUT: 180 | os << quote(rewritePath(arg->getValue())) << "\n"; 181 | break; 182 | case OPT_o: 183 | // If -o path contains directories, "lld @response.txt" will likely 184 | // fail because the archive we are creating doesn't contain empty 185 | // directories for the output path (-o doesn't create directories). 186 | // Strip directories to prevent the issue. 187 | os << "-o " << quote(sys::path::filename(arg->getValue())) << "\n"; 188 | break; 189 | case OPT_dynamic_list: 190 | case OPT_library_path: 191 | case OPT_rpath: 192 | case OPT_script: 193 | case OPT_symbol_ordering_file: 194 | case OPT_sysroot: 195 | case OPT_version_script: 196 | os << arg->getSpelling() << " " << quote(rewritePath(arg->getValue())) 197 | << "\n"; 198 | break; 199 | default: 200 | os << toString(*arg) << "\n"; 201 | } 202 | } 203 | return std::string(data.str()); 204 | } 205 | 206 | // Find a file by concatenating given paths. If a resulting path 207 | // starts with "=", the character is replaced with a --sysroot value. 208 | static Optional findFile(StringRef path1, const Twine &path2) { 209 | SmallString<128> s; 210 | if (path1.startswith("=")) 211 | path::append(s, config->sysroot, path1.substr(1), path2); 212 | else 213 | path::append(s, path1, path2); 214 | 215 | if (fs::exists(s)) 216 | return std::string(s); 217 | return None; 218 | } 219 | 220 | Optional findFromSearchPaths(StringRef path) { 221 | for (StringRef dir : config->searchPaths) 222 | if (Optional s = findFile(dir, path)) 223 | return s; 224 | return None; 225 | } 226 | 227 | // This is for -l. We'll look for lib.so or lib.a from 228 | // search paths. 229 | Optional searchLibraryBaseName(StringRef name) { 230 | for (StringRef dir : config->searchPaths) { 231 | if (!config->isStatic) 232 | if (Optional s = findFile(dir, "lib" + name + ".so")) 233 | return s; 234 | if (Optional s = findFile(dir, "lib" + name + ".a")) 235 | return s; 236 | } 237 | return None; 238 | } 239 | 240 | // This is for -l. 241 | Optional searchLibrary(StringRef name) { 242 | if (name.startswith(":")) 243 | return findFromSearchPaths(name.substr(1)); 244 | return searchLibraryBaseName(name); 245 | } 246 | 247 | // If a linker/version script doesn't exist in the current directory, we also 248 | // look for the script in the '-L' search paths. This matches the behaviour of 249 | // '-T', --version-script=, and linker script INPUT() command in ld.bfd. 250 | Optional searchScript(StringRef name) { 251 | if (fs::exists(name)) 252 | return name.str(); 253 | return findFromSearchPaths(name); 254 | } 255 | 256 | } // namespace elf 257 | } // namespace lld 258 | -------------------------------------------------------------------------------- /ELF/EhFrame.cpp: -------------------------------------------------------------------------------- 1 | //===- EhFrame.cpp -------------------------------------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // 9 | // .eh_frame section contains information on how to unwind the stack when 10 | // an exception is thrown. The section consists of sequence of CIE and FDE 11 | // records. The linker needs to merge CIEs and associate FDEs to CIEs. 12 | // That means the linker has to understand the format of the section. 13 | // 14 | // This file contains a few utility functions to read .eh_frame contents. 15 | // 16 | //===----------------------------------------------------------------------===// 17 | 18 | #include "EhFrame.h" 19 | #include "Config.h" 20 | #include "InputSection.h" 21 | #include "Relocations.h" 22 | #include "Target.h" 23 | #include "lld/Common/ErrorHandler.h" 24 | #include "lld/Common/Strings.h" 25 | #include "llvm/BinaryFormat/Dwarf.h" 26 | #include "llvm/Object/ELF.h" 27 | 28 | using namespace llvm; 29 | using namespace llvm::ELF; 30 | using namespace llvm::dwarf; 31 | using namespace llvm::object; 32 | 33 | namespace lld { 34 | namespace elf { 35 | namespace { 36 | class EhReader { 37 | public: 38 | EhReader(InputSectionBase *s, ArrayRef d) : isec(s), d(d) {} 39 | size_t readEhRecordSize(); 40 | uint8_t getFdeEncoding(); 41 | 42 | private: 43 | template void failOn(const P *loc, const Twine &msg) { 44 | fatal("corrupted .eh_frame: " + msg + "\n>>> defined in " + 45 | isec->getObjMsg((const uint8_t *)loc - isec->data().data())); 46 | } 47 | 48 | uint8_t readByte(); 49 | void skipBytes(size_t count); 50 | StringRef readString(); 51 | void skipLeb128(); 52 | void skipAugP(); 53 | 54 | InputSectionBase *isec; 55 | ArrayRef d; 56 | }; 57 | } 58 | 59 | size_t readEhRecordSize(InputSectionBase *s, size_t off) { 60 | return EhReader(s, s->data().slice(off)).readEhRecordSize(); 61 | } 62 | 63 | // .eh_frame section is a sequence of records. Each record starts with 64 | // a 4 byte length field. This function reads the length. 65 | size_t EhReader::readEhRecordSize() { 66 | if (d.size() < 4) 67 | failOn(d.data(), "CIE/FDE too small"); 68 | 69 | // First 4 bytes of CIE/FDE is the size of the record. 70 | // If it is 0xFFFFFFFF, the next 8 bytes contain the size instead, 71 | // but we do not support that format yet. 72 | uint64_t v = read32(d.data()); 73 | if (v == UINT32_MAX) 74 | failOn(d.data(), "CIE/FDE too large"); 75 | uint64_t size = v + 4; 76 | if (size > d.size()) 77 | failOn(d.data(), "CIE/FDE ends past the end of the section"); 78 | return size; 79 | } 80 | 81 | // Read a byte and advance D by one byte. 82 | uint8_t EhReader::readByte() { 83 | if (d.empty()) 84 | failOn(d.data(), "unexpected end of CIE"); 85 | uint8_t b = d.front(); 86 | d = d.slice(1); 87 | return b; 88 | } 89 | 90 | void EhReader::skipBytes(size_t count) { 91 | if (d.size() < count) 92 | failOn(d.data(), "CIE is too small"); 93 | d = d.slice(count); 94 | } 95 | 96 | // Read a null-terminated string. 97 | StringRef EhReader::readString() { 98 | const uint8_t *end = llvm::find(d, '\0'); 99 | if (end == d.end()) 100 | failOn(d.data(), "corrupted CIE (failed to read string)"); 101 | StringRef s = toStringRef(d.slice(0, end - d.begin())); 102 | d = d.slice(s.size() + 1); 103 | return s; 104 | } 105 | 106 | // Skip an integer encoded in the LEB128 format. 107 | // Actual number is not of interest because only the runtime needs it. 108 | // But we need to be at least able to skip it so that we can read 109 | // the field that follows a LEB128 number. 110 | void EhReader::skipLeb128() { 111 | const uint8_t *errPos = d.data(); 112 | while (!d.empty()) { 113 | uint8_t val = d.front(); 114 | d = d.slice(1); 115 | if ((val & 0x80) == 0) 116 | return; 117 | } 118 | failOn(errPos, "corrupted CIE (failed to read LEB128)"); 119 | } 120 | 121 | static size_t getAugPSize(unsigned enc) { 122 | switch (enc & 0x0f) { 123 | case DW_EH_PE_absptr: 124 | case DW_EH_PE_signed: 125 | return config->wordsize; 126 | case DW_EH_PE_udata2: 127 | case DW_EH_PE_sdata2: 128 | return 2; 129 | case DW_EH_PE_udata4: 130 | case DW_EH_PE_sdata4: 131 | return 4; 132 | case DW_EH_PE_udata8: 133 | case DW_EH_PE_sdata8: 134 | return 8; 135 | } 136 | return 0; 137 | } 138 | 139 | void EhReader::skipAugP() { 140 | uint8_t enc = readByte(); 141 | if ((enc & 0xf0) == DW_EH_PE_aligned) 142 | failOn(d.data() - 1, "DW_EH_PE_aligned encoding is not supported"); 143 | size_t size = getAugPSize(enc); 144 | if (size == 0) 145 | failOn(d.data() - 1, "unknown FDE encoding"); 146 | if (size >= d.size()) 147 | failOn(d.data() - 1, "corrupted CIE"); 148 | d = d.slice(size); 149 | } 150 | 151 | uint8_t getFdeEncoding(EhSectionPiece *p) { 152 | return EhReader(p->sec, p->data()).getFdeEncoding(); 153 | } 154 | 155 | uint8_t EhReader::getFdeEncoding() { 156 | skipBytes(8); 157 | int version = readByte(); 158 | if (version != 1 && version != 3) 159 | failOn(d.data() - 1, 160 | "FDE version 1 or 3 expected, but got " + Twine(version)); 161 | 162 | StringRef aug = readString(); 163 | 164 | // Skip code and data alignment factors. 165 | skipLeb128(); 166 | skipLeb128(); 167 | 168 | // Skip the return address register. In CIE version 1 this is a single 169 | // byte. In CIE version 3 this is an unsigned LEB128. 170 | if (version == 1) 171 | readByte(); 172 | else 173 | skipLeb128(); 174 | 175 | // We only care about an 'R' value, but other records may precede an 'R' 176 | // record. Unfortunately records are not in TLV (type-length-value) format, 177 | // so we need to teach the linker how to skip records for each type. 178 | for (char c : aug) { 179 | if (c == 'R') 180 | return readByte(); 181 | if (c == 'z') { 182 | skipLeb128(); 183 | continue; 184 | } 185 | if (c == 'P') { 186 | skipAugP(); 187 | continue; 188 | } 189 | if (c == 'L') { 190 | readByte(); 191 | continue; 192 | } 193 | failOn(aug.data(), "unknown .eh_frame augmentation string: " + aug); 194 | } 195 | return DW_EH_PE_absptr; 196 | } 197 | 198 | } // namespace elf 199 | } // namespace lld 200 | -------------------------------------------------------------------------------- /ELF/EhFrame.h: -------------------------------------------------------------------------------- 1 | //===- EhFrame.h ------------------------------------------------*- C++ -*-===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | #ifndef LLD_ELF_EHFRAME_H 10 | #define LLD_ELF_EHFRAME_H 11 | 12 | #include "lld/Common/LLVM.h" 13 | 14 | namespace lld { 15 | namespace elf { 16 | class InputSectionBase; 17 | struct EhSectionPiece; 18 | 19 | size_t readEhRecordSize(InputSectionBase *s, size_t off); 20 | uint8_t getFdeEncoding(EhSectionPiece *p); 21 | } // namespace elf 22 | } // namespace lld 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /ELF/ICF.h: -------------------------------------------------------------------------------- 1 | //===- ICF.h --------------------------------------------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | #ifndef LLD_ELF_ICF_H 10 | #define LLD_ELF_ICF_H 11 | 12 | namespace lld { 13 | namespace elf { 14 | 15 | template void doIcf(); 16 | 17 | } // namespace elf 18 | } // namespace lld 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /ELF/InputFiles.h: -------------------------------------------------------------------------------- 1 | //===- InputFiles.h ---------------------------------------------*- C++ -*-===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | #ifndef LLD_ELF_INPUT_FILES_H 10 | #define LLD_ELF_INPUT_FILES_H 11 | 12 | #include "Config.h" 13 | #include "lld/Common/ErrorHandler.h" 14 | #include "lld/Common/LLVM.h" 15 | #include "lld/Common/Reproduce.h" 16 | #include "llvm/ADT/CachedHashString.h" 17 | #include "llvm/ADT/DenseSet.h" 18 | #include "llvm/ADT/STLExtras.h" 19 | #include "llvm/IR/Comdat.h" 20 | #include "llvm/Object/Archive.h" 21 | #include "llvm/Object/ELF.h" 22 | #include "llvm/Object/IRObjectFile.h" 23 | #include "llvm/Support/Threading.h" 24 | #include 25 | 26 | namespace llvm { 27 | struct DILineInfo; 28 | class TarWriter; 29 | } // namespace llvm 30 | 31 | namespace lld { 32 | class DWARFCache; 33 | 34 | // Returns "", "foo.a(bar.o)" or "baz.o". 35 | std::string toString(const elf::InputFile *f); 36 | 37 | namespace elf { 38 | class InputFile; 39 | class InputSectionBase; 40 | 41 | using llvm::object::Archive; 42 | 43 | class Symbol; 44 | 45 | // If -reproduce option is given, all input files are written 46 | // to this tar archive. 47 | extern std::unique_ptr tar; 48 | 49 | // Opens a given file. 50 | llvm::Optional readFile(StringRef path); 51 | 52 | // Add symbols in File to the symbol table. 53 | void parseFile(InputFile *file); 54 | 55 | // The root class of input files. 56 | class InputFile { 57 | public: 58 | enum Kind { 59 | ObjKind, 60 | SharedKind, 61 | LazyObjKind, 62 | ArchiveKind, 63 | BinaryKind, 64 | }; 65 | 66 | Kind kind() const { return fileKind; } 67 | 68 | bool isElf() const { 69 | Kind k = kind(); 70 | return k == ObjKind || k == SharedKind; 71 | } 72 | 73 | StringRef getName() const { return mb.getBufferIdentifier(); } 74 | MemoryBufferRef mb; 75 | 76 | // Returns sections. It is a runtime error to call this function 77 | // on files that don't have the notion of sections. 78 | ArrayRef getSections() const { 79 | assert(fileKind == ObjKind || fileKind == BinaryKind); 80 | return sections; 81 | } 82 | 83 | // Returns object file symbols. It is a runtime error to call this 84 | // function on files of other types. 85 | ArrayRef getSymbols() { return getMutableSymbols(); } 86 | 87 | MutableArrayRef getMutableSymbols() { 88 | assert(fileKind == BinaryKind || fileKind == ObjKind); 89 | return symbols; 90 | } 91 | 92 | // Filename of .a which contained this file. If this file was 93 | // not in an archive file, it is the empty string. We use this 94 | // string for creating error messages. 95 | std::string archiveName; 96 | 97 | // If this is an architecture-specific file, the following members 98 | // have ELF type (i.e. ELF{32,64}{LE,BE}) and target machine type. 99 | ELFKind ekind = ELFNoneKind; 100 | uint16_t emachine = llvm::ELF::EM_NONE; 101 | uint8_t osabi = 0; 102 | uint8_t abiVersion = 0; 103 | 104 | // Cache for toString(). Only toString() should use this member. 105 | mutable std::string toStringCache; 106 | 107 | std::string getSrcMsg(const Symbol &sym, InputSectionBase &sec, 108 | uint64_t offset); 109 | 110 | // True if this is an argument for --just-symbols. Usually false. 111 | bool justSymbols = false; 112 | 113 | // outSecOff of .got2 in the current file. This is used by PPC32 -fPIC/-fPIE 114 | // to compute offsets in PLT call stubs. 115 | uint32_t ppc32Got2OutSecOff = 0; 116 | 117 | // On PPC64 we need to keep track of which files contain small code model 118 | // relocations that access the .toc section. To minimize the chance of a 119 | // relocation overflow, files that do contain said relocations should have 120 | // their .toc sections sorted closer to the .got section than files that do 121 | // not contain any small code model relocations. Thats because the toc-pointer 122 | // is defined to point at .got + 0x8000 and the instructions used with small 123 | // code model relocations support immediates in the range [-0x8000, 0x7FFC], 124 | // making the addressable range relative to the toc pointer 125 | // [.got, .got + 0xFFFC]. 126 | bool ppc64SmallCodeModelTocRelocs = false; 127 | 128 | // groupId is used for --warn-backrefs which is an optional error 129 | // checking feature. All files within the same --{start,end}-group or 130 | // --{start,end}-lib get the same group ID. Otherwise, each file gets a new 131 | // group ID. For more info, see checkDependency() in SymbolTable.cpp. 132 | uint32_t groupId; 133 | static bool isInGroup; 134 | static uint32_t nextGroupId; 135 | 136 | // Index of MIPS GOT built for this file. 137 | llvm::Optional mipsGotIndex; 138 | 139 | std::vector symbols; 140 | 141 | protected: 142 | InputFile(Kind k, MemoryBufferRef m); 143 | std::vector sections; 144 | 145 | private: 146 | const Kind fileKind; 147 | }; 148 | 149 | class ELFFileBase : public InputFile { 150 | public: 151 | ELFFileBase(Kind k, MemoryBufferRef m); 152 | static bool classof(const InputFile *f) { return f->isElf(); } 153 | 154 | template llvm::object::ELFFile getObj() const { 155 | return check(llvm::object::ELFFile::create(mb.getBuffer())); 156 | } 157 | 158 | StringRef getStringTable() const { return stringTable; } 159 | 160 | template typename ELFT::SymRange getELFSyms() const { 161 | return typename ELFT::SymRange( 162 | reinterpret_cast(elfSyms), numELFSyms); 163 | } 164 | template typename ELFT::SymRange getGlobalELFSyms() const { 165 | return getELFSyms().slice(firstGlobal); 166 | } 167 | 168 | protected: 169 | // Initializes this class's member variables. 170 | template void init(); 171 | 172 | const void *elfSyms = nullptr; 173 | size_t numELFSyms = 0; 174 | uint32_t firstGlobal = 0; 175 | StringRef stringTable; 176 | }; 177 | 178 | // .o file. 179 | template class ObjFile : public ELFFileBase { 180 | using Elf_Rel = typename ELFT::Rel; 181 | using Elf_Rela = typename ELFT::Rela; 182 | using Elf_Sym = typename ELFT::Sym; 183 | using Elf_Shdr = typename ELFT::Shdr; 184 | using Elf_Word = typename ELFT::Word; 185 | 186 | public: 187 | static bool classof(const InputFile *f) { return f->kind() == ObjKind; } 188 | 189 | llvm::object::ELFFile getObj() const { 190 | return this->ELFFileBase::getObj(); 191 | } 192 | 193 | ArrayRef getLocalSymbols(); 194 | ArrayRef getGlobalSymbols(); 195 | 196 | ObjFile(MemoryBufferRef m, StringRef archiveName) : ELFFileBase(ObjKind, m) { 197 | this->archiveName = std::string(archiveName); 198 | } 199 | 200 | void parse(bool ignoreComdats = false); 201 | 202 | StringRef getShtGroupSignature(ArrayRef sections, 203 | const Elf_Shdr &sec); 204 | 205 | Symbol &getSymbol(uint32_t symbolIndex) const { 206 | if (symbolIndex >= this->symbols.size()) 207 | fatal(toString(this) + ": invalid symbol index"); 208 | return *this->symbols[symbolIndex]; 209 | } 210 | 211 | uint32_t getSectionIndex(const Elf_Sym &sym) const; 212 | 213 | template Symbol &getRelocTargetSym(const RelT &rel) const { 214 | uint32_t symIndex = rel.getSymbol(config->isMips64EL); 215 | return getSymbol(symIndex); 216 | } 217 | 218 | // Name of source file obtained from STT_FILE symbol value, 219 | // or empty string if there is no such symbol in object file 220 | // symbol table. 221 | StringRef sourceFile; 222 | 223 | // Pointer to this input file's .llvm_addrsig section, if it has one. 224 | const Elf_Shdr *addrsigSec = nullptr; 225 | 226 | // Get cached DWARF information. 227 | DWARFCache *getDwarf(); 228 | 229 | private: 230 | void initializeSections(bool ignoreComdats); 231 | void initializeSymbols(); 232 | void initializeJustSymbols(); 233 | 234 | InputSectionBase *getRelocTarget(const Elf_Shdr &sec); 235 | InputSectionBase *createInputSection(const Elf_Shdr &sec); 236 | StringRef getSectionName(const Elf_Shdr &sec); 237 | 238 | bool shouldMerge(const Elf_Shdr &sec, StringRef name); 239 | 240 | // Each ELF symbol contains a section index which the symbol belongs to. 241 | // However, because the number of bits dedicated for that is limited, a 242 | // symbol can directly point to a section only when the section index is 243 | // equal to or smaller than 65280. 244 | // 245 | // If an object file contains more than 65280 sections, the file must 246 | // contain .symtab_shndx section. The section contains an array of 247 | // 32-bit integers whose size is the same as the number of symbols. 248 | // Nth symbol's section index is in the Nth entry of .symtab_shndx. 249 | // 250 | // The following variable contains the contents of .symtab_shndx. 251 | // If the section does not exist (which is common), the array is empty. 252 | ArrayRef shndxTable; 253 | 254 | // .shstrtab contents. 255 | StringRef sectionStringTable; 256 | 257 | // Debugging information to retrieve source file and line for error 258 | // reporting. Linker may find reasonable number of errors in a 259 | // single object file, so we cache debugging information in order to 260 | // parse it only once for each object file we link. 261 | std::unique_ptr dwarf; 262 | llvm::once_flag initDwarf; 263 | }; 264 | 265 | // LazyObjFile is analogous to ArchiveFile in the sense that 266 | // the file contains lazy symbols. The difference is that 267 | // LazyObjFile wraps a single file instead of multiple files. 268 | // 269 | // This class is used for --start-lib and --end-lib options which 270 | // instruct the linker to link object files between them with the 271 | // archive file semantics. 272 | class LazyObjFile : public InputFile { 273 | public: 274 | LazyObjFile(MemoryBufferRef m, StringRef archiveName, 275 | uint64_t offsetInArchive) 276 | : InputFile(LazyObjKind, m), offsetInArchive(offsetInArchive) { 277 | this->archiveName = std::string(archiveName); 278 | } 279 | 280 | static bool classof(const InputFile *f) { return f->kind() == LazyObjKind; } 281 | 282 | template void parse(); 283 | void fetch(); 284 | 285 | private: 286 | uint64_t offsetInArchive; 287 | }; 288 | 289 | // An ArchiveFile object represents a .a file. 290 | class ArchiveFile : public InputFile { 291 | public: 292 | explicit ArchiveFile(std::unique_ptr &&file); 293 | static bool classof(const InputFile *f) { return f->kind() == ArchiveKind; } 294 | void parse(); 295 | 296 | // Pulls out an object file that contains a definition for Sym and 297 | // returns it. If the same file was instantiated before, this 298 | // function does nothing (so we don't instantiate the same file 299 | // more than once.) 300 | void fetch(const Archive::Symbol &sym); 301 | 302 | private: 303 | std::unique_ptr file; 304 | llvm::DenseSet seen; 305 | }; 306 | 307 | // .so file. 308 | class SharedFile : public ELFFileBase { 309 | public: 310 | SharedFile(MemoryBufferRef m, StringRef defaultSoName) 311 | : ELFFileBase(SharedKind, m), soName(std::string(defaultSoName)), 312 | isNeeded(!config->asNeeded) {} 313 | 314 | // This is actually a vector of Elf_Verdef pointers. 315 | std::vector verdefs; 316 | 317 | // If the output file needs Elf_Verneed data structures for this file, this is 318 | // a vector of Elf_Vernaux version identifiers that map onto the entries in 319 | // Verdefs, otherwise it is empty. 320 | std::vector vernauxs; 321 | 322 | static unsigned vernauxNum; 323 | 324 | std::vector dtNeeded; 325 | std::string soName; 326 | 327 | static bool classof(const InputFile *f) { return f->kind() == SharedKind; } 328 | 329 | template void parse(); 330 | 331 | // Used for --no-allow-shlib-undefined. 332 | bool allNeededIsKnown; 333 | 334 | // Used for --as-needed 335 | bool isNeeded; 336 | }; 337 | 338 | class BinaryFile : public InputFile { 339 | public: 340 | explicit BinaryFile(MemoryBufferRef m) : InputFile(BinaryKind, m) {} 341 | static bool classof(const InputFile *f) { return f->kind() == BinaryKind; } 342 | void parse(); 343 | }; 344 | 345 | InputFile *createObjectFile(MemoryBufferRef mb, StringRef archiveName = "", 346 | uint64_t offsetInArchive = 0); 347 | 348 | extern std::vector binaryFiles; 349 | extern std::vector lazyObjFiles; 350 | extern std::vector objectFiles; 351 | extern std::vector sharedFiles; 352 | 353 | } // namespace elf 354 | } // namespace lld 355 | 356 | #endif 357 | -------------------------------------------------------------------------------- /ELF/LinkerScript.h: -------------------------------------------------------------------------------- 1 | //===- LinkerScript.h -------------------------------------------*- C++ -*-===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | #ifndef LLD_ELF_LINKER_SCRIPT_H 10 | #define LLD_ELF_LINKER_SCRIPT_H 11 | 12 | #include "Config.h" 13 | #include "Writer.h" 14 | #include "lld/Common/LLVM.h" 15 | #include "lld/Common/Strings.h" 16 | #include "llvm/ADT/ArrayRef.h" 17 | #include "llvm/ADT/DenseMap.h" 18 | #include "llvm/ADT/DenseSet.h" 19 | #include "llvm/ADT/MapVector.h" 20 | #include "llvm/ADT/StringRef.h" 21 | #include "llvm/Support/MemoryBuffer.h" 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | namespace lld { 29 | namespace elf { 30 | 31 | class Defined; 32 | class InputSection; 33 | class InputSectionBase; 34 | class OutputSection; 35 | class SectionBase; 36 | class Symbol; 37 | class ThunkSection; 38 | 39 | // This represents an r-value in the linker script. 40 | struct ExprValue { 41 | ExprValue(SectionBase *sec, bool forceAbsolute, uint64_t val, 42 | const Twine &loc) 43 | : sec(sec), forceAbsolute(forceAbsolute), val(val), loc(loc.str()) {} 44 | 45 | ExprValue(uint64_t val) : ExprValue(nullptr, false, val, "") {} 46 | 47 | bool isAbsolute() const { return forceAbsolute || sec == nullptr; } 48 | uint64_t getValue() const; 49 | uint64_t getSecAddr() const; 50 | uint64_t getSectionOffset() const; 51 | 52 | // If a value is relative to a section, it has a non-null Sec. 53 | SectionBase *sec; 54 | 55 | // True if this expression is enclosed in ABSOLUTE(). 56 | // This flag affects the return value of getValue(). 57 | bool forceAbsolute; 58 | 59 | uint64_t val; 60 | uint64_t alignment = 1; 61 | 62 | // Original source location. Used for error messages. 63 | std::string loc; 64 | }; 65 | 66 | // This represents an expression in the linker script. 67 | // ScriptParser::readExpr reads an expression and returns an Expr. 68 | // Later, we evaluate the expression by calling the function. 69 | using Expr = std::function; 70 | 71 | // This enum is used to implement linker script SECTIONS command. 72 | // https://sourceware.org/binutils/docs/ld/SECTIONS.html#SECTIONS 73 | enum SectionsCommandKind { 74 | AssignmentKind, // . = expr or = expr 75 | OutputSectionKind, 76 | InputSectionKind, 77 | ByteKind // BYTE(expr), SHORT(expr), LONG(expr) or QUAD(expr) 78 | }; 79 | 80 | struct BaseCommand { 81 | BaseCommand(int k) : kind(k) {} 82 | int kind; 83 | }; 84 | 85 | // This represents ". = " or " = ". 86 | struct SymbolAssignment : BaseCommand { 87 | SymbolAssignment(StringRef name, Expr e, std::string loc) 88 | : BaseCommand(AssignmentKind), name(name), expression(e), location(loc) {} 89 | 90 | static bool classof(const BaseCommand *c) { 91 | return c->kind == AssignmentKind; 92 | } 93 | 94 | // The LHS of an expression. Name is either a symbol name or ".". 95 | StringRef name; 96 | Defined *sym = nullptr; 97 | 98 | // The RHS of an expression. 99 | Expr expression; 100 | 101 | // Command attributes for PROVIDE, HIDDEN and PROVIDE_HIDDEN. 102 | bool provide = false; 103 | bool hidden = false; 104 | 105 | // Holds file name and line number for error reporting. 106 | std::string location; 107 | 108 | // A string representation of this command. We use this for -Map. 109 | std::string commandString; 110 | 111 | // Address of this assignment command. 112 | uint64_t addr; 113 | 114 | // Size of this assignment command. This is usually 0, but if 115 | // you move '.' this may be greater than 0. 116 | uint64_t size; 117 | }; 118 | 119 | // Linker scripts allow additional constraints to be put on output sections. 120 | // If an output section is marked as ONLY_IF_RO, the section is created 121 | // only if its input sections are read-only. Likewise, an output section 122 | // with ONLY_IF_RW is created if all input sections are RW. 123 | enum class ConstraintKind { NoConstraint, ReadOnly, ReadWrite }; 124 | 125 | // This struct is used to represent the location and size of regions of 126 | // target memory. Instances of the struct are created by parsing the 127 | // MEMORY command. 128 | struct MemoryRegion { 129 | MemoryRegion(StringRef name, Expr origin, Expr length, uint32_t flags, 130 | uint32_t negFlags) 131 | : name(std::string(name)), origin(origin), length(length), flags(flags), 132 | negFlags(negFlags) {} 133 | 134 | std::string name; 135 | Expr origin; 136 | Expr length; 137 | uint32_t flags; 138 | uint32_t negFlags; 139 | uint64_t curPos = 0; 140 | }; 141 | 142 | // This struct represents one section match pattern in SECTIONS() command. 143 | // It can optionally have negative match pattern for EXCLUDED_FILE command. 144 | // Also it may be surrounded with SORT() command, so contains sorting rules. 145 | struct SectionPattern { 146 | SectionPattern(StringMatcher &&pat1, StringMatcher &&pat2) 147 | : excludedFilePat(pat1), sectionPat(pat2), 148 | sortOuter(SortSectionPolicy::Default), 149 | sortInner(SortSectionPolicy::Default) {} 150 | 151 | StringMatcher excludedFilePat; 152 | StringMatcher sectionPat; 153 | SortSectionPolicy sortOuter; 154 | SortSectionPolicy sortInner; 155 | }; 156 | 157 | struct InputSectionDescription : BaseCommand { 158 | InputSectionDescription(StringRef filePattern, uint64_t withFlags = 0, 159 | uint64_t withoutFlags = 0) 160 | : BaseCommand(InputSectionKind), filePat(filePattern), 161 | withFlags(withFlags), withoutFlags(withoutFlags) {} 162 | 163 | static bool classof(const BaseCommand *c) { 164 | return c->kind == InputSectionKind; 165 | } 166 | 167 | SingleStringMatcher filePat; 168 | 169 | // Input sections that matches at least one of SectionPatterns 170 | // will be associated with this InputSectionDescription. 171 | std::vector sectionPatterns; 172 | 173 | // Includes InputSections and MergeInputSections. Used temporarily during 174 | // assignment of input sections to output sections. 175 | std::vector sectionBases; 176 | 177 | // Used after the finalizeInputSections() pass. MergeInputSections have been 178 | // merged into MergeSyntheticSections. 179 | std::vector sections; 180 | 181 | // Temporary record of synthetic ThunkSection instances and the pass that 182 | // they were created in. This is used to insert newly created ThunkSections 183 | // into Sections at the end of a createThunks() pass. 184 | std::vector> thunkSections; 185 | 186 | // SectionPatterns can be filtered with the INPUT_SECTION_FLAGS command. 187 | uint64_t withFlags; 188 | uint64_t withoutFlags; 189 | }; 190 | 191 | // Represents BYTE(), SHORT(), LONG(), or QUAD(). 192 | struct ByteCommand : BaseCommand { 193 | ByteCommand(Expr e, unsigned size, std::string commandString) 194 | : BaseCommand(ByteKind), commandString(commandString), expression(e), 195 | size(size) {} 196 | 197 | static bool classof(const BaseCommand *c) { return c->kind == ByteKind; } 198 | 199 | // Keeps string representing the command. Used for -Map" is perhaps better. 200 | std::string commandString; 201 | 202 | Expr expression; 203 | 204 | // This is just an offset of this assignment command in the output section. 205 | unsigned offset; 206 | 207 | // Size of this data command. 208 | unsigned size; 209 | }; 210 | 211 | struct InsertCommand { 212 | OutputSection *os; 213 | bool isAfter; 214 | StringRef where; 215 | }; 216 | 217 | struct PhdrsCommand { 218 | StringRef name; 219 | unsigned type = llvm::ELF::PT_NULL; 220 | bool hasFilehdr = false; 221 | bool hasPhdrs = false; 222 | llvm::Optional flags; 223 | Expr lmaExpr = nullptr; 224 | }; 225 | 226 | class LinkerScript final { 227 | // Temporary state used in processSectionCommands() and assignAddresses() 228 | // that must be reinitialized for each call to the above functions, and must 229 | // not be used outside of the scope of a call to the above functions. 230 | struct AddressState { 231 | AddressState(); 232 | uint64_t threadBssOffset = 0; 233 | OutputSection *outSec = nullptr; 234 | MemoryRegion *memRegion = nullptr; 235 | MemoryRegion *lmaRegion = nullptr; 236 | uint64_t lmaOffset = 0; 237 | }; 238 | 239 | llvm::DenseMap nameToOutputSection; 240 | 241 | void addSymbol(SymbolAssignment *cmd); 242 | void assignSymbol(SymbolAssignment *cmd, bool inSec); 243 | void setDot(Expr e, const Twine &loc, bool inSec); 244 | void expandOutputSection(uint64_t size); 245 | void expandMemoryRegions(uint64_t size); 246 | 247 | std::vector 248 | computeInputSections(const InputSectionDescription *); 249 | 250 | std::vector createInputSectionList(OutputSection &cmd); 251 | 252 | std::vector getPhdrIndices(OutputSection *sec); 253 | 254 | MemoryRegion *findMemoryRegion(OutputSection *sec); 255 | 256 | void switchTo(OutputSection *sec); 257 | uint64_t advance(uint64_t size, unsigned align); 258 | void output(InputSection *sec); 259 | 260 | void assignOffsets(OutputSection *sec); 261 | 262 | // Ctx captures the local AddressState and makes it accessible 263 | // deliberately. This is needed as there are some cases where we cannot just 264 | // thread the current state through to a lambda function created by the 265 | // script parser. 266 | // This should remain a plain pointer as its lifetime is smaller than 267 | // LinkerScript. 268 | AddressState *ctx = nullptr; 269 | 270 | OutputSection *aether; 271 | 272 | uint64_t dot; 273 | 274 | public: 275 | OutputSection *createOutputSection(StringRef name, StringRef location); 276 | OutputSection *getOrCreateOutputSection(StringRef name); 277 | 278 | bool hasPhdrsCommands() { return !phdrsCommands.empty(); } 279 | uint64_t getDot() { return dot; } 280 | void discard(InputSectionBase *s); 281 | 282 | ExprValue getSymbolValue(StringRef name, const Twine &loc); 283 | 284 | void addOrphanSections(); 285 | void diagnoseOrphanHandling() const; 286 | void adjustSectionsBeforeSorting(); 287 | void adjustSectionsAfterSorting(); 288 | 289 | std::vector createPhdrs(); 290 | bool needsInterpSection(); 291 | 292 | bool shouldKeep(InputSectionBase *s); 293 | const Defined *assignAddresses(); 294 | void allocateHeaders(std::vector &phdrs); 295 | void processSectionCommands(); 296 | void processSymbolAssignments(); 297 | void declareSymbols(); 298 | 299 | // Used to handle INSERT AFTER statements. 300 | void processInsertCommands(); 301 | 302 | // SECTIONS command list. 303 | std::vector sectionCommands; 304 | 305 | // PHDRS command list. 306 | std::vector phdrsCommands; 307 | 308 | bool hasSectionsCommand = false; 309 | bool errorOnMissingSection = false; 310 | 311 | // List of section patterns specified with KEEP commands. They will 312 | // be kept even if they are unused and --gc-sections is specified. 313 | std::vector keptSections; 314 | 315 | // A map from memory region name to a memory region descriptor. 316 | llvm::MapVector memoryRegions; 317 | 318 | // A list of symbols referenced by the script. 319 | std::vector referencedSymbols; 320 | 321 | // Used to implement INSERT [AFTER|BEFORE]. Contains output sections that need 322 | // to be reordered. 323 | std::vector insertCommands; 324 | 325 | // Sections that will be warned/errored by --orphan-handling. 326 | std::vector orphanSections; 327 | }; 328 | 329 | extern LinkerScript *script; 330 | 331 | } // end namespace elf 332 | } // end namespace lld 333 | 334 | #endif // LLD_ELF_LINKER_SCRIPT_H 335 | -------------------------------------------------------------------------------- /ELF/MapFile.cpp: -------------------------------------------------------------------------------- 1 | //===- MapFile.cpp --------------------------------------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // 9 | // This file implements the -Map option. It shows lists in order and 10 | // hierarchically the output sections, input sections, input files and 11 | // symbol: 12 | // 13 | // Address Size Align Out In Symbol 14 | // 00201000 00000015 4 .text 15 | // 00201000 0000000e 4 test.o:(.text) 16 | // 0020100e 00000000 0 local 17 | // 00201005 00000000 0 f(int) 18 | // 19 | //===----------------------------------------------------------------------===// 20 | 21 | #include "MapFile.h" 22 | #include "InputFiles.h" 23 | #include "LinkerScript.h" 24 | #include "OutputSections.h" 25 | #include "SymbolTable.h" 26 | #include "Symbols.h" 27 | #include "SyntheticSections.h" 28 | #include "lld/Common/Strings.h" 29 | #include "lld/Common/Threads.h" 30 | #include "llvm/ADT/MapVector.h" 31 | #include "llvm/ADT/SetVector.h" 32 | #include "llvm/Support/raw_ostream.h" 33 | 34 | using namespace llvm; 35 | using namespace llvm::object; 36 | 37 | namespace lld { 38 | namespace elf { 39 | using SymbolMapTy = DenseMap>; 40 | 41 | static constexpr char indent8[] = " "; // 8 spaces 42 | static constexpr char indent16[] = " "; // 16 spaces 43 | 44 | // Print out the first three columns of a line. 45 | static void writeHeader(raw_ostream &os, uint64_t vma, uint64_t lma, 46 | uint64_t size, uint64_t align) { 47 | if (config->is64) 48 | os << format("%16llx %16llx %8llx %5lld ", vma, lma, size, align); 49 | else 50 | os << format("%8llx %8llx %8llx %5lld ", vma, lma, size, align); 51 | } 52 | 53 | // Returns a list of all symbols that we want to print out. 54 | static std::vector getSymbols() { 55 | std::vector v; 56 | for (InputFile *file : objectFiles) 57 | for (Symbol *b : file->getSymbols()) 58 | if (auto *dr = dyn_cast(b)) 59 | if (!dr->isSection() && dr->section && dr->section->isLive() && 60 | (dr->file == file || dr->needsPltAddr || dr->section->bss)) 61 | v.push_back(dr); 62 | return v; 63 | } 64 | 65 | // Returns a map from sections to their symbols. 66 | static SymbolMapTy getSectionSyms(ArrayRef syms) { 67 | SymbolMapTy ret; 68 | for (Defined *dr : syms) 69 | ret[dr->section].push_back(dr); 70 | 71 | // Sort symbols by address. We want to print out symbols in the 72 | // order in the output file rather than the order they appeared 73 | // in the input files. 74 | for (auto &it : ret) 75 | llvm::stable_sort(it.second, [](Defined *a, Defined *b) { 76 | return a->getVA() < b->getVA(); 77 | }); 78 | return ret; 79 | } 80 | 81 | // Construct a map from symbols to their stringified representations. 82 | // Demangling symbols (which is what toString() does) is slow, so 83 | // we do that in batch using parallel-for. 84 | static DenseMap 85 | getSymbolStrings(ArrayRef syms) { 86 | std::vector str(syms.size()); 87 | parallelForEachN(0, syms.size(), [&](size_t i) { 88 | raw_string_ostream os(str[i]); 89 | OutputSection *osec = syms[i]->getOutputSection(); 90 | uint64_t vma = syms[i]->getVA(); 91 | uint64_t lma = osec ? osec->getLMA() + vma - osec->getVA(0) : 0; 92 | writeHeader(os, vma, lma, syms[i]->getSize(), 1); 93 | os << indent16 << toString(*syms[i]); 94 | }); 95 | 96 | DenseMap ret; 97 | for (size_t i = 0, e = syms.size(); i < e; ++i) 98 | ret[syms[i]] = std::move(str[i]); 99 | return ret; 100 | } 101 | 102 | // Print .eh_frame contents. Since the section consists of EhSectionPieces, 103 | // we need a specialized printer for that section. 104 | // 105 | // .eh_frame tend to contain a lot of section pieces that are contiguous 106 | // both in input file and output file. Such pieces are squashed before 107 | // being displayed to make output compact. 108 | static void printEhFrame(raw_ostream &os, const EhFrameSection *sec) { 109 | std::vector pieces; 110 | 111 | auto add = [&](const EhSectionPiece &p) { 112 | // If P is adjacent to Last, squash the two. 113 | if (!pieces.empty()) { 114 | EhSectionPiece &last = pieces.back(); 115 | if (last.sec == p.sec && last.inputOff + last.size == p.inputOff && 116 | last.outputOff + last.size == p.outputOff) { 117 | last.size += p.size; 118 | return; 119 | } 120 | } 121 | pieces.push_back(p); 122 | }; 123 | 124 | // Gather section pieces. 125 | for (const CieRecord *rec : sec->getCieRecords()) { 126 | add(*rec->cie); 127 | for (const EhSectionPiece *fde : rec->fdes) 128 | add(*fde); 129 | } 130 | 131 | // Print out section pieces. 132 | const OutputSection *osec = sec->getOutputSection(); 133 | for (EhSectionPiece &p : pieces) { 134 | writeHeader(os, osec->addr + p.outputOff, osec->getLMA() + p.outputOff, 135 | p.size, 1); 136 | os << indent8 << toString(p.sec->file) << ":(" << p.sec->name << "+0x" 137 | << Twine::utohexstr(p.inputOff) + ")\n"; 138 | } 139 | } 140 | 141 | void writeMapFile() { 142 | if (config->mapFile.empty()) 143 | return; 144 | 145 | // Open a map file for writing. 146 | std::error_code ec; 147 | raw_fd_ostream os(config->mapFile, ec, sys::fs::OF_None); 148 | if (ec) { 149 | error("cannot open " + config->mapFile + ": " + ec.message()); 150 | return; 151 | } 152 | 153 | // Collect symbol info that we want to print out. 154 | std::vector syms = getSymbols(); 155 | SymbolMapTy sectionSyms = getSectionSyms(syms); 156 | DenseMap symStr = getSymbolStrings(syms); 157 | 158 | // Print out the header line. 159 | int w = config->is64 ? 16 : 8; 160 | os << right_justify("VMA", w) << ' ' << right_justify("LMA", w) 161 | << " Size Align Out In Symbol\n"; 162 | 163 | OutputSection* osec = nullptr; 164 | for (BaseCommand *base : script->sectionCommands) { 165 | if (auto *cmd = dyn_cast(base)) { 166 | if (cmd->provide && !cmd->sym) 167 | continue; 168 | uint64_t lma = osec ? osec->getLMA() + cmd->addr - osec->getVA(0) : 0; 169 | writeHeader(os, cmd->addr, lma, cmd->size, 1); 170 | os << cmd->commandString << '\n'; 171 | continue; 172 | } 173 | 174 | osec = cast(base); 175 | writeHeader(os, osec->addr, osec->getLMA(), osec->size, osec->alignment); 176 | os << osec->name << '\n'; 177 | 178 | // Dump symbols for each input section. 179 | for (BaseCommand *base : osec->sectionCommands) { 180 | if (auto *isd = dyn_cast(base)) { 181 | for (InputSection *isec : isd->sections) { 182 | if (auto *ehSec = dyn_cast(isec)) { 183 | printEhFrame(os, ehSec); 184 | continue; 185 | } 186 | 187 | writeHeader(os, isec->getVA(0), osec->getLMA() + isec->getOffset(0), 188 | isec->getSize(), isec->alignment); 189 | os << indent8 << toString(isec) << '\n'; 190 | for (Symbol *sym : sectionSyms[isec]) 191 | os << symStr[sym] << '\n'; 192 | } 193 | continue; 194 | } 195 | 196 | if (auto *cmd = dyn_cast(base)) { 197 | writeHeader(os, osec->addr + cmd->offset, osec->getLMA() + cmd->offset, 198 | cmd->size, 1); 199 | os << indent8 << cmd->commandString << '\n'; 200 | continue; 201 | } 202 | 203 | if (auto *cmd = dyn_cast(base)) { 204 | if (cmd->provide && !cmd->sym) 205 | continue; 206 | writeHeader(os, cmd->addr, osec->getLMA() + cmd->addr - osec->getVA(0), 207 | cmd->size, 1); 208 | os << indent8 << cmd->commandString << '\n'; 209 | continue; 210 | } 211 | } 212 | } 213 | } 214 | 215 | static void print(StringRef a, StringRef b) { 216 | lld::outs() << left_justify(a, 49) << " " << b << "\n"; 217 | } 218 | 219 | // Output a cross reference table to stdout. This is for --cref. 220 | // 221 | // For each global symbol, we print out a file that defines the symbol 222 | // followed by files that uses that symbol. Here is an example. 223 | // 224 | // strlen /lib/x86_64-linux-gnu/libc.so.6 225 | // tools/lld/tools/lld/CMakeFiles/lld.dir/lld.cpp.o 226 | // lib/libLLVMSupport.a(PrettyStackTrace.cpp.o) 227 | // 228 | // In this case, strlen is defined by libc.so.6 and used by other two 229 | // files. 230 | void writeCrossReferenceTable() { 231 | if (!config->cref) 232 | return; 233 | 234 | // Collect symbols and files. 235 | MapVector> map; 236 | for (InputFile *file : objectFiles) { 237 | for (Symbol *sym : file->getSymbols()) { 238 | if (isa(sym)) 239 | map[sym].insert(file); 240 | if (auto *d = dyn_cast(sym)) 241 | if (!d->isLocal() && (!d->section || d->section->isLive())) 242 | map[d].insert(file); 243 | } 244 | } 245 | 246 | // Print out a header. 247 | lld::outs() << "Cross Reference Table\n\n"; 248 | print("Symbol", "File"); 249 | 250 | // Print out a table. 251 | for (auto kv : map) { 252 | Symbol *sym = kv.first; 253 | SetVector &files = kv.second; 254 | 255 | print(toString(*sym), toString(sym->file)); 256 | for (InputFile *file : files) 257 | if (file != sym->file) 258 | print("", toString(file)); 259 | } 260 | } 261 | 262 | } // namespace elf 263 | } // namespace lld 264 | -------------------------------------------------------------------------------- /ELF/MapFile.h: -------------------------------------------------------------------------------- 1 | //===- MapFile.h ------------------------------------------------*- C++ -*-===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | #ifndef LLD_ELF_MAPFILE_H 10 | #define LLD_ELF_MAPFILE_H 11 | 12 | namespace lld { 13 | namespace elf { 14 | void writeMapFile(); 15 | void writeCrossReferenceTable(); 16 | } // namespace elf 17 | } // namespace lld 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /ELF/MarkLive.h: -------------------------------------------------------------------------------- 1 | //===- MarkLive.h -----------------------------------------------*- C++ -*-===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | #ifndef LLD_ELF_MARKLIVE_H 10 | #define LLD_ELF_MARKLIVE_H 11 | 12 | namespace lld { 13 | namespace elf { 14 | 15 | template void markLive(); 16 | 17 | } // namespace elf 18 | } // namespace lld 19 | 20 | #endif // LLD_ELF_MARKLIVE_H 21 | -------------------------------------------------------------------------------- /ELF/OutputSections.h: -------------------------------------------------------------------------------- 1 | //===- OutputSections.h -----------------------------------------*- C++ -*-===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | #ifndef LLD_ELF_OUTPUT_SECTIONS_H 10 | #define LLD_ELF_OUTPUT_SECTIONS_H 11 | 12 | #include "Config.h" 13 | #include "InputSection.h" 14 | #include "LinkerScript.h" 15 | #include "Relocations.h" 16 | #include "lld/Common/LLVM.h" 17 | #include "llvm/MC/StringTableBuilder.h" 18 | #include "llvm/Object/ELF.h" 19 | #include 20 | 21 | namespace lld { 22 | namespace elf { 23 | 24 | struct PhdrEntry; 25 | class InputSection; 26 | class InputSectionBase; 27 | 28 | // This represents a section in an output file. 29 | // It is composed of multiple InputSections. 30 | // The writer creates multiple OutputSections and assign them unique, 31 | // non-overlapping file offsets and VAs. 32 | class OutputSection final : public BaseCommand, public SectionBase { 33 | public: 34 | OutputSection(StringRef name, uint32_t type, uint64_t flags); 35 | 36 | static bool classof(const SectionBase *s) { 37 | return s->kind() == SectionBase::Output; 38 | } 39 | 40 | static bool classof(const BaseCommand *c); 41 | 42 | uint64_t getLMA() const { return ptLoad ? addr + ptLoad->lmaOffset : addr; } 43 | template void writeHeaderTo(typename ELFT::Shdr *sHdr); 44 | 45 | uint32_t sectionIndex = UINT32_MAX; 46 | unsigned sortRank; 47 | 48 | uint32_t getPhdrFlags() const; 49 | 50 | // Pointer to the PT_LOAD segment, which this section resides in. This field 51 | // is used to correctly compute file offset of a section. When two sections 52 | // share the same load segment, difference between their file offsets should 53 | // be equal to difference between their virtual addresses. To compute some 54 | // section offset we use the following formula: Off = Off_first + VA - 55 | // VA_first, where Off_first and VA_first is file offset and VA of first 56 | // section in PT_LOAD. 57 | PhdrEntry *ptLoad = nullptr; 58 | 59 | // Pointer to a relocation section for this section. Usually nullptr because 60 | // we consume relocations, but if --emit-relocs is specified (which is rare), 61 | // it may have a non-null value. 62 | OutputSection *relocationSection = nullptr; 63 | 64 | // Initially this field is the number of InputSections that have been added to 65 | // the OutputSection so far. Later on, after a call to assignAddresses, it 66 | // corresponds to the Elf_Shdr member. 67 | uint64_t size = 0; 68 | 69 | // The following fields correspond to Elf_Shdr members. 70 | uint64_t offset = 0; 71 | uint64_t addr = 0; 72 | uint32_t shName = 0; 73 | 74 | void recordSection(InputSectionBase *isec); 75 | void commitSection(InputSection *isec); 76 | void finalizeInputSections(); 77 | 78 | // The following members are normally only used in linker scripts. 79 | MemoryRegion *memRegion = nullptr; 80 | MemoryRegion *lmaRegion = nullptr; 81 | Expr addrExpr; 82 | Expr alignExpr; 83 | Expr lmaExpr; 84 | Expr subalignExpr; 85 | std::vector sectionCommands; 86 | std::vector phdrs; 87 | llvm::Optional> filler; 88 | ConstraintKind constraint = ConstraintKind::NoConstraint; 89 | std::string location; 90 | std::string memoryRegionName; 91 | std::string lmaRegionName; 92 | bool nonAlloc = false; 93 | bool noload = false; 94 | bool expressionsUseSymbols = false; 95 | bool usedInExpression = false; 96 | bool inOverlay = false; 97 | 98 | // Tracks whether the section has ever had an input section added to it, even 99 | // if the section was later removed (e.g. because it is a synthetic section 100 | // that wasn't needed). This is needed for orphan placement. 101 | bool hasInputSections = false; 102 | 103 | void finalize(); 104 | template void writeTo(uint8_t *buf); 105 | template void maybeCompress(); 106 | 107 | void sort(llvm::function_ref order); 108 | void sortInitFini(); 109 | void sortCtorsDtors(); 110 | 111 | private: 112 | // Used for implementation of --compress-debug-sections option. 113 | std::vector zDebugHeader; 114 | llvm::SmallVector compressedData; 115 | 116 | std::array getFiller(); 117 | }; 118 | 119 | int getPriority(StringRef s); 120 | 121 | InputSection *getFirstInputSection(const OutputSection *os); 122 | std::vector getInputSections(const OutputSection *os); 123 | 124 | // All output sections that are handled by the linker specially are 125 | // globally accessible. Writer initializes them, so don't use them 126 | // until Writer is initialized. 127 | struct Out { 128 | static uint8_t *bufferStart; 129 | static uint8_t first; 130 | static PhdrEntry *tlsPhdr; 131 | static OutputSection *elfHeader; 132 | static OutputSection *programHeaders; 133 | static OutputSection *preinitArray; 134 | static OutputSection *initArray; 135 | static OutputSection *finiArray; 136 | }; 137 | 138 | } // namespace elf 139 | } // namespace lld 140 | 141 | namespace lld { 142 | namespace elf { 143 | 144 | uint64_t getHeaderSize(); 145 | 146 | extern std::vector outputSections; 147 | } // namespace elf 148 | } // namespace lld 149 | 150 | #endif 151 | -------------------------------------------------------------------------------- /ELF/README.md: -------------------------------------------------------------------------------- 1 | See docs/NewLLD.rst 2 | -------------------------------------------------------------------------------- /ELF/Relocations.h: -------------------------------------------------------------------------------- 1 | //===- Relocations.h -------------------------------------------*- C++ -*-===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | #ifndef LLD_ELF_RELOCATIONS_H 10 | #define LLD_ELF_RELOCATIONS_H 11 | 12 | #include "lld/Common/LLVM.h" 13 | #include "llvm/ADT/DenseMap.h" 14 | #include 15 | #include 16 | 17 | namespace lld { 18 | namespace elf { 19 | class Symbol; 20 | class InputSection; 21 | class InputSectionBase; 22 | class OutputSection; 23 | class SectionBase; 24 | 25 | // Represents a relocation type, such as R_X86_64_PC32 or R_ARM_THM_CALL. 26 | using RelType = uint32_t; 27 | using JumpModType = uint32_t; 28 | 29 | // List of target-independent relocation types. Relocations read 30 | // from files are converted to these types so that the main code 31 | // doesn't have to know about architecture-specific details. 32 | enum RelExpr { 33 | R_ABS, 34 | R_ADDEND, 35 | R_DTPREL, 36 | R_GOT, 37 | R_GOT_OFF, 38 | R_GOT_PC, 39 | R_GOTONLY_PC, 40 | R_GOTPLTONLY_PC, 41 | R_GOTPLT, 42 | R_GOTPLTREL, 43 | R_GOTREL, 44 | R_NEG_TLS, 45 | R_NONE, 46 | R_PC, 47 | R_PLT, 48 | R_PLT_PC, 49 | R_RELAX_GOT_PC, 50 | R_RELAX_GOT_PC_NOPIC, 51 | R_RELAX_TLS_GD_TO_IE, 52 | R_RELAX_TLS_GD_TO_IE_ABS, 53 | R_RELAX_TLS_GD_TO_IE_GOT_OFF, 54 | R_RELAX_TLS_GD_TO_IE_GOTPLT, 55 | R_RELAX_TLS_GD_TO_LE, 56 | R_RELAX_TLS_GD_TO_LE_NEG, 57 | R_RELAX_TLS_IE_TO_LE, 58 | R_RELAX_TLS_LD_TO_LE, 59 | R_RELAX_TLS_LD_TO_LE_ABS, 60 | R_SIZE, 61 | R_TLS, 62 | R_TLSDESC, 63 | R_TLSDESC_CALL, 64 | R_TLSDESC_PC, 65 | R_TLSGD_GOT, 66 | R_TLSGD_GOTPLT, 67 | R_TLSGD_PC, 68 | R_TLSIE_HINT, 69 | R_TLSLD_GOT, 70 | R_TLSLD_GOTPLT, 71 | R_TLSLD_GOT_OFF, 72 | R_TLSLD_HINT, 73 | R_TLSLD_PC, 74 | 75 | // The following is abstract relocation types used for only one target. 76 | // 77 | // Even though RelExpr is intended to be a target-neutral representation 78 | // of a relocation type, there are some relocations whose semantics are 79 | // unique to a target. Such relocation are marked with R_. 80 | R_AARCH64_GOT_PAGE_PC, 81 | R_AARCH64_PAGE_PC, 82 | R_AARCH64_RELAX_TLS_GD_TO_IE_PAGE_PC, 83 | R_AARCH64_TLSDESC_PAGE, 84 | R_ARM_PCA, 85 | R_ARM_SBREL, 86 | R_PPC32_PLTREL, 87 | R_PPC64_CALL, 88 | R_PPC64_CALL_PLT, 89 | R_PPC64_RELAX_TOC, 90 | R_PPC64_TOCBASE, 91 | R_RISCV_ADD, 92 | R_RISCV_PC_INDIRECT, 93 | }; 94 | 95 | // Architecture-neutral representation of relocation. 96 | struct Relocation { 97 | RelExpr expr; 98 | RelType type; 99 | uint64_t offset; 100 | int64_t addend; 101 | Symbol *sym; 102 | }; 103 | 104 | // Manipulate jump instructions with these modifiers. These are used to relax 105 | // jump instruction opcodes at basic block boundaries and are particularly 106 | // useful when basic block sections are enabled. 107 | struct JumpInstrMod { 108 | JumpModType original; 109 | uint64_t offset; 110 | unsigned size; 111 | }; 112 | 113 | // This function writes undefined symbol diagnostics to an internal buffer. 114 | // Call reportUndefinedSymbols() after calling scanRelocations() to emit 115 | // the diagnostics. 116 | template void scanRelocations(InputSectionBase &); 117 | 118 | template void reportUndefinedSymbols(); 119 | 120 | void hexagonTLSSymbolUpdate(ArrayRef outputSections); 121 | bool hexagonNeedsTLSSymbol(ArrayRef outputSections); 122 | 123 | class ThunkSection; 124 | class Thunk; 125 | struct InputSectionDescription; 126 | 127 | class ThunkCreator { 128 | public: 129 | // Return true if Thunks have been added to OutputSections 130 | bool createThunks(ArrayRef outputSections); 131 | 132 | // The number of completed passes of createThunks this permits us 133 | // to do one time initialization on Pass 0 and put a limit on the 134 | // number of times it can be called to prevent infinite loops. 135 | uint32_t pass = 0; 136 | 137 | private: 138 | void mergeThunks(ArrayRef outputSections); 139 | 140 | ThunkSection *getISDThunkSec(OutputSection *os, InputSection *isec, 141 | InputSectionDescription *isd, uint32_t type, 142 | uint64_t src); 143 | 144 | ThunkSection *getISThunkSec(InputSection *isec); 145 | 146 | void createInitialThunkSections(ArrayRef outputSections); 147 | 148 | std::pair getThunk(InputSection *isec, Relocation &rel, 149 | uint64_t src); 150 | 151 | ThunkSection *addThunkSection(OutputSection *os, InputSectionDescription *, 152 | uint64_t off); 153 | 154 | bool normalizeExistingThunk(Relocation &rel, uint64_t src); 155 | 156 | // Record all the available Thunks for a (Symbol, addend) pair, where Symbol 157 | // is represented as a (section, offset) pair. There may be multiple 158 | // relocations sharing the same (section, offset + addend) pair. We may revert 159 | // a relocation back to its original non-Thunk target, and restore the 160 | // original addend, so we cannot fold offset + addend. A nested pair is used 161 | // because DenseMapInfo is not specialized for std::tuple. 162 | llvm::DenseMap, int64_t>, 163 | std::vector> 164 | thunkedSymbolsBySectionAndAddend; 165 | llvm::DenseMap, std::vector> 166 | thunkedSymbols; 167 | 168 | // Find a Thunk from the Thunks symbol definition, we can use this to find 169 | // the Thunk from a relocation to the Thunks symbol definition. 170 | llvm::DenseMap thunks; 171 | 172 | // Track InputSections that have an inline ThunkSection placed in front 173 | // an inline ThunkSection may have control fall through to the section below 174 | // so we need to make sure that there is only one of them. 175 | // The Mips LA25 Thunk is an example of an inline ThunkSection. 176 | llvm::DenseMap thunkedSections; 177 | }; 178 | 179 | // Return a int64_t to make sure we get the sign extension out of the way as 180 | // early as possible. 181 | template 182 | static inline int64_t getAddend(const typename ELFT::Rel &rel) { 183 | return 0; 184 | } 185 | template 186 | static inline int64_t getAddend(const typename ELFT::Rela &rel) { 187 | return rel.r_addend; 188 | } 189 | } // namespace elf 190 | } // namespace lld 191 | 192 | #endif 193 | -------------------------------------------------------------------------------- /ELF/ScriptLexer.cpp: -------------------------------------------------------------------------------- 1 | //===- ScriptLexer.cpp ----------------------------------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // 9 | // This file defines a lexer for the linker script. 10 | // 11 | // The linker script's grammar is not complex but ambiguous due to the 12 | // lack of the formal specification of the language. What we are trying to 13 | // do in this and other files in LLD is to make a "reasonable" linker 14 | // script processor. 15 | // 16 | // Among simplicity, compatibility and efficiency, we put the most 17 | // emphasis on simplicity when we wrote this lexer. Compatibility with the 18 | // GNU linkers is important, but we did not try to clone every tiny corner 19 | // case of their lexers, as even ld.bfd and ld.gold are subtly different 20 | // in various corner cases. We do not care much about efficiency because 21 | // the time spent in parsing linker scripts is usually negligible. 22 | // 23 | // Our grammar of the linker script is LL(2), meaning that it needs at 24 | // most two-token lookahead to parse. The only place we need two-token 25 | // lookahead is labels in version scripts, where we need to parse "local :" 26 | // as if "local:". 27 | // 28 | // Overall, this lexer works fine for most linker scripts. There might 29 | // be room for improving compatibility, but that's probably not at the 30 | // top of our todo list. 31 | // 32 | //===----------------------------------------------------------------------===// 33 | 34 | #include "ScriptLexer.h" 35 | #include "lld/Common/ErrorHandler.h" 36 | #include "llvm/ADT/Twine.h" 37 | 38 | using namespace llvm; 39 | 40 | namespace lld { 41 | namespace elf { 42 | // Returns a whole line containing the current token. 43 | StringRef ScriptLexer::getLine() { 44 | StringRef s = getCurrentMB().getBuffer(); 45 | StringRef tok = tokens[pos - 1]; 46 | 47 | size_t pos = s.rfind('\n', tok.data() - s.data()); 48 | if (pos != StringRef::npos) 49 | s = s.substr(pos + 1); 50 | return s.substr(0, s.find_first_of("\r\n")); 51 | } 52 | 53 | // Returns 1-based line number of the current token. 54 | size_t ScriptLexer::getLineNumber() { 55 | StringRef s = getCurrentMB().getBuffer(); 56 | StringRef tok = tokens[pos - 1]; 57 | return s.substr(0, tok.data() - s.data()).count('\n') + 1; 58 | } 59 | 60 | // Returns 0-based column number of the current token. 61 | size_t ScriptLexer::getColumnNumber() { 62 | StringRef tok = tokens[pos - 1]; 63 | return tok.data() - getLine().data(); 64 | } 65 | 66 | std::string ScriptLexer::getCurrentLocation() { 67 | std::string filename = std::string(getCurrentMB().getBufferIdentifier()); 68 | return (filename + ":" + Twine(getLineNumber())).str(); 69 | } 70 | 71 | ScriptLexer::ScriptLexer(MemoryBufferRef mb) { tokenize(mb); } 72 | 73 | // We don't want to record cascading errors. Keep only the first one. 74 | void ScriptLexer::setError(const Twine &msg) { 75 | if (errorCount()) 76 | return; 77 | 78 | std::string s = (getCurrentLocation() + ": " + msg).str(); 79 | if (pos) 80 | s += "\n>>> " + getLine().str() + "\n>>> " + 81 | std::string(getColumnNumber(), ' ') + "^"; 82 | error(s); 83 | } 84 | 85 | // Split S into linker script tokens. 86 | void ScriptLexer::tokenize(MemoryBufferRef mb) { 87 | std::vector vec; 88 | mbs.push_back(mb); 89 | StringRef s = mb.getBuffer(); 90 | StringRef begin = s; 91 | 92 | for (;;) { 93 | s = skipSpace(s); 94 | if (s.empty()) 95 | break; 96 | 97 | // Quoted token. Note that double-quote characters are parts of a token 98 | // because, in a glob match context, only unquoted tokens are interpreted 99 | // as glob patterns. Double-quoted tokens are literal patterns in that 100 | // context. 101 | if (s.startswith("\"")) { 102 | size_t e = s.find("\"", 1); 103 | if (e == StringRef::npos) { 104 | StringRef filename = mb.getBufferIdentifier(); 105 | size_t lineno = begin.substr(0, s.data() - begin.data()).count('\n'); 106 | error(filename + ":" + Twine(lineno + 1) + ": unclosed quote"); 107 | return; 108 | } 109 | 110 | vec.push_back(s.take_front(e + 1)); 111 | s = s.substr(e + 1); 112 | continue; 113 | } 114 | 115 | // ">foo" is parsed to ">" and "foo", but ">>" is parsed to ">>". 116 | // "|", "||", "&" and "&&" are different operators. 117 | if (s.startswith("<<") || s.startswith("<=") || s.startswith(">>") || 118 | s.startswith(">=") || s.startswith("||") || s.startswith("&&")) { 119 | vec.push_back(s.substr(0, 2)); 120 | s = s.substr(2); 121 | continue; 122 | } 123 | 124 | // Unquoted token. This is more relaxed than tokens in C-like language, 125 | // so that you can write "file-name.cpp" as one bare token, for example. 126 | size_t pos = s.find_first_not_of( 127 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" 128 | "0123456789_.$/\\~=+[]*?-!^:"); 129 | 130 | // A character that cannot start a word (which is usually a 131 | // punctuation) forms a single character token. 132 | if (pos == 0) 133 | pos = 1; 134 | vec.push_back(s.substr(0, pos)); 135 | s = s.substr(pos); 136 | } 137 | 138 | tokens.insert(tokens.begin() + pos, vec.begin(), vec.end()); 139 | } 140 | 141 | // Skip leading whitespace characters or comments. 142 | StringRef ScriptLexer::skipSpace(StringRef s) { 143 | for (;;) { 144 | if (s.startswith("/*")) { 145 | size_t e = s.find("*/", 2); 146 | if (e == StringRef::npos) { 147 | error("unclosed comment in a linker script"); 148 | return ""; 149 | } 150 | s = s.substr(e + 2); 151 | continue; 152 | } 153 | if (s.startswith("#")) { 154 | size_t e = s.find('\n', 1); 155 | if (e == StringRef::npos) 156 | e = s.size() - 1; 157 | s = s.substr(e + 1); 158 | continue; 159 | } 160 | size_t size = s.size(); 161 | s = s.ltrim(); 162 | if (s.size() == size) 163 | return s; 164 | } 165 | } 166 | 167 | // An erroneous token is handled as if it were the last token before EOF. 168 | bool ScriptLexer::atEOF() { return errorCount() || tokens.size() == pos; } 169 | 170 | // Split a given string as an expression. 171 | // This function returns "3", "*" and "5" for "3*5" for example. 172 | static std::vector tokenizeExpr(StringRef s) { 173 | StringRef ops = "+-*/:!~=<>"; // List of operators 174 | 175 | // Quoted strings are literal strings, so we don't want to split it. 176 | if (s.startswith("\"")) 177 | return {s}; 178 | 179 | // Split S with operators as separators. 180 | std::vector ret; 181 | while (!s.empty()) { 182 | size_t e = s.find_first_of(ops); 183 | 184 | // No need to split if there is no operator. 185 | if (e == StringRef::npos) { 186 | ret.push_back(s); 187 | break; 188 | } 189 | 190 | // Get a token before the operator. 191 | if (e != 0) 192 | ret.push_back(s.substr(0, e)); 193 | 194 | // Get the operator as a token. 195 | // Keep !=, ==, >=, <=, << and >> operators as a single tokens. 196 | if (s.substr(e).startswith("!=") || s.substr(e).startswith("==") || 197 | s.substr(e).startswith(">=") || s.substr(e).startswith("<=") || 198 | s.substr(e).startswith("<<") || s.substr(e).startswith(">>")) { 199 | ret.push_back(s.substr(e, 2)); 200 | s = s.substr(e + 2); 201 | } else { 202 | ret.push_back(s.substr(e, 1)); 203 | s = s.substr(e + 1); 204 | } 205 | } 206 | return ret; 207 | } 208 | 209 | // In contexts where expressions are expected, the lexer should apply 210 | // different tokenization rules than the default one. By default, 211 | // arithmetic operator characters are regular characters, but in the 212 | // expression context, they should be independent tokens. 213 | // 214 | // For example, "foo*3" should be tokenized to "foo", "*" and "3" only 215 | // in the expression context. 216 | // 217 | // This function may split the current token into multiple tokens. 218 | void ScriptLexer::maybeSplitExpr() { 219 | if (!inExpr || errorCount() || atEOF()) 220 | return; 221 | 222 | std::vector v = tokenizeExpr(tokens[pos]); 223 | if (v.size() == 1) 224 | return; 225 | tokens.erase(tokens.begin() + pos); 226 | tokens.insert(tokens.begin() + pos, v.begin(), v.end()); 227 | } 228 | 229 | StringRef ScriptLexer::next() { 230 | maybeSplitExpr(); 231 | 232 | if (errorCount()) 233 | return ""; 234 | if (atEOF()) { 235 | setError("unexpected EOF"); 236 | return ""; 237 | } 238 | return tokens[pos++]; 239 | } 240 | 241 | StringRef ScriptLexer::peek() { 242 | StringRef tok = next(); 243 | if (errorCount()) 244 | return ""; 245 | pos = pos - 1; 246 | return tok; 247 | } 248 | 249 | StringRef ScriptLexer::peek2() { 250 | skip(); 251 | StringRef tok = next(); 252 | if (errorCount()) 253 | return ""; 254 | pos = pos - 2; 255 | return tok; 256 | } 257 | 258 | bool ScriptLexer::consume(StringRef tok) { 259 | if (peek() == tok) { 260 | skip(); 261 | return true; 262 | } 263 | return false; 264 | } 265 | 266 | // Consumes Tok followed by ":". Space is allowed between Tok and ":". 267 | bool ScriptLexer::consumeLabel(StringRef tok) { 268 | if (consume((tok + ":").str())) 269 | return true; 270 | if (tokens.size() >= pos + 2 && tokens[pos] == tok && 271 | tokens[pos + 1] == ":") { 272 | pos += 2; 273 | return true; 274 | } 275 | return false; 276 | } 277 | 278 | void ScriptLexer::skip() { (void)next(); } 279 | 280 | void ScriptLexer::expect(StringRef expect) { 281 | if (errorCount()) 282 | return; 283 | StringRef tok = next(); 284 | if (tok != expect) 285 | setError(expect + " expected, but got " + tok); 286 | } 287 | 288 | // Returns true if S encloses T. 289 | static bool encloses(StringRef s, StringRef t) { 290 | return s.bytes_begin() <= t.bytes_begin() && t.bytes_end() <= s.bytes_end(); 291 | } 292 | 293 | MemoryBufferRef ScriptLexer::getCurrentMB() { 294 | // Find input buffer containing the current token. 295 | assert(!mbs.empty() && pos > 0); 296 | for (MemoryBufferRef mb : mbs) 297 | if (encloses(mb.getBuffer(), tokens[pos - 1])) 298 | return mb; 299 | llvm_unreachable("getCurrentMB: failed to find a token"); 300 | } 301 | 302 | } // namespace elf 303 | } // namespace lld 304 | -------------------------------------------------------------------------------- /ELF/ScriptLexer.h: -------------------------------------------------------------------------------- 1 | //===- ScriptLexer.h --------------------------------------------*- C++ -*-===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | #ifndef LLD_ELF_SCRIPT_LEXER_H 10 | #define LLD_ELF_SCRIPT_LEXER_H 11 | 12 | #include "lld/Common/LLVM.h" 13 | #include "llvm/ADT/StringRef.h" 14 | #include "llvm/Support/MemoryBuffer.h" 15 | #include 16 | #include 17 | 18 | namespace lld { 19 | namespace elf { 20 | 21 | class ScriptLexer { 22 | public: 23 | explicit ScriptLexer(MemoryBufferRef mb); 24 | 25 | void setError(const Twine &msg); 26 | void tokenize(MemoryBufferRef mb); 27 | static StringRef skipSpace(StringRef s); 28 | bool atEOF(); 29 | StringRef next(); 30 | StringRef peek(); 31 | StringRef peek2(); 32 | void skip(); 33 | bool consume(StringRef tok); 34 | void expect(StringRef expect); 35 | bool consumeLabel(StringRef tok); 36 | std::string getCurrentLocation(); 37 | 38 | std::vector mbs; 39 | std::vector tokens; 40 | bool inExpr = false; 41 | size_t pos = 0; 42 | 43 | private: 44 | void maybeSplitExpr(); 45 | StringRef getLine(); 46 | size_t getLineNumber(); 47 | size_t getColumnNumber(); 48 | 49 | MemoryBufferRef getCurrentMB(); 50 | }; 51 | 52 | } // namespace elf 53 | } // namespace lld 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /ELF/ScriptParser.h: -------------------------------------------------------------------------------- 1 | //===- ScriptParser.h -------------------------------------------*- C++ -*-===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | #ifndef LLD_ELF_SCRIPT_PARSER_H 10 | #define LLD_ELF_SCRIPT_PARSER_H 11 | 12 | #include "lld/Common/LLVM.h" 13 | #include "llvm/Support/MemoryBuffer.h" 14 | 15 | namespace lld { 16 | namespace elf { 17 | 18 | // Parses a linker script. Calling this function updates 19 | // lld::elf::config and lld::elf::script. 20 | void readLinkerScript(MemoryBufferRef mb); 21 | 22 | // Parses a version script. 23 | void readVersionScript(MemoryBufferRef mb); 24 | 25 | void readDynamicList(MemoryBufferRef mb); 26 | 27 | // Parses the defsym expression. 28 | void readDefsym(StringRef name, MemoryBufferRef mb); 29 | 30 | } // namespace elf 31 | } // namespace lld 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /ELF/SymbolTable.cpp: -------------------------------------------------------------------------------- 1 | //===- SymbolTable.cpp ----------------------------------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // 9 | // Symbol table is a bag of all known symbols. We put all symbols of 10 | // all input files to the symbol table. The symbol table is basically 11 | // a hash table with the logic to resolve symbol name conflicts using 12 | // the symbol types. 13 | // 14 | //===----------------------------------------------------------------------===// 15 | 16 | #include "SymbolTable.h" 17 | #include "Config.h" 18 | #include "LinkerScript.h" 19 | #include "Symbols.h" 20 | #include "SyntheticSections.h" 21 | #include "lld/Common/ErrorHandler.h" 22 | #include "lld/Common/Memory.h" 23 | #include "lld/Common/Strings.h" 24 | #include "llvm/ADT/STLExtras.h" 25 | 26 | using namespace llvm; 27 | using namespace llvm::object; 28 | using namespace llvm::ELF; 29 | 30 | namespace lld { 31 | namespace elf { 32 | SymbolTable *symtab; 33 | 34 | void SymbolTable::wrap(Symbol *sym, Symbol *real, Symbol *wrap) { 35 | // Swap symbols as instructed by -wrap. 36 | int &idx1 = symMap[CachedHashStringRef(sym->getName())]; 37 | int &idx2 = symMap[CachedHashStringRef(real->getName())]; 38 | int &idx3 = symMap[CachedHashStringRef(wrap->getName())]; 39 | 40 | idx2 = idx1; 41 | idx1 = idx3; 42 | 43 | // Now renaming is complete. No one refers Real symbol. We could leave 44 | // Real as-is, but if Real is written to the symbol table, that may 45 | // contain irrelevant values. So, we copy all values from Sym to Real. 46 | StringRef s = real->getName(); 47 | memcpy(real, sym, sizeof(SymbolUnion)); 48 | real->setName(s); 49 | } 50 | 51 | // Find an existing symbol or create a new one. 52 | Symbol *SymbolTable::insert(StringRef name) { 53 | // @@ means the symbol is the default version. In that 54 | // case @@ will be used to resolve references to . 55 | // 56 | // Since this is a hot path, the following string search code is 57 | // optimized for speed. StringRef::find(char) is much faster than 58 | // StringRef::find(StringRef). 59 | size_t pos = name.find('@'); 60 | if (pos != StringRef::npos && pos + 1 < name.size() && name[pos + 1] == '@') 61 | name = name.take_front(pos); 62 | 63 | auto p = symMap.insert({CachedHashStringRef(name), (int)symVector.size()}); 64 | int &symIndex = p.first->second; 65 | bool isNew = p.second; 66 | 67 | if (!isNew) 68 | return symVector[symIndex]; 69 | 70 | Symbol *sym = reinterpret_cast(make()); 71 | symVector.push_back(sym); 72 | 73 | // *sym was not initialized by a constructor. Fields that may get referenced 74 | // when it is a placeholder must be initialized here. 75 | sym->setName(name); 76 | sym->symbolKind = Symbol::PlaceholderKind; 77 | sym->versionId = VER_NDX_GLOBAL; 78 | sym->visibility = STV_DEFAULT; 79 | sym->isUsedInRegularObj = false; 80 | sym->exportDynamic = false; 81 | sym->inDynamicList = false; 82 | sym->referenced = false; 83 | sym->traced = false; 84 | sym->scriptDefined = false; 85 | sym->partition = 1; 86 | return sym; 87 | } 88 | 89 | Symbol *SymbolTable::addSymbol(const Symbol &newSym) { 90 | Symbol *sym = symtab->insert(newSym.getName()); 91 | sym->resolve(newSym); 92 | return sym; 93 | } 94 | 95 | Symbol *SymbolTable::find(StringRef name) { 96 | auto it = symMap.find(CachedHashStringRef(name)); 97 | if (it == symMap.end()) 98 | return nullptr; 99 | Symbol *sym = symVector[it->second]; 100 | if (sym->isPlaceholder()) 101 | return nullptr; 102 | return sym; 103 | } 104 | 105 | // A version script/dynamic list is only meaningful for a Defined symbol. 106 | // A CommonSymbol will be converted to a Defined in replaceCommonSymbols(). 107 | // A lazy symbol may be made Defined if an LTO libcall fetches it. 108 | static bool canBeVersioned(const Symbol &sym) { 109 | return sym.isDefined() || sym.isCommon() || sym.isLazy(); 110 | } 111 | 112 | // Initialize demangledSyms with a map from demangled symbols to symbol 113 | // objects. Used to handle "extern C++" directive in version scripts. 114 | // 115 | // The map will contain all demangled symbols. That can be very large, 116 | // and in LLD we generally want to avoid do anything for each symbol. 117 | // Then, why are we doing this? Here's why. 118 | // 119 | // Users can use "extern C++ {}" directive to match against demangled 120 | // C++ symbols. For example, you can write a pattern such as 121 | // "llvm::*::foo(int, ?)". Obviously, there's no way to handle this 122 | // other than trying to match a pattern against all demangled symbols. 123 | // So, if "extern C++" feature is used, we need to demangle all known 124 | // symbols. 125 | StringMap> &SymbolTable::getDemangledSyms() { 126 | if (!demangledSyms) { 127 | demangledSyms.emplace(); 128 | for (Symbol *sym : symVector) 129 | if (canBeVersioned(*sym)) 130 | (*demangledSyms)[demangleItanium(sym->getName())].push_back(sym); 131 | } 132 | return *demangledSyms; 133 | } 134 | 135 | std::vector SymbolTable::findByVersion(SymbolVersion ver) { 136 | if (ver.isExternCpp) 137 | return getDemangledSyms().lookup(ver.name); 138 | if (Symbol *sym = find(ver.name)) 139 | if (canBeVersioned(*sym)) 140 | return {sym}; 141 | return {}; 142 | } 143 | 144 | std::vector SymbolTable::findAllByVersion(SymbolVersion ver) { 145 | std::vector res; 146 | SingleStringMatcher m(ver.name); 147 | 148 | if (ver.isExternCpp) { 149 | for (auto &p : getDemangledSyms()) 150 | if (m.match(p.first())) 151 | res.insert(res.end(), p.second.begin(), p.second.end()); 152 | return res; 153 | } 154 | 155 | for (Symbol *sym : symVector) 156 | if (canBeVersioned(*sym) && m.match(sym->getName())) 157 | res.push_back(sym); 158 | return res; 159 | } 160 | 161 | // Handles -dynamic-list. 162 | void SymbolTable::handleDynamicList() { 163 | for (SymbolVersion &ver : config->dynamicList) { 164 | std::vector syms; 165 | if (ver.hasWildcard) 166 | syms = findAllByVersion(ver); 167 | else 168 | syms = findByVersion(ver); 169 | 170 | for (Symbol *sym : syms) 171 | sym->inDynamicList = true; 172 | } 173 | } 174 | 175 | // Set symbol versions to symbols. This function handles patterns 176 | // containing no wildcard characters. 177 | void SymbolTable::assignExactVersion(SymbolVersion ver, uint16_t versionId, 178 | StringRef versionName) { 179 | if (ver.hasWildcard) 180 | return; 181 | 182 | // Get a list of symbols which we need to assign the version to. 183 | std::vector syms = findByVersion(ver); 184 | if (syms.empty()) { 185 | if (!config->undefinedVersion) 186 | error("version script assignment of '" + versionName + "' to symbol '" + 187 | ver.name + "' failed: symbol not defined"); 188 | return; 189 | } 190 | 191 | auto getName = [](uint16_t ver) -> std::string { 192 | if (ver == VER_NDX_LOCAL) 193 | return "VER_NDX_LOCAL"; 194 | if (ver == VER_NDX_GLOBAL) 195 | return "VER_NDX_GLOBAL"; 196 | return ("version '" + config->versionDefinitions[ver].name + "'").str(); 197 | }; 198 | 199 | // Assign the version. 200 | for (Symbol *sym : syms) { 201 | // Skip symbols containing version info because symbol versions 202 | // specified by symbol names take precedence over version scripts. 203 | // See parseSymbolVersion(). 204 | if (sym->getName().contains('@')) 205 | continue; 206 | 207 | // If the version has not been assigned, verdefIndex is -1. Use an arbitrary 208 | // number (0) to indicate the version has been assigned. 209 | if (sym->verdefIndex == UINT32_C(-1)) { 210 | sym->verdefIndex = 0; 211 | sym->versionId = versionId; 212 | } 213 | if (sym->versionId == versionId) 214 | continue; 215 | 216 | warn("attempt to reassign symbol '" + ver.name + "' of " + 217 | getName(sym->versionId) + " to " + getName(versionId)); 218 | } 219 | } 220 | 221 | void SymbolTable::assignWildcardVersion(SymbolVersion ver, uint16_t versionId) { 222 | // Exact matching takes precedence over fuzzy matching, 223 | // so we set a version to a symbol only if no version has been assigned 224 | // to the symbol. This behavior is compatible with GNU. 225 | for (Symbol *sym : findAllByVersion(ver)) 226 | if (sym->verdefIndex == UINT32_C(-1)) { 227 | sym->verdefIndex = 0; 228 | sym->versionId = versionId; 229 | } 230 | } 231 | 232 | // This function processes version scripts by updating the versionId 233 | // member of symbols. 234 | // If there's only one anonymous version definition in a version 235 | // script file, the script does not actually define any symbol version, 236 | // but just specifies symbols visibilities. 237 | void SymbolTable::scanVersionScript() { 238 | // First, we assign versions to exact matching symbols, 239 | // i.e. version definitions not containing any glob meta-characters. 240 | for (VersionDefinition &v : config->versionDefinitions) 241 | for (SymbolVersion &pat : v.patterns) 242 | assignExactVersion(pat, v.id, v.name); 243 | 244 | // Next, assign versions to wildcards that are not "*". Note that because the 245 | // last match takes precedence over previous matches, we iterate over the 246 | // definitions in the reverse order. 247 | for (VersionDefinition &v : llvm::reverse(config->versionDefinitions)) 248 | for (SymbolVersion &pat : v.patterns) 249 | if (pat.hasWildcard && pat.name != "*") 250 | assignWildcardVersion(pat, v.id); 251 | 252 | // Then, assign versions to "*". In GNU linkers they have lower priority than 253 | // other wildcards. 254 | for (VersionDefinition &v : config->versionDefinitions) 255 | for (SymbolVersion &pat : v.patterns) 256 | if (pat.hasWildcard && pat.name == "*") 257 | assignWildcardVersion(pat, v.id); 258 | 259 | // Symbol themselves might know their versions because symbols 260 | // can contain versions in the form of @. 261 | // Let them parse and update their names to exclude version suffix. 262 | for (Symbol *sym : symVector) 263 | sym->parseSymbolVersion(); 264 | 265 | // isPreemptible is false at this point. To correctly compute the binding of a 266 | // Defined (which is used by includeInDynsym()), we need to know if it is 267 | // VER_NDX_LOCAL or not. Compute symbol versions before handling 268 | // --dynamic-list. 269 | handleDynamicList(); 270 | } 271 | 272 | } // namespace elf 273 | } // namespace lld 274 | -------------------------------------------------------------------------------- /ELF/SymbolTable.h: -------------------------------------------------------------------------------- 1 | //===- SymbolTable.h --------------------------------------------*- C++ -*-===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | #ifndef LLD_ELF_SYMBOL_TABLE_H 10 | #define LLD_ELF_SYMBOL_TABLE_H 11 | 12 | #include "InputFiles.h" 13 | #include "Symbols.h" 14 | #include "lld/Common/Strings.h" 15 | #include "llvm/ADT/CachedHashString.h" 16 | #include "llvm/ADT/DenseMap.h" 17 | #include "llvm/ADT/STLExtras.h" 18 | 19 | namespace lld { 20 | namespace elf { 21 | 22 | // SymbolTable is a bucket of all known symbols, including defined, 23 | // undefined, or lazy symbols (the last one is symbols in archive 24 | // files whose archive members are not yet loaded). 25 | // 26 | // We put all symbols of all files to a SymbolTable, and the 27 | // SymbolTable selects the "best" symbols if there are name 28 | // conflicts. For example, obviously, a defined symbol is better than 29 | // an undefined symbol. Or, if there's a conflict between a lazy and a 30 | // undefined, it'll read an archive member to read a real definition 31 | // to replace the lazy symbol. The logic is implemented in the 32 | // add*() functions, which are called by input files as they are parsed. There 33 | // is one add* function per symbol type. 34 | class SymbolTable { 35 | struct FilterOutPlaceholder { 36 | bool operator()(Symbol *S) const { return !S->isPlaceholder(); } 37 | }; 38 | using iterator = llvm::filter_iterator::const_iterator, 39 | FilterOutPlaceholder>; 40 | 41 | public: 42 | llvm::iterator_range symbols() const { 43 | return llvm::make_filter_range(symVector, FilterOutPlaceholder()); 44 | } 45 | 46 | void wrap(Symbol *sym, Symbol *real, Symbol *wrap); 47 | 48 | Symbol *insert(StringRef name); 49 | 50 | Symbol *addSymbol(const Symbol &newSym); 51 | 52 | void scanVersionScript(); 53 | 54 | Symbol *find(StringRef name); 55 | 56 | void handleDynamicList(); 57 | 58 | // Set of .so files to not link the same shared object file more than once. 59 | llvm::DenseMap soNames; 60 | 61 | // Comdat groups define "link once" sections. If two comdat groups have the 62 | // same name, only one of them is linked, and the other is ignored. This map 63 | // is used to uniquify them. 64 | llvm::DenseMap comdatGroups; 65 | 66 | private: 67 | std::vector findByVersion(SymbolVersion ver); 68 | std::vector findAllByVersion(SymbolVersion ver); 69 | 70 | llvm::StringMap> &getDemangledSyms(); 71 | void assignExactVersion(SymbolVersion ver, uint16_t versionId, 72 | StringRef versionName); 73 | void assignWildcardVersion(SymbolVersion ver, uint16_t versionId); 74 | 75 | // The order the global symbols are in is not defined. We can use an arbitrary 76 | // order, but it has to be reproducible. That is true even when cross linking. 77 | // The default hashing of StringRef produces different results on 32 and 64 78 | // bit systems so we use a map to a vector. That is arbitrary, deterministic 79 | // but a bit inefficient. 80 | // FIXME: Experiment with passing in a custom hashing or sorting the symbols 81 | // once symbol resolution is finished. 82 | llvm::DenseMap symMap; 83 | std::vector symVector; 84 | 85 | // A map from demangled symbol names to their symbol objects. 86 | // This mapping is 1:N because two symbols with different versions 87 | // can have the same name. We use this map to handle "extern C++ {}" 88 | // directive in version scripts. 89 | llvm::Optional>> demangledSyms; 90 | }; 91 | 92 | extern SymbolTable *symtab; 93 | 94 | } // namespace elf 95 | } // namespace lld 96 | 97 | #endif 98 | -------------------------------------------------------------------------------- /ELF/Target.cpp: -------------------------------------------------------------------------------- 1 | //===- Target.cpp ---------------------------------------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // 9 | // Machine-specific things, such as applying relocations, creation of 10 | // GOT or PLT entries, etc., are handled in this file. 11 | // 12 | // Refer the ELF spec for the single letter variables, S, A or P, used 13 | // in this file. 14 | // 15 | // Some functions defined in this file has "relaxTls" as part of their names. 16 | // They do peephole optimization for TLS variables by rewriting instructions. 17 | // They are not part of the ABI but optional optimization, so you can skip 18 | // them if you are not interested in how TLS variables are optimized. 19 | // See the following paper for the details. 20 | // 21 | // Ulrich Drepper, ELF Handling For Thread-Local Storage 22 | // http://www.akkadia.org/drepper/tls.pdf 23 | // 24 | //===----------------------------------------------------------------------===// 25 | 26 | #include "Target.h" 27 | #include "InputFiles.h" 28 | #include "OutputSections.h" 29 | #include "SymbolTable.h" 30 | #include "Symbols.h" 31 | #include "SyntheticSections.h" 32 | #include "lld/Common/ErrorHandler.h" 33 | #include "llvm/Object/ELF.h" 34 | 35 | using namespace llvm; 36 | using namespace llvm::object; 37 | using namespace llvm::ELF; 38 | 39 | namespace lld { 40 | std::string toString(elf::RelType type) { 41 | StringRef s = getELFRelocationTypeName(elf::config->emachine, type); 42 | if (s == "Unknown") 43 | return ("Unknown (" + Twine(type) + ")").str(); 44 | return std::string(s); 45 | } 46 | 47 | namespace elf { 48 | const TargetInfo *target; 49 | 50 | TargetInfo *getTarget() { 51 | switch (config->emachine) { 52 | case EM_386: 53 | case EM_IAMCU: 54 | return getX86TargetInfo(); 55 | case EM_AARCH64: 56 | return getAArch64TargetInfo(); 57 | case EM_ARM: 58 | return getARMTargetInfo(); 59 | case EM_PPC: 60 | return getPPCTargetInfo(); 61 | case EM_PPC64: 62 | return getPPC64TargetInfo(); 63 | case EM_RISCV: 64 | return getRISCVTargetInfo(); 65 | case EM_X86_64: 66 | return getX86_64TargetInfo(); 67 | } 68 | llvm_unreachable("unknown target machine"); 69 | } 70 | 71 | template static ErrorPlace getErrPlace(const uint8_t *loc) { 72 | assert(loc != nullptr); 73 | for (InputSectionBase *d : inputSections) { 74 | auto *isec = cast(d); 75 | if (!isec->getParent() || (isec->type & SHT_NOBITS)) 76 | continue; 77 | 78 | const uint8_t *isecLoc = 79 | Out::bufferStart 80 | ? (Out::bufferStart + isec->getParent()->offset + isec->outSecOff) 81 | : isec->data().data(); 82 | if (isecLoc == nullptr) { 83 | assert(isa(isec) && "No data but not synthetic?"); 84 | continue; 85 | } 86 | if (isecLoc <= loc && loc < isecLoc + isec->getSize()) 87 | return {isec, isec->template getLocation(loc - isecLoc) + ": "}; 88 | } 89 | return {}; 90 | } 91 | 92 | ErrorPlace getErrorPlace(const uint8_t *loc) { 93 | switch (config->ekind) { 94 | case ELF32LEKind: 95 | return getErrPlace(loc); 96 | case ELF32BEKind: 97 | return getErrPlace(loc); 98 | case ELF64LEKind: 99 | return getErrPlace(loc); 100 | case ELF64BEKind: 101 | return getErrPlace(loc); 102 | default: 103 | llvm_unreachable("unknown ELF type"); 104 | } 105 | } 106 | 107 | TargetInfo::~TargetInfo() {} 108 | 109 | int64_t TargetInfo::getImplicitAddend(const uint8_t *buf, RelType type) const { 110 | return 0; 111 | } 112 | 113 | bool TargetInfo::usesOnlyLowPageBits(RelType type) const { return false; } 114 | 115 | bool TargetInfo::needsThunk(RelExpr expr, RelType type, const InputFile *file, 116 | uint64_t branchAddr, const Symbol &s, 117 | int64_t a) const { 118 | return false; 119 | } 120 | 121 | bool TargetInfo::inBranchRange(RelType type, uint64_t src, uint64_t dst) const { 122 | return true; 123 | } 124 | 125 | RelExpr TargetInfo::adjustRelaxExpr(RelType type, const uint8_t *data, 126 | RelExpr expr) const { 127 | return expr; 128 | } 129 | 130 | void TargetInfo::relaxGot(uint8_t *loc, const Relocation &rel, 131 | uint64_t val) const { 132 | llvm_unreachable("Should not have claimed to be relaxable"); 133 | } 134 | 135 | void TargetInfo::relaxTlsGdToLe(uint8_t *loc, const Relocation &rel, 136 | uint64_t val) const { 137 | llvm_unreachable("Should not have claimed to be relaxable"); 138 | } 139 | 140 | void TargetInfo::relaxTlsGdToIe(uint8_t *loc, const Relocation &rel, 141 | uint64_t val) const { 142 | llvm_unreachable("Should not have claimed to be relaxable"); 143 | } 144 | 145 | void TargetInfo::relaxTlsIeToLe(uint8_t *loc, const Relocation &rel, 146 | uint64_t val) const { 147 | llvm_unreachable("Should not have claimed to be relaxable"); 148 | } 149 | 150 | void TargetInfo::relaxTlsLdToLe(uint8_t *loc, const Relocation &rel, 151 | uint64_t val) const { 152 | llvm_unreachable("Should not have claimed to be relaxable"); 153 | } 154 | 155 | uint64_t TargetInfo::getImageBase() const { 156 | // Use -image-base if set. Fall back to the target default if not. 157 | if (config->imageBase) 158 | return *config->imageBase; 159 | return config->isPic ? 0 : defaultImageBase; 160 | } 161 | 162 | } // namespace elf 163 | } // namespace lld 164 | -------------------------------------------------------------------------------- /ELF/Target.h: -------------------------------------------------------------------------------- 1 | //===- Target.h -------------------------------------------------*- C++ -*-===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | #ifndef LLD_ELF_TARGET_H 10 | #define LLD_ELF_TARGET_H 11 | 12 | #include "InputSection.h" 13 | #include "lld/Common/ErrorHandler.h" 14 | #include "llvm/Object/ELF.h" 15 | #include "llvm/Support/MathExtras.h" 16 | #include 17 | 18 | namespace lld { 19 | std::string toString(elf::RelType type); 20 | 21 | namespace elf { 22 | class Defined; 23 | class InputFile; 24 | class Symbol; 25 | 26 | class TargetInfo { 27 | public: 28 | virtual uint32_t calcEFlags() const { return 0; } 29 | virtual RelExpr getRelExpr(RelType type, const Symbol &s, 30 | const uint8_t *loc) const = 0; 31 | virtual RelType getDynRel(RelType type) const { return 0; } 32 | virtual void writeGotPltHeader(uint8_t *buf) const {} 33 | virtual void writeGotHeader(uint8_t *buf) const {} 34 | virtual void writeGotPlt(uint8_t *buf, const Symbol &s) const {}; 35 | virtual void writeIgotPlt(uint8_t *buf, const Symbol &s) const {} 36 | virtual int64_t getImplicitAddend(const uint8_t *buf, RelType type) const; 37 | virtual int getTlsGdRelaxSkip(RelType type) const { return 1; } 38 | 39 | // If lazy binding is supported, the first entry of the PLT has code 40 | // to call the dynamic linker to resolve PLT entries the first time 41 | // they are called. This function writes that code. 42 | virtual void writePltHeader(uint8_t *buf) const {} 43 | 44 | virtual void writePlt(uint8_t *buf, const Symbol &sym, 45 | uint64_t pltEntryAddr) const {} 46 | virtual void writeIplt(uint8_t *buf, const Symbol &sym, 47 | uint64_t pltEntryAddr) const { 48 | // All but PPC32 and PPC64 use the same format for .plt and .iplt entries. 49 | writePlt(buf, sym, pltEntryAddr); 50 | } 51 | virtual void addPltHeaderSymbols(InputSection &isec) const {} 52 | virtual void addPltSymbols(InputSection &isec, uint64_t off) const {} 53 | 54 | // Returns true if a relocation only uses the low bits of a value such that 55 | // all those bits are in the same page. For example, if the relocation 56 | // only uses the low 12 bits in a system with 4k pages. If this is true, the 57 | // bits will always have the same value at runtime and we don't have to emit 58 | // a dynamic relocation. 59 | virtual bool usesOnlyLowPageBits(RelType type) const; 60 | 61 | // Decide whether a Thunk is needed for the relocation from File 62 | // targeting S. 63 | virtual bool needsThunk(RelExpr expr, RelType relocType, 64 | const InputFile *file, uint64_t branchAddr, 65 | const Symbol &s, int64_t a) const; 66 | 67 | // On systems with range extensions we place collections of Thunks at 68 | // regular spacings that enable the majority of branches reach the Thunks. 69 | // a value of 0 means range extension thunks are not supported. 70 | virtual uint32_t getThunkSectionSpacing() const { return 0; } 71 | 72 | // Return true if we can reach dst from src with RelType type. 73 | virtual bool inBranchRange(RelType type, uint64_t src, 74 | uint64_t dst) const; 75 | 76 | virtual void relocate(uint8_t *loc, const Relocation &rel, 77 | uint64_t val) const = 0; 78 | void relocateNoSym(uint8_t *loc, RelType type, uint64_t val) const { 79 | relocate(loc, Relocation{R_NONE, type, 0, 0, nullptr}, val); 80 | } 81 | 82 | virtual void applyJumpInstrMod(uint8_t *loc, JumpModType type, 83 | JumpModType val) const {} 84 | 85 | virtual ~TargetInfo(); 86 | 87 | unsigned defaultCommonPageSize = 4096; 88 | unsigned defaultMaxPageSize = 4096; 89 | 90 | uint64_t getImageBase() const; 91 | 92 | // True if _GLOBAL_OFFSET_TABLE_ is relative to .got.plt, false if .got. 93 | bool gotBaseSymInGotPlt = true; 94 | 95 | RelType copyRel; 96 | RelType gotRel; 97 | RelType noneRel; 98 | RelType pltRel; 99 | RelType relativeRel; 100 | RelType iRelativeRel; 101 | RelType symbolicRel; 102 | RelType tlsDescRel; 103 | RelType tlsGotRel; 104 | RelType tlsModuleIndexRel; 105 | RelType tlsOffsetRel; 106 | unsigned pltEntrySize; 107 | unsigned pltHeaderSize; 108 | unsigned ipltEntrySize; 109 | 110 | // At least on x86_64 positions 1 and 2 are used by the first plt entry 111 | // to support lazy loading. 112 | unsigned gotPltHeaderEntriesNum = 3; 113 | 114 | // On PPC ELF V2 abi, the first entry in the .got is the .TOC. 115 | unsigned gotHeaderEntriesNum = 0; 116 | 117 | bool needsThunks = false; 118 | 119 | // A 4-byte field corresponding to one or more trap instructions, used to pad 120 | // executable OutputSections. 121 | std::array trapInstr; 122 | 123 | // Stores the NOP instructions of different sizes for the target and is used 124 | // to pad sections that are relaxed. 125 | llvm::Optional>> nopInstrs; 126 | 127 | // If a target needs to rewrite calls to __morestack to instead call 128 | // __morestack_non_split when a split-stack enabled caller calls a 129 | // non-split-stack callee this will return true. Otherwise returns false. 130 | bool needsMoreStackNonSplit = true; 131 | 132 | virtual RelExpr adjustRelaxExpr(RelType type, const uint8_t *data, 133 | RelExpr expr) const; 134 | virtual void relaxGot(uint8_t *loc, const Relocation &rel, 135 | uint64_t val) const; 136 | virtual void relaxTlsGdToIe(uint8_t *loc, const Relocation &rel, 137 | uint64_t val) const; 138 | virtual void relaxTlsGdToLe(uint8_t *loc, const Relocation &rel, 139 | uint64_t val) const; 140 | virtual void relaxTlsIeToLe(uint8_t *loc, const Relocation &rel, 141 | uint64_t val) const; 142 | virtual void relaxTlsLdToLe(uint8_t *loc, const Relocation &rel, 143 | uint64_t val) const; 144 | 145 | protected: 146 | // On FreeBSD x86_64 the first page cannot be mmaped. 147 | // On Linux this is controlled by vm.mmap_min_addr. At least on some x86_64 148 | // installs this is set to 65536, so the first 15 pages cannot be used. 149 | // Given that, the smallest value that can be used in here is 0x10000. 150 | uint64_t defaultImageBase = 0x10000; 151 | }; 152 | 153 | TargetInfo *getAArch64TargetInfo(); 154 | TargetInfo *getAMDGPUTargetInfo(); 155 | TargetInfo *getARMTargetInfo(); 156 | TargetInfo *getPPC64TargetInfo(); 157 | TargetInfo *getPPCTargetInfo(); 158 | TargetInfo *getRISCVTargetInfo(); 159 | TargetInfo *getX86TargetInfo(); 160 | TargetInfo *getX86_64TargetInfo(); 161 | 162 | struct ErrorPlace { 163 | InputSectionBase *isec; 164 | std::string loc; 165 | }; 166 | 167 | // Returns input section and corresponding source string for the given location. 168 | ErrorPlace getErrorPlace(const uint8_t *loc); 169 | 170 | static inline std::string getErrorLocation(const uint8_t *loc) { 171 | return getErrorPlace(loc).loc; 172 | } 173 | 174 | void writePPC32GlinkSection(uint8_t *buf, size_t numEntries); 175 | 176 | bool tryRelaxPPC64TocIndirection(const Relocation &rel, uint8_t *bufLoc); 177 | unsigned getPPCDFormOp(unsigned secondaryOp); 178 | 179 | // In the PowerPC64 Elf V2 abi a function can have 2 entry points. The first 180 | // is a global entry point (GEP) which typically is used to initialize the TOC 181 | // pointer in general purpose register 2. The second is a local entry 182 | // point (LEP) which bypasses the TOC pointer initialization code. The 183 | // offset between GEP and LEP is encoded in a function's st_other flags. 184 | // This function will return the offset (in bytes) from the global entry-point 185 | // to the local entry-point. 186 | unsigned getPPC64GlobalEntryToLocalEntryOffset(uint8_t stOther); 187 | 188 | // Returns true if a relocation is a small code model relocation that accesses 189 | // the .toc section. 190 | bool isPPC64SmallCodeModelTocReloc(RelType type); 191 | 192 | uint64_t getPPC64TocBase(); 193 | uint64_t getAArch64Page(uint64_t expr); 194 | 195 | extern const TargetInfo *target; 196 | TargetInfo *getTarget(); 197 | 198 | void reportRangeError(uint8_t *loc, const Relocation &rel, const Twine &v, 199 | int64_t min, uint64_t max); 200 | 201 | // Make sure that V can be represented as an N bit signed integer. 202 | inline void checkInt(uint8_t *loc, int64_t v, int n, const Relocation &rel) { 203 | if (v != llvm::SignExtend64(v, n)) 204 | reportRangeError(loc, rel, Twine(v), llvm::minIntN(n), llvm::maxIntN(n)); 205 | } 206 | 207 | // Make sure that V can be represented as an N bit unsigned integer. 208 | inline void checkUInt(uint8_t *loc, uint64_t v, int n, const Relocation &rel) { 209 | if ((v >> n) != 0) 210 | reportRangeError(loc, rel, Twine(v), 0, llvm::maxUIntN(n)); 211 | } 212 | 213 | // Make sure that V can be represented as an N bit signed or unsigned integer. 214 | inline void checkIntUInt(uint8_t *loc, uint64_t v, int n, 215 | const Relocation &rel) { 216 | // For the error message we should cast V to a signed integer so that error 217 | // messages show a small negative value rather than an extremely large one 218 | if (v != (uint64_t)llvm::SignExtend64(v, n) && (v >> n) != 0) 219 | reportRangeError(loc, rel, Twine((int64_t)v), llvm::minIntN(n), 220 | llvm::maxUIntN(n)); 221 | } 222 | 223 | inline void checkAlignment(uint8_t *loc, uint64_t v, int n, 224 | const Relocation &rel) { 225 | if ((v & (n - 1)) != 0) 226 | error(getErrorLocation(loc) + "improper alignment for relocation " + 227 | lld::toString(rel.type) + ": 0x" + llvm::utohexstr(v) + 228 | " is not aligned to " + Twine(n) + " bytes"); 229 | } 230 | 231 | // Endianness-aware read/write. 232 | inline uint16_t read16(const void *p) { 233 | return llvm::support::endian::read16(p, config->endianness); 234 | } 235 | 236 | inline uint32_t read32(const void *p) { 237 | return llvm::support::endian::read32(p, config->endianness); 238 | } 239 | 240 | inline uint64_t read64(const void *p) { 241 | return llvm::support::endian::read64(p, config->endianness); 242 | } 243 | 244 | inline void write16(void *p, uint16_t v) { 245 | llvm::support::endian::write16(p, v, config->endianness); 246 | } 247 | 248 | inline void write32(void *p, uint32_t v) { 249 | llvm::support::endian::write32(p, v, config->endianness); 250 | } 251 | 252 | inline void write64(void *p, uint64_t v) { 253 | llvm::support::endian::write64(p, v, config->endianness); 254 | } 255 | } // namespace elf 256 | } // namespace lld 257 | 258 | #endif 259 | -------------------------------------------------------------------------------- /ELF/Thunks.h: -------------------------------------------------------------------------------- 1 | //===- Thunks.h --------------------------------------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | #ifndef LLD_ELF_THUNKS_H 10 | #define LLD_ELF_THUNKS_H 11 | 12 | #include "Relocations.h" 13 | 14 | namespace lld { 15 | namespace elf { 16 | class Defined; 17 | class InputFile; 18 | class Symbol; 19 | class ThunkSection; 20 | // Class to describe an instance of a Thunk. 21 | // A Thunk is a code-sequence inserted by the linker in between a caller and 22 | // the callee. The relocation to the callee is redirected to the Thunk, which 23 | // after executing transfers control to the callee. Typical uses of Thunks 24 | // include transferring control from non-pi to pi and changing state on 25 | // targets like ARM. 26 | // 27 | // Thunks can be created for Defined, Shared and Undefined Symbols. 28 | // Thunks are assigned to synthetic ThunkSections 29 | class Thunk { 30 | public: 31 | Thunk(Symbol &destination, int64_t addend); 32 | virtual ~Thunk(); 33 | 34 | virtual uint32_t size() = 0; 35 | virtual void writeTo(uint8_t *buf) = 0; 36 | 37 | // All Thunks must define at least one symbol, known as the thunk target 38 | // symbol, so that we can redirect relocations to it. The thunk may define 39 | // additional symbols, but these are never targets for relocations. 40 | virtual void addSymbols(ThunkSection &isec) = 0; 41 | 42 | void setOffset(uint64_t offset); 43 | Defined *addSymbol(StringRef name, uint8_t type, uint64_t value, 44 | InputSectionBase §ion); 45 | 46 | // Some Thunks must be placed immediately before their Target as they elide 47 | // a branch and fall through to the first Symbol in the Target. 48 | virtual InputSection *getTargetInputSection() const { return nullptr; } 49 | 50 | // To reuse a Thunk the InputSection and the relocation must be compatible 51 | // with it. 52 | virtual bool isCompatibleWith(const InputSection &, 53 | const Relocation &) const { 54 | return true; 55 | } 56 | 57 | Defined *getThunkTargetSym() const { return syms[0]; } 58 | 59 | Symbol &destination; 60 | int64_t addend; 61 | llvm::SmallVector syms; 62 | uint64_t offset = 0; 63 | // The alignment requirement for this Thunk, defaults to the size of the 64 | // typical code section alignment. 65 | uint32_t alignment = 4; 66 | }; 67 | 68 | // For a Relocation to symbol S create a Thunk to be added to a synthetic 69 | // ThunkSection. 70 | Thunk *addThunk(const InputSection &isec, Relocation &rel); 71 | 72 | void writePPC32PltCallStub(uint8_t *buf, uint64_t gotPltVA, 73 | const InputFile *file, int64_t addend); 74 | void writePPC64LoadAndBranch(uint8_t *buf, int64_t offset); 75 | 76 | } // namespace elf 77 | } // namespace lld 78 | 79 | #endif 80 | -------------------------------------------------------------------------------- /ELF/Writer.h: -------------------------------------------------------------------------------- 1 | //===- Writer.h -------------------------------------------------*- C++ -*-===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | #ifndef LLD_ELF_WRITER_H 10 | #define LLD_ELF_WRITER_H 11 | 12 | #include "Config.h" 13 | #include "llvm/ADT/ArrayRef.h" 14 | #include "llvm/ADT/StringRef.h" 15 | #include 16 | #include 17 | 18 | namespace lld { 19 | namespace elf { 20 | class InputFile; 21 | class OutputSection; 22 | class InputSectionBase; 23 | void copySectionsIntoPartitions(); 24 | template void createSyntheticSections(); 25 | void combineEhSections(); 26 | template void writeResult(); 27 | 28 | // This describes a program header entry. 29 | // Each contains type, access flags and range of output sections that will be 30 | // placed in it. 31 | struct PhdrEntry { 32 | PhdrEntry(unsigned type, unsigned flags) 33 | : p_align(type == llvm::ELF::PT_LOAD ? config->maxPageSize : 0), 34 | p_type(type), p_flags(flags) {} 35 | void add(OutputSection *sec); 36 | 37 | uint64_t p_paddr = 0; 38 | uint64_t p_vaddr = 0; 39 | uint64_t p_memsz = 0; 40 | uint64_t p_filesz = 0; 41 | uint64_t p_offset = 0; 42 | uint32_t p_align = 0; 43 | uint32_t p_type = 0; 44 | uint32_t p_flags = 0; 45 | 46 | OutputSection *firstSec = nullptr; 47 | OutputSection *lastSec = nullptr; 48 | bool hasLMA = false; 49 | 50 | uint64_t lmaOffset = 0; 51 | }; 52 | 53 | void addReservedSymbols(); 54 | llvm::StringRef getOutputSectionName(const InputSectionBase *s); 55 | 56 | } // namespace elf 57 | } // namespace lld 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | picolld (stripped-down lld) 2 | =========================== 3 | 4 | With `llvm-config` in PATH, 5 | 6 | ```sh 7 | mkdir out 8 | cd out 9 | cmake /path/to/picolld -G Ninja 10 | ninja lld 11 | ``` 12 | 13 | Based on llvm-project/lld on 2020-04-10. Deleted 14 | 15 | * MIPS: ~3000 lines 16 | * LTO: ~800 lines 17 | * basic block sections: ~400 lines 18 | 19 | Removing the dependency on LLVM is possible, but it would require lots of efforts: 20 | 21 | * `llvm/DebugInfo/DWARF/`: .eh_frame support 22 | * `llvm/Object/`: ELF parsing 23 | * `llvm/Option/Option.h`: command line parsing 24 | * `llvm/ADT/`: STL extensions 25 | -------------------------------------------------------------------------------- /cmake/modules/AddLLD.cmake: -------------------------------------------------------------------------------- 1 | macro(add_lld_library name) 2 | cmake_parse_arguments(ARG 3 | "SHARED" 4 | "" 5 | "" 6 | ${ARGN}) 7 | if(ARG_SHARED) 8 | set(ARG_ENABLE_SHARED SHARED) 9 | endif() 10 | llvm_add_library(${name} ${ARG_ENABLE_SHARED} ${ARG_UNPARSED_ARGUMENTS}) 11 | set_target_properties(${name} PROPERTIES FOLDER "lld libraries") 12 | 13 | if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY) 14 | if(${name} IN_LIST LLVM_DISTRIBUTION_COMPONENTS OR 15 | NOT LLVM_DISTRIBUTION_COMPONENTS) 16 | set(export_to_lldtargets EXPORT lldTargets) 17 | set_property(GLOBAL PROPERTY LLD_HAS_EXPORTS True) 18 | endif() 19 | 20 | install(TARGETS ${name} 21 | COMPONENT ${name} 22 | ${export_to_lldtargets} 23 | LIBRARY DESTINATION lib${LLVM_LIBDIR_SUFFIX} 24 | ARCHIVE DESTINATION lib${LLVM_LIBDIR_SUFFIX} 25 | RUNTIME DESTINATION bin) 26 | 27 | if (${ARG_SHARED} AND NOT CMAKE_CONFIGURATION_TYPES) 28 | add_llvm_install_targets(install-${name} 29 | DEPENDS ${name} 30 | COMPONENT ${name}) 31 | endif() 32 | set_property(GLOBAL APPEND PROPERTY LLD_EXPORTS ${name}) 33 | endif() 34 | endmacro(add_lld_library) 35 | 36 | macro(add_lld_executable name) 37 | add_llvm_executable(${name} ${ARGN}) 38 | set_target_properties(${name} PROPERTIES FOLDER "lld executables") 39 | endmacro(add_lld_executable) 40 | 41 | macro(add_lld_tool name) 42 | if (NOT LLD_BUILD_TOOLS) 43 | set(EXCLUDE_FROM_ALL ON) 44 | endif() 45 | 46 | add_lld_executable(${name} ${ARGN}) 47 | 48 | if (LLD_BUILD_TOOLS) 49 | if(${name} IN_LIST LLVM_DISTRIBUTION_COMPONENTS OR 50 | NOT LLVM_DISTRIBUTION_COMPONENTS) 51 | set(export_to_lldtargets EXPORT lldTargets) 52 | set_property(GLOBAL PROPERTY LLD_HAS_EXPORTS True) 53 | endif() 54 | 55 | install(TARGETS ${name} 56 | ${export_to_lldtargets} 57 | RUNTIME DESTINATION bin 58 | COMPONENT ${name}) 59 | 60 | if(NOT CMAKE_CONFIGURATION_TYPES) 61 | add_llvm_install_targets(install-${name} 62 | DEPENDS ${name} 63 | COMPONENT ${name}) 64 | endif() 65 | set_property(GLOBAL APPEND PROPERTY LLD_EXPORTS ${name}) 66 | endif() 67 | endmacro() 68 | 69 | macro(add_lld_symlink name dest) 70 | add_llvm_tool_symlink(${name} ${dest} ALWAYS_GENERATE) 71 | # Always generate install targets 72 | llvm_install_symlink(${name} ${dest} ALWAYS_GENERATE) 73 | endmacro() 74 | -------------------------------------------------------------------------------- /cmake/modules/FindVTune.cmake: -------------------------------------------------------------------------------- 1 | # - Find VTune ittnotify. 2 | # Defines: 3 | # VTune_FOUND 4 | # VTune_INCLUDE_DIRS 5 | # VTune_LIBRARIES 6 | 7 | set(dirs 8 | "$ENV{VTUNE_AMPLIFIER_XE_2013_DIR}/" 9 | "C:/Program Files (x86)/Intel/VTune Amplifier XE 2013/" 10 | "$ENV{VTUNE_AMPLIFIER_XE_2011_DIR}/" 11 | "C:/Program Files (x86)/Intel/VTune Amplifier XE 2011/" 12 | ) 13 | 14 | find_path(VTune_INCLUDE_DIRS ittnotify.h 15 | PATHS ${dirs} 16 | PATH_SUFFIXES include) 17 | 18 | if (CMAKE_SIZEOF_VOID_P MATCHES "8") 19 | set(vtune_lib_dir lib64) 20 | else() 21 | set(vtune_lib_dir lib32) 22 | endif() 23 | 24 | find_library(VTune_LIBRARIES libittnotify 25 | HINTS "${VTune_INCLUDE_DIRS}/.." 26 | PATHS ${dirs} 27 | PATH_SUFFIXES ${vtune_lib_dir}) 28 | 29 | include(FindPackageHandleStandardArgs) 30 | find_package_handle_standard_args( 31 | VTune DEFAULT_MSG VTune_LIBRARIES VTune_INCLUDE_DIRS) 32 | -------------------------------------------------------------------------------- /include/lld/Common/Args.h: -------------------------------------------------------------------------------- 1 | //===- Args.h ---------------------------------------------------*- C++ -*-===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | #ifndef LLD_ARGS_H 10 | #define LLD_ARGS_H 11 | 12 | #include "lld/Common/LLVM.h" 13 | #include "llvm/Support/CodeGen.h" 14 | #include "llvm/Support/MemoryBuffer.h" 15 | #include 16 | 17 | namespace llvm { 18 | namespace opt { 19 | class InputArgList; 20 | } 21 | } // namespace llvm 22 | 23 | namespace lld { 24 | namespace args { 25 | 26 | llvm::CodeGenOpt::Level getCGOptLevel(int optLevelLTO); 27 | 28 | int64_t getInteger(llvm::opt::InputArgList &args, unsigned key, 29 | int64_t Default); 30 | 31 | std::vector getStrings(llvm::opt::InputArgList &args, int id); 32 | 33 | uint64_t getZOptionValue(llvm::opt::InputArgList &args, int id, StringRef key, 34 | uint64_t Default); 35 | 36 | std::vector getLines(MemoryBufferRef mb); 37 | 38 | StringRef getFilenameWithoutExe(StringRef path); 39 | 40 | } // namespace args 41 | } // namespace lld 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /include/lld/Common/DWARF.h: -------------------------------------------------------------------------------- 1 | //===- DWARF.h --------------------------------------------------*- C++ -*-===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | #ifndef LLD_DWARF_H 10 | #define LLD_DWARF_H 11 | 12 | #include "lld/Common/LLVM.h" 13 | #include "llvm/ADT/DenseMap.h" 14 | #include "llvm/ADT/StringRef.h" 15 | #include "llvm/DebugInfo/DWARF/DWARFContext.h" 16 | #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h" 17 | #include 18 | #include 19 | 20 | namespace llvm { 21 | struct DILineInfo; 22 | } // namespace llvm 23 | 24 | namespace lld { 25 | 26 | class DWARFCache { 27 | public: 28 | DWARFCache(std::unique_ptr dwarf); 29 | llvm::Optional getDILineInfo(uint64_t offset, 30 | uint64_t sectionIndex); 31 | llvm::Optional> 32 | getVariableLoc(StringRef name); 33 | 34 | llvm::DWARFContext *getContext() { return dwarf.get(); } 35 | 36 | private: 37 | std::unique_ptr dwarf; 38 | std::vector lineTables; 39 | struct VarLoc { 40 | const llvm::DWARFDebugLine::LineTable *lt; 41 | unsigned file; 42 | unsigned line; 43 | }; 44 | llvm::DenseMap variableLoc; 45 | }; 46 | 47 | } // namespace lld 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /include/lld/Common/Driver.h: -------------------------------------------------------------------------------- 1 | //===- lld/Common/Driver.h - Linker Driver Emulator -----------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | #ifndef LLD_COMMON_DRIVER_H 10 | #define LLD_COMMON_DRIVER_H 11 | 12 | #include "llvm/ADT/ArrayRef.h" 13 | #include "llvm/Support/raw_ostream.h" 14 | 15 | namespace lld { 16 | namespace coff { 17 | bool link(llvm::ArrayRef args, bool canExitEarly, 18 | llvm::raw_ostream &stdoutOS, llvm::raw_ostream &stderrOS); 19 | } 20 | 21 | namespace mingw { 22 | bool link(llvm::ArrayRef args, bool canExitEarly, 23 | llvm::raw_ostream &stdoutOS, llvm::raw_ostream &stderrOS); 24 | } 25 | 26 | namespace elf { 27 | bool link(llvm::ArrayRef args, bool canExitEarly, 28 | llvm::raw_ostream &stdoutOS, llvm::raw_ostream &stderrOS); 29 | } 30 | 31 | namespace mach_o { 32 | bool link(llvm::ArrayRef args, bool canExitEarly, 33 | llvm::raw_ostream &stdoutOS, llvm::raw_ostream &stderrOS); 34 | } 35 | 36 | namespace macho { 37 | bool link(llvm::ArrayRef args, bool canExitEarly, 38 | llvm::raw_ostream &stdoutOS, llvm::raw_ostream &stderrOS); 39 | } 40 | 41 | namespace wasm { 42 | bool link(llvm::ArrayRef args, bool canExitEarly, 43 | llvm::raw_ostream &stdoutOS, llvm::raw_ostream &stderrOS); 44 | } 45 | } 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /include/lld/Common/ErrorHandler.h: -------------------------------------------------------------------------------- 1 | //===- ErrorHandler.h -------------------------------------------*- C++ -*-===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // 9 | // We designed lld's error handlers with the following goals in mind: 10 | // 11 | // - Errors can occur at any place where we handle user input, but we don't 12 | // want them to affect the normal execution path too much. Ideally, 13 | // handling errors should be as simple as reporting them and exit (but 14 | // without actually doing exit). 15 | // 16 | // In particular, the design to wrap all functions that could fail with 17 | // ErrorOr is rejected because otherwise we would have to wrap a large 18 | // number of functions in lld with ErrorOr. With that approach, if some 19 | // function F can fail, not only F but all functions that transitively call 20 | // F have to be wrapped with ErrorOr. That seemed too much. 21 | // 22 | // - Finding only one error at a time is not sufficient. We want to find as 23 | // many errors as possible with one execution of the linker. That means the 24 | // linker needs to keep running after a first error and give up at some 25 | // checkpoint (beyond which it would find cascading, false errors caused by 26 | // the previous errors). 27 | // 28 | // - We want a simple interface to report errors. Unlike Clang, the data we 29 | // handle is compiled binary, so we don't need an error reporting mechanism 30 | // that's as sophisticated as the one that Clang has. 31 | // 32 | // The current lld's error handling mechanism is simple: 33 | // 34 | // - When you find an error, report it using error() and continue as far as 35 | // you can. An internal error counter is incremented by one every time you 36 | // call error(). 37 | // 38 | // A common idiom to handle an error is calling error() and then returning 39 | // a reasonable default value. For example, if your function handles a 40 | // user-supplied alignment value, and if you find an invalid alignment 41 | // (e.g. 17 which is not 2^n), you may report it using error() and continue 42 | // as if it were alignment 1 (which is the simplest reasonable value). 43 | // 44 | // Note that you should not continue with an invalid value; that breaks the 45 | // internal consistency. You need to maintain all variables have some sane 46 | // value even after an error occurred. So, when you have to continue with 47 | // some value, always use a dummy value. 48 | // 49 | // - Find a reasonable checkpoint at where you want to stop the linker, and 50 | // add code to return from the function if errorCount() > 0. In most cases, 51 | // a checkpoint already exists, so you don't need to do anything for this. 52 | // 53 | // This interface satisfies all the goals that we mentioned above. 54 | // 55 | // You should never call fatal() except for reporting a corrupted input file. 56 | // fatal() immediately terminates the linker, so the function is not desirable 57 | // if you are using lld as a subroutine in other program, and with that you 58 | // can find only one error at a time. 59 | // 60 | // warn() doesn't do anything but printing out a given message. 61 | // 62 | // It is not recommended to use llvm::outs() or lld::errs() directly in lld 63 | // because they are not thread-safe. The functions declared in this file are 64 | // thread-safe. 65 | // 66 | //===----------------------------------------------------------------------===// 67 | 68 | #ifndef LLD_COMMON_ERRORHANDLER_H 69 | #define LLD_COMMON_ERRORHANDLER_H 70 | 71 | #include "lld/Common/LLVM.h" 72 | 73 | #include "llvm/ADT/STLExtras.h" 74 | #include "llvm/Support/Error.h" 75 | #include "llvm/Support/FileOutputBuffer.h" 76 | 77 | namespace llvm { 78 | class DiagnosticInfo; 79 | class raw_ostream; 80 | } 81 | 82 | namespace lld { 83 | 84 | // We wrap stdout and stderr so that you can pass alternative stdout/stderr as 85 | // arguments to lld::*::link() functions. 86 | extern llvm::raw_ostream *stdoutOS; 87 | extern llvm::raw_ostream *stderrOS; 88 | 89 | llvm::raw_ostream &outs(); 90 | llvm::raw_ostream &errs(); 91 | 92 | class ErrorHandler { 93 | public: 94 | uint64_t errorCount = 0; 95 | uint64_t errorLimit = 20; 96 | StringRef errorLimitExceededMsg = "too many errors emitted, stopping now"; 97 | StringRef logName = "lld"; 98 | bool exitEarly = true; 99 | bool fatalWarnings = false; 100 | bool verbose = false; 101 | bool vsDiagnostics = false; 102 | 103 | void error(const Twine &msg); 104 | LLVM_ATTRIBUTE_NORETURN void fatal(const Twine &msg); 105 | void log(const Twine &msg); 106 | void message(const Twine &msg); 107 | void warn(const Twine &msg); 108 | 109 | std::unique_ptr outputBuffer; 110 | 111 | private: 112 | using Colors = raw_ostream::Colors; 113 | 114 | std::string getLocation(const Twine &msg); 115 | }; 116 | 117 | /// Returns the default error handler. 118 | ErrorHandler &errorHandler(); 119 | 120 | inline void error(const Twine &msg) { errorHandler().error(msg); } 121 | inline LLVM_ATTRIBUTE_NORETURN void fatal(const Twine &msg) { 122 | errorHandler().fatal(msg); 123 | } 124 | inline void log(const Twine &msg) { errorHandler().log(msg); } 125 | inline void message(const Twine &msg) { errorHandler().message(msg); } 126 | inline void warn(const Twine &msg) { errorHandler().warn(msg); } 127 | inline uint64_t errorCount() { return errorHandler().errorCount; } 128 | 129 | LLVM_ATTRIBUTE_NORETURN void exitLld(int val); 130 | 131 | void diagnosticHandler(const llvm::DiagnosticInfo &di); 132 | void checkError(Error e); 133 | 134 | // check functions are convenient functions to strip errors 135 | // from error-or-value objects. 136 | template T check(ErrorOr e) { 137 | if (auto ec = e.getError()) 138 | fatal(ec.message()); 139 | return std::move(*e); 140 | } 141 | 142 | template T check(Expected e) { 143 | if (!e) 144 | fatal(llvm::toString(e.takeError())); 145 | return std::move(*e); 146 | } 147 | 148 | template 149 | T check2(ErrorOr e, llvm::function_ref prefix) { 150 | if (auto ec = e.getError()) 151 | fatal(prefix() + ": " + ec.message()); 152 | return std::move(*e); 153 | } 154 | 155 | template 156 | T check2(Expected e, llvm::function_ref prefix) { 157 | if (!e) 158 | fatal(prefix() + ": " + toString(e.takeError())); 159 | return std::move(*e); 160 | } 161 | 162 | inline std::string toString(const Twine &s) { return s.str(); } 163 | 164 | // To evaluate the second argument lazily, we use C macro. 165 | #define CHECK(E, S) check2((E), [&] { return toString(S); }) 166 | 167 | } // namespace lld 168 | 169 | #endif 170 | -------------------------------------------------------------------------------- /include/lld/Common/Filesystem.h: -------------------------------------------------------------------------------- 1 | //===- Filesystem.h ---------------------------------------------*- C++ -*-===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | #ifndef LLD_FILESYSTEM_H 10 | #define LLD_FILESYSTEM_H 11 | 12 | #include "lld/Common/LLVM.h" 13 | #include 14 | 15 | namespace lld { 16 | void unlinkAsync(StringRef path); 17 | std::error_code tryCreateFile(StringRef path); 18 | } // namespace lld 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /include/lld/Common/LLVM.h: -------------------------------------------------------------------------------- 1 | //===--- LLVM.h - Import various common LLVM datatypes ----------*- C++ -*-===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // 9 | // This file forward declares and imports various common LLVM datatypes that 10 | // lld wants to use unqualified. 11 | // 12 | //===----------------------------------------------------------------------===// 13 | 14 | #ifndef LLD_COMMON_LLVM_H 15 | #define LLD_COMMON_LLVM_H 16 | 17 | // This should be the only #include, force #includes of all the others on 18 | // clients. 19 | #include "llvm/ADT/Hashing.h" 20 | #include "llvm/ADT/StringRef.h" 21 | #include "llvm/Support/Casting.h" 22 | #include 23 | 24 | namespace llvm { 25 | // ADT's. 26 | class raw_ostream; 27 | class Error; 28 | class StringRef; 29 | class Twine; 30 | class MemoryBuffer; 31 | class MemoryBufferRef; 32 | template class ArrayRef; 33 | template class MutableArrayRef; 34 | template class SmallString; 35 | template class SmallVector; 36 | template class ErrorOr; 37 | template class Expected; 38 | 39 | namespace object { 40 | class WasmObjectFile; 41 | struct WasmSection; 42 | struct WasmSegment; 43 | class WasmSymbol; 44 | } // namespace object 45 | 46 | namespace wasm { 47 | struct WasmEvent; 48 | struct WasmEventType; 49 | struct WasmFunction; 50 | struct WasmGlobal; 51 | struct WasmGlobalType; 52 | struct WasmRelocation; 53 | struct WasmSignature; 54 | } // namespace wasm 55 | } // namespace llvm 56 | 57 | namespace lld { 58 | llvm::raw_ostream &outs(); 59 | llvm::raw_ostream &errs(); 60 | 61 | // Casting operators. 62 | using llvm::cast; 63 | using llvm::cast_or_null; 64 | using llvm::dyn_cast; 65 | using llvm::dyn_cast_or_null; 66 | using llvm::isa; 67 | 68 | // ADT's. 69 | using llvm::ArrayRef; 70 | using llvm::MutableArrayRef; 71 | using llvm::Error; 72 | using llvm::ErrorOr; 73 | using llvm::Expected; 74 | using llvm::MemoryBuffer; 75 | using llvm::MemoryBufferRef; 76 | using llvm::raw_ostream; 77 | using llvm::SmallString; 78 | using llvm::SmallVector; 79 | using llvm::StringRef; 80 | using llvm::Twine; 81 | 82 | using llvm::object::WasmObjectFile; 83 | using llvm::object::WasmSection; 84 | using llvm::object::WasmSegment; 85 | using llvm::object::WasmSymbol; 86 | using llvm::wasm::WasmEvent; 87 | using llvm::wasm::WasmEventType; 88 | using llvm::wasm::WasmFunction; 89 | using llvm::wasm::WasmGlobal; 90 | using llvm::wasm::WasmGlobalType; 91 | using llvm::wasm::WasmRelocation; 92 | using llvm::wasm::WasmSignature; 93 | } // end namespace lld. 94 | 95 | namespace std { 96 | template <> struct hash { 97 | public: 98 | size_t operator()(const llvm::StringRef &s) const { 99 | return llvm::hash_value(s); 100 | } 101 | }; 102 | } // namespace std 103 | 104 | #endif 105 | -------------------------------------------------------------------------------- /include/lld/Common/Memory.h: -------------------------------------------------------------------------------- 1 | //===- Memory.h -------------------------------------------------*- C++ -*-===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // 9 | // This file defines arena allocators. 10 | // 11 | // Almost all large objects, such as files, sections or symbols, are 12 | // used for the entire lifetime of the linker once they are created. 13 | // This usage characteristic makes arena allocator an attractive choice 14 | // where the entire linker is one arena. With an arena, newly created 15 | // objects belong to the arena and freed all at once when everything is done. 16 | // Arena allocators are efficient and easy to understand. 17 | // Most objects are allocated using the arena allocators defined by this file. 18 | // 19 | //===----------------------------------------------------------------------===// 20 | 21 | #ifndef LLD_COMMON_MEMORY_H 22 | #define LLD_COMMON_MEMORY_H 23 | 24 | #include "llvm/Support/Allocator.h" 25 | #include "llvm/Support/StringSaver.h" 26 | #include 27 | 28 | namespace lld { 29 | 30 | // Use this arena if your object doesn't have a destructor. 31 | extern llvm::BumpPtrAllocator bAlloc; 32 | extern llvm::StringSaver saver; 33 | 34 | void freeArena(); 35 | 36 | // These two classes are hack to keep track of all 37 | // SpecificBumpPtrAllocator instances. 38 | struct SpecificAllocBase { 39 | SpecificAllocBase() { instances.push_back(this); } 40 | virtual ~SpecificAllocBase() = default; 41 | virtual void reset() = 0; 42 | static std::vector instances; 43 | }; 44 | 45 | template struct SpecificAlloc : public SpecificAllocBase { 46 | void reset() override { alloc.DestroyAll(); } 47 | llvm::SpecificBumpPtrAllocator alloc; 48 | }; 49 | 50 | // Use this arena if your object has a destructor. 51 | // Your destructor will be invoked from freeArena(). 52 | template T *make(U &&... args) { 53 | static SpecificAlloc alloc; 54 | return new (alloc.alloc.Allocate()) T(std::forward(args)...); 55 | } 56 | 57 | } // namespace lld 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /include/lld/Common/Reproduce.h: -------------------------------------------------------------------------------- 1 | //===- Reproduce.h - Utilities for creating reproducers ---------*- C++ -*-===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | #ifndef LLD_COMMON_REPRODUCE_H 10 | #define LLD_COMMON_REPRODUCE_H 11 | 12 | #include "lld/Common/LLVM.h" 13 | #include "llvm/ADT/StringRef.h" 14 | #include "llvm/Support/Error.h" 15 | 16 | namespace llvm { 17 | namespace opt { class Arg; } 18 | } 19 | 20 | namespace lld { 21 | 22 | // Makes a given pathname an absolute path first, and then remove 23 | // beginning /. For example, "../foo.o" is converted to "home/john/foo.o", 24 | // assuming that the current directory is "/home/john/bar". 25 | std::string relativeToRoot(StringRef path); 26 | 27 | // Quote a given string if it contains a space character. 28 | std::string quote(StringRef s); 29 | 30 | // Returns the string form of the given argument. 31 | std::string toString(const llvm::opt::Arg &arg); 32 | } 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /include/lld/Common/Strings.h: -------------------------------------------------------------------------------- 1 | //===- Strings.h ------------------------------------------------*- C++ -*-===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | #ifndef LLD_STRINGS_H 10 | #define LLD_STRINGS_H 11 | 12 | #include "llvm/ADT/ArrayRef.h" 13 | #include "llvm/ADT/Optional.h" 14 | #include "llvm/ADT/StringRef.h" 15 | #include "llvm/Support/GlobPattern.h" 16 | #include 17 | #include 18 | 19 | namespace lld { 20 | // Returns a demangled C++ symbol name. If Name is not a mangled 21 | // name, it returns name. 22 | std::string demangleItanium(llvm::StringRef name); 23 | 24 | std::vector parseHex(llvm::StringRef s); 25 | bool isValidCIdentifier(llvm::StringRef s); 26 | 27 | // Write the contents of the a buffer to a file 28 | void saveBuffer(llvm::StringRef buffer, const llvm::Twine &path); 29 | 30 | // A single pattern to match against. A pattern can either be double-quoted 31 | // text that should be matched exactly after removing the quoting marks or a 32 | // glob pattern in the sense of GlobPattern. 33 | class SingleStringMatcher { 34 | public: 35 | // Create a StringPattern from Pattern to be matched exactly irregardless 36 | // of globbing characters if ExactMatch is true. 37 | SingleStringMatcher(llvm::StringRef Pattern); 38 | 39 | // Match s against this pattern, exactly if ExactMatch is true. 40 | bool match(llvm::StringRef s) const; 41 | 42 | private: 43 | // Whether to do an exact match irregardless of the presence of wildcard 44 | // character. 45 | bool ExactMatch; 46 | 47 | // GlobPattern object if not doing an exact match. 48 | llvm::GlobPattern GlobPatternMatcher; 49 | 50 | // StringRef to match exactly if doing an exact match. 51 | llvm::StringRef ExactPattern; 52 | }; 53 | 54 | // This class represents multiple patterns to match against. A pattern can 55 | // either be a double-quoted text that should be matched exactly after removing 56 | // the quoted marks or a glob pattern. 57 | class StringMatcher { 58 | private: 59 | // Patterns to match against. 60 | std::vector patterns; 61 | 62 | public: 63 | StringMatcher() = default; 64 | 65 | // Matcher for a single pattern. 66 | StringMatcher(llvm::StringRef Pattern) 67 | : patterns({SingleStringMatcher(Pattern)}) {} 68 | 69 | // Add a new pattern to the existing ones to match against. 70 | void addPattern(SingleStringMatcher Matcher) { patterns.push_back(Matcher); } 71 | 72 | bool empty() { return patterns.empty(); } 73 | 74 | // Match s against the patterns. 75 | bool match(llvm::StringRef s) const; 76 | }; 77 | 78 | } // namespace lld 79 | 80 | #endif 81 | -------------------------------------------------------------------------------- /include/lld/Common/Threads.h: -------------------------------------------------------------------------------- 1 | //===- Threads.h ------------------------------------------------*- C++ -*-===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // 9 | // LLD supports threads to distribute workloads to multiple cores. Using 10 | // multicore is most effective when more than one core are idle. At the 11 | // last step of a build, it is often the case that a linker is the only 12 | // active process on a computer. So, we are naturally interested in using 13 | // threads wisely to reduce latency to deliver results to users. 14 | // 15 | // That said, we don't want to do "too clever" things using threads. 16 | // Complex multi-threaded algorithms are sometimes extremely hard to 17 | // reason about and can easily mess up the entire design. 18 | // 19 | // Fortunately, when a linker links large programs (when the link time is 20 | // most critical), it spends most of the time to work on massive number of 21 | // small pieces of data of the same kind, and there are opportunities for 22 | // large parallelism there. Here are examples: 23 | // 24 | // - We have hundreds of thousands of input sections that need to be 25 | // copied to a result file at the last step of link. Once we fix a file 26 | // layout, each section can be copied to its destination and its 27 | // relocations can be applied independently. 28 | // 29 | // - We have tens of millions of small strings when constructing a 30 | // mergeable string section. 31 | // 32 | // For the cases such as the former, we can just use parallelForEach 33 | // instead of std::for_each (or a plain for loop). Because tasks are 34 | // completely independent from each other, we can run them in parallel 35 | // without any coordination between them. That's very easy to understand 36 | // and reason about. 37 | // 38 | // For the cases such as the latter, we can use parallel algorithms to 39 | // deal with massive data. We have to write code for a tailored algorithm 40 | // for each problem, but the complexity of multi-threading is isolated in 41 | // a single pass and doesn't affect the linker's overall design. 42 | // 43 | // The above approach seems to be working fairly well. As an example, when 44 | // linking Chromium (output size 1.6 GB), using 4 cores reduces latency to 45 | // 75% compared to single core (from 12.66 seconds to 9.55 seconds) on my 46 | // Ivy Bridge Xeon 2.8 GHz machine. Using 40 cores reduces it to 63% (from 47 | // 12.66 seconds to 7.95 seconds). Because of the Amdahl's law, the 48 | // speedup is not linear, but as you add more cores, it gets faster. 49 | // 50 | // On a final note, if you are trying to optimize, keep the axiom "don't 51 | // guess, measure!" in mind. Some important passes of the linker are not 52 | // that slow. For example, resolving all symbols is not a very heavy pass, 53 | // although it would be very hard to parallelize it. You want to first 54 | // identify a slow pass and then optimize it. 55 | // 56 | //===----------------------------------------------------------------------===// 57 | 58 | #ifndef LLD_COMMON_THREADS_H 59 | #define LLD_COMMON_THREADS_H 60 | 61 | #include "llvm/Support/Parallel.h" 62 | #include 63 | 64 | namespace lld { 65 | 66 | template void parallelForEach(R &&range, FuncTy fn) { 67 | if (llvm::parallel::strategy.ThreadsRequested != 1) 68 | for_each(llvm::parallel::par, std::begin(range), std::end(range), fn); 69 | else 70 | for_each(llvm::parallel::seq, std::begin(range), std::end(range), fn); 71 | } 72 | 73 | inline void parallelForEachN(size_t begin, size_t end, 74 | llvm::function_ref fn) { 75 | if (llvm::parallel::strategy.ThreadsRequested != 1) 76 | for_each_n(llvm::parallel::par, begin, end, fn); 77 | else 78 | for_each_n(llvm::parallel::seq, begin, end, fn); 79 | } 80 | 81 | template void parallelSort(R &&range, FuncTy fn) { 82 | if (llvm::parallel::strategy.ThreadsRequested != 1) 83 | sort(llvm::parallel::par, std::begin(range), std::end(range), fn); 84 | else 85 | sort(llvm::parallel::seq, std::begin(range), std::end(range), fn); 86 | } 87 | 88 | } // namespace lld 89 | 90 | #endif 91 | -------------------------------------------------------------------------------- /include/lld/Common/Version.h: -------------------------------------------------------------------------------- 1 | //===- lld/Common/Version.h - LLD Version Number ----------------*- C++ -*-===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // 9 | // Defines a version-related utility function. 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #ifndef LLD_VERSION_H 14 | #define LLD_VERSION_H 15 | 16 | #include "lld/Common/Version.inc" 17 | #include "llvm/ADT/StringRef.h" 18 | 19 | namespace lld { 20 | /// Retrieves a string representing the complete lld version. 21 | std::string getLLDVersion(); 22 | } 23 | 24 | #endif // LLD_VERSION_H 25 | -------------------------------------------------------------------------------- /include/lld/Common/Version.inc.in: -------------------------------------------------------------------------------- 1 | #define LLD_VERSION_STRING "@LLD_VERSION@" 2 | -------------------------------------------------------------------------------- /tools/lld/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(LLVM_LINK_COMPONENTS 2 | Support 3 | ) 4 | 5 | add_lld_tool(lld 6 | lld.cpp 7 | ) 8 | 9 | target_link_libraries(lld 10 | PRIVATE 11 | lldCommon 12 | lldDriver 13 | lldELF 14 | ) 15 | 16 | install(TARGETS lld 17 | RUNTIME DESTINATION bin) 18 | 19 | if(NOT LLD_SYMLINKS_TO_CREATE) 20 | set(LLD_SYMLINKS_TO_CREATE ld.lld) 21 | endif() 22 | 23 | foreach(link ${LLD_SYMLINKS_TO_CREATE}) 24 | add_lld_symlink(${link} lld) 25 | endforeach() 26 | -------------------------------------------------------------------------------- /tools/lld/lld.cpp: -------------------------------------------------------------------------------- 1 | //===- tools/lld/lld.cpp - Linker Driver Dispatcher -----------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // 9 | // This file contains the main function of the lld executable. The main 10 | // function is a thin wrapper which dispatches to the platform specific 11 | // driver. 12 | // 13 | // lld is a single executable that contains four different linkers for ELF, 14 | // COFF, WebAssembly and Mach-O. The main function dispatches according to 15 | // argv[0] (i.e. command name). The most common name for each target is shown 16 | // below: 17 | // 18 | // - ld.lld: ELF (Unix) 19 | // - ld64: Mach-O (macOS) 20 | // - lld-link: COFF (Windows) 21 | // - ld-wasm: WebAssembly 22 | // 23 | // lld can be invoked as "lld" along with "-flavor" option. This is for 24 | // backward compatibility and not recommended. 25 | // 26 | //===----------------------------------------------------------------------===// 27 | 28 | #include "lld/Common/Driver.h" 29 | #include "lld/Common/Memory.h" 30 | #include "llvm/ADT/STLExtras.h" 31 | #include "llvm/ADT/SmallVector.h" 32 | #include "llvm/ADT/StringSwitch.h" 33 | #include "llvm/ADT/Triple.h" 34 | #include "llvm/ADT/Twine.h" 35 | #include "llvm/Support/CommandLine.h" 36 | #include "llvm/Support/Host.h" 37 | #include "llvm/Support/InitLLVM.h" 38 | #include "llvm/Support/Path.h" 39 | #include "llvm/Support/PluginLoader.h" 40 | #include 41 | 42 | using namespace lld; 43 | using namespace llvm; 44 | using namespace llvm::sys; 45 | 46 | // If this function returns true, lld calls _exit() so that it quickly 47 | // exits without invoking destructors of globally allocated objects. 48 | // 49 | // We don't want to do that if we are running tests though, because 50 | // doing that breaks leak sanitizer. So, lit sets this environment variable, 51 | // and we use it to detect whether we are running tests or not. 52 | static bool canExitEarly() { return StringRef(getenv("LLD_IN_TEST")) != "1"; } 53 | 54 | /// Universal linker main(). This linker emulates the gnu, darwin, or 55 | /// windows linker based on the argv[0] or -flavor option. 56 | int main(int argc, const char **argv) { 57 | InitLLVM x(argc, argv); 58 | 59 | std::vector args(argv, argv + argc); 60 | return !elf::link(args, canExitEarly(), llvm::outs(), llvm::errs()); 61 | } 62 | --------------------------------------------------------------------------------