Index: vendor/lld/dist/CMakeLists.txt =================================================================== --- vendor/lld/dist/CMakeLists.txt (revision 312963) +++ vendor/lld/dist/CMakeLists.txt (revision 312964) @@ -1,156 +1,157 @@ # Check if lld is built as a standalone project. if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) project(lld) cmake_minimum_required(VERSION 3.4.3) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(LLD_BUILT_STANDALONE TRUE) find_program(LLVM_CONFIG_PATH "llvm-config" DOC "Path to llvm-config binary") if(NOT LLVM_CONFIG_PATH) message(FATAL_ERROR "llvm-config not found: specify LLVM_CONFIG_PATH") endif() execute_process(COMMAND "${LLVM_CONFIG_PATH}" "--obj-root" "--includedir" "--cmakedir" RESULT_VARIABLE HAD_ERROR OUTPUT_VARIABLE LLVM_CONFIG_OUTPUT OUTPUT_STRIP_TRAILING_WHITESPACE) if(HAD_ERROR) message(FATAL_ERROR "llvm-config failed with status ${HAD_ERROR}") endif() string(REGEX REPLACE "[ \t]*[\r\n]+[ \t]*" ";" LLVM_CONFIG_OUTPUT "${LLVM_CONFIG_OUTPUT}") list(GET LLVM_CONFIG_OUTPUT 0 OBJ_ROOT) list(GET LLVM_CONFIG_OUTPUT 1 MAIN_INCLUDE_DIR) list(GET LLVM_CONFIG_OUTPUT 2 LLVM_CMAKE_PATH) set(LLVM_OBJ_ROOT ${OBJ_ROOT} CACHE PATH "path to LLVM build tree") set(LLVM_MAIN_INCLUDE_DIR ${MAIN_INCLUDE_DIR} CACHE PATH "path to llvm/include") file(TO_CMAKE_PATH ${LLVM_OBJ_ROOT} LLVM_BINARY_DIR) if(NOT EXISTS "${LLVM_CMAKE_PATH}/LLVMConfig.cmake") message(FATAL_ERROR "LLVMConfig.cmake not found") endif() include("${LLVM_CMAKE_PATH}/LLVMConfig.cmake") list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_PATH}") set(PACKAGE_VERSION "${LLVM_PACKAGE_VERSION}") include_directories("${LLVM_BINARY_DIR}/include" ${LLVM_INCLUDE_DIRS}) link_directories(${LLVM_LIBRARY_DIRS}) + set(LLVM_LIBRARY_OUTPUT_INTDIR ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/lib${LLVM_LIBDIR_SUFFIX}) set(LLVM_RUNTIME_OUTPUT_INTDIR ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin) find_program(LLVM_TABLEGEN_EXE "llvm-tblgen" ${LLVM_TOOLS_BINARY_DIR} NO_DEFAULT_PATH) include(AddLLVM) include(TableGen) include(HandleLLVMOptions) endif() set(LLD_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) set(LLD_INCLUDE_DIR ${LLD_SOURCE_DIR}/include ) set(LLD_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}) # Compute the LLD version from the LLVM version. string(REGEX MATCH "[0-9]+\\.[0-9]+(\\.[0-9]+)?" LLD_VERSION ${PACKAGE_VERSION}) message(STATUS "LLD version: ${LLD_VERSION}") string(REGEX REPLACE "([0-9]+)\\.[0-9]+(\\.[0-9]+)?" "\\1" LLD_VERSION_MAJOR ${LLD_VERSION}) string(REGEX REPLACE "[0-9]+\\.([0-9]+)(\\.[0-9]+)?" "\\1" LLD_VERSION_MINOR ${LLD_VERSION}) # Determine LLD revision and repository. # TODO: Figure out a way to get the revision and the repository on windows. if ( NOT CMAKE_SYSTEM_NAME MATCHES "Windows" ) execute_process(COMMAND ${CMAKE_SOURCE_DIR}/utils/GetSourceVersion ${LLD_SOURCE_DIR} OUTPUT_VARIABLE LLD_REVISION) execute_process(COMMAND ${CMAKE_SOURCE_DIR}/utils/GetRepositoryPath ${LLD_SOURCE_DIR} OUTPUT_VARIABLE LLD_REPOSITORY) if ( LLD_REPOSITORY ) # Replace newline characters with spaces string(REGEX REPLACE "(\r?\n)+" " " LLD_REPOSITORY ${LLD_REPOSITORY}) # Remove leading spaces STRING(REGEX REPLACE "^[ \t\r\n]+" "" LLD_REPOSITORY "${LLD_REPOSITORY}" ) # Remove trailing spaces string(REGEX REPLACE "(\ )+$" "" LLD_REPOSITORY ${LLD_REPOSITORY}) endif() if ( LLD_REVISION ) # Replace newline characters with spaces string(REGEX REPLACE "(\r?\n)+" " " LLD_REVISION ${LLD_REVISION}) # Remove leading spaces STRING(REGEX REPLACE "^[ \t\r\n]+" "" LLD_REVISION "${LLD_REVISION}" ) # Remove trailing spaces string(REGEX REPLACE "(\ )+$" "" LLD_REVISION ${LLD_REVISION}) endif() endif () # Configure the Version.inc file. configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/include/lld/Config/Version.inc.in ${CMAKE_CURRENT_BINARY_DIR}/include/lld/Config/Version.inc) if (CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR) message(FATAL_ERROR "In-source builds are not allowed. CMake would overwrite " "the makefiles distributed with LLVM. Please create a directory and run cmake " "from there, passing the path to this source directory as the last argument. " "This process created the file `CMakeCache.txt' and the directory " "`CMakeFiles'. Please delete them.") endif() list (APPEND CMAKE_MODULE_PATH "${LLD_SOURCE_DIR}/cmake/modules") include(AddLLD) option(LLD_USE_VTUNE "Enable VTune user task tracking." OFF) if (LLD_USE_VTUNE) find_package(VTune) if (VTUNE_FOUND) include_directories(${VTune_INCLUDE_DIRS}) list(APPEND LLVM_COMMON_LIBS ${VTune_LIBRARIES}) add_definitions(-DLLD_HAS_VTUNE) endif() endif() option(LLD_BUILD_TOOLS "Build the lld tools. If OFF, just generate build targets." ON) if (MSVC) add_definitions(-wd4530) # Suppress 'warning C4530: C++ exception handler used, but unwind semantics are not enabled.' add_definitions(-wd4062) # Suppress 'warning C4062: enumerator X in switch of enum Y is not handled' from system header. endif() include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/include ) if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY) install(DIRECTORY include/ DESTINATION include FILES_MATCHING PATTERN "*.h" PATTERN ".svn" EXCLUDE ) endif() add_subdirectory(lib) add_subdirectory(tools/lld) if (LLVM_INCLUDE_TESTS) add_subdirectory(test) add_subdirectory(unittests) endif() add_subdirectory(docs) add_subdirectory(COFF) add_subdirectory(ELF) Index: vendor/lld/dist/ELF/LinkerScript.cpp =================================================================== --- vendor/lld/dist/ELF/LinkerScript.cpp (revision 312963) +++ vendor/lld/dist/ELF/LinkerScript.cpp (revision 312964) @@ -1,1963 +1,1958 @@ //===- LinkerScript.cpp ---------------------------------------------------===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file contains the parser/evaluator of the linker script. // //===----------------------------------------------------------------------===// #include "LinkerScript.h" #include "Config.h" #include "Driver.h" #include "InputSection.h" #include "Memory.h" #include "OutputSections.h" #include "ScriptParser.h" #include "Strings.h" #include "SymbolTable.h" #include "Symbols.h" #include "SyntheticSections.h" #include "Target.h" #include "Writer.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/Casting.h" #include "llvm/Support/ELF.h" #include "llvm/Support/Endian.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/Path.h" #include #include #include #include #include #include #include #include #include #include using namespace llvm; using namespace llvm::ELF; using namespace llvm::object; using namespace llvm::support::endian; using namespace lld; using namespace lld::elf; LinkerScriptBase *elf::ScriptBase; ScriptConfiguration *elf::ScriptConfig; template static SymbolBody *addRegular(SymbolAssignment *Cmd) { uint8_t Visibility = Cmd->Hidden ? STV_HIDDEN : STV_DEFAULT; Symbol *Sym = Symtab::X->addUndefined( Cmd->Name, /*IsLocal=*/false, STB_GLOBAL, Visibility, /*Type*/ 0, /*CanOmitFromDynSym*/ false, /*File*/ nullptr); replaceBody>(Sym, Cmd->Name, /*IsLocal=*/false, Visibility, STT_NOTYPE, 0, 0, nullptr, nullptr); return Sym->body(); } template static SymbolBody *addSynthetic(SymbolAssignment *Cmd) { uint8_t Visibility = Cmd->Hidden ? STV_HIDDEN : STV_DEFAULT; const OutputSectionBase *Sec = ScriptConfig->HasSections ? nullptr : Cmd->Expression.Section(); Symbol *Sym = Symtab::X->addUndefined( Cmd->Name, /*IsLocal=*/false, STB_GLOBAL, Visibility, /*Type*/ 0, /*CanOmitFromDynSym*/ false, /*File*/ nullptr); replaceBody(Sym, Cmd->Name, 0, Sec); return Sym->body(); } static bool isUnderSysroot(StringRef Path) { if (Config->Sysroot == "") return false; for (; !Path.empty(); Path = sys::path::parent_path(Path)) if (sys::fs::equivalent(Config->Sysroot, Path)) return true; return false; } template static void assignSymbol(SymbolAssignment *Cmd) { // If there are sections, then let the value be assigned later in // `assignAddresses`. if (ScriptConfig->HasSections) return; uint64_t Value = Cmd->Expression(0); if (Cmd->Expression.IsAbsolute()) { cast>(Cmd->Sym)->Value = Value; } else { const OutputSectionBase *Sec = Cmd->Expression.Section(); if (Sec) cast(Cmd->Sym)->Value = Value - Sec->Addr; } } template static void addSymbol(SymbolAssignment *Cmd) { if (Cmd->Name == ".") return; // If a symbol was in PROVIDE(), we need to define it only when // it is a referenced undefined symbol. SymbolBody *B = Symtab::X->find(Cmd->Name); if (Cmd->Provide && (!B || B->isDefined())) return; // Otherwise, create a new symbol if one does not exist or an // undefined one does exist. if (Cmd->Expression.IsAbsolute()) Cmd->Sym = addRegular(Cmd); else Cmd->Sym = addSynthetic(Cmd); assignSymbol(Cmd); } bool SymbolAssignment::classof(const BaseCommand *C) { return C->Kind == AssignmentKind; } bool OutputSectionCommand::classof(const BaseCommand *C) { return C->Kind == OutputSectionKind; } bool InputSectionDescription::classof(const BaseCommand *C) { return C->Kind == InputSectionKind; } bool AssertCommand::classof(const BaseCommand *C) { return C->Kind == AssertKind; } bool BytesDataCommand::classof(const BaseCommand *C) { return C->Kind == BytesDataKind; } template LinkerScript::LinkerScript() = default; template LinkerScript::~LinkerScript() = default; template static StringRef basename(InputSectionBase *S) { if (S->getFile()) return sys::path::filename(S->getFile()->getName()); return ""; } template bool LinkerScript::shouldKeep(InputSectionBase *S) { for (InputSectionDescription *ID : Opt.KeptSections) if (ID->FilePat.match(basename(S))) for (SectionPattern &P : ID->SectionPatterns) if (P.SectionPat.match(S->Name)) return true; return false; } static bool comparePriority(InputSectionData *A, InputSectionData *B) { return getPriority(A->Name) < getPriority(B->Name); } static bool compareName(InputSectionData *A, InputSectionData *B) { return A->Name < B->Name; } static bool compareAlignment(InputSectionData *A, InputSectionData *B) { // ">" is not a mistake. Larger alignments are placed before smaller // alignments in order to reduce the amount of padding necessary. // This is compatible with GNU. return A->Alignment > B->Alignment; } static std::function getComparator(SortSectionPolicy K) { switch (K) { case SortSectionPolicy::Alignment: return compareAlignment; case SortSectionPolicy::Name: return compareName; case SortSectionPolicy::Priority: return comparePriority; default: llvm_unreachable("unknown sort policy"); } } template static bool matchConstraints(ArrayRef *> Sections, ConstraintKind Kind) { if (Kind == ConstraintKind::NoConstraint) return true; bool IsRW = llvm::any_of(Sections, [=](InputSectionData *Sec2) { auto *Sec = static_cast *>(Sec2); return Sec->Flags & SHF_WRITE; }); return (IsRW && Kind == ConstraintKind::ReadWrite) || (!IsRW && Kind == ConstraintKind::ReadOnly); } static void sortSections(InputSectionData **Begin, InputSectionData **End, SortSectionPolicy K) { if (K != SortSectionPolicy::Default && K != SortSectionPolicy::None) std::stable_sort(Begin, End, getComparator(K)); } // Compute and remember which sections the InputSectionDescription matches. template void LinkerScript::computeInputSections(InputSectionDescription *I) { // Collects all sections that satisfy constraints of I // and attach them to I. for (SectionPattern &Pat : I->SectionPatterns) { size_t SizeBefore = I->Sections.size(); for (InputSectionBase *S : Symtab::X->Sections) { if (!S->Live || S->Assigned) continue; StringRef Filename = basename(S); if (!I->FilePat.match(Filename) || Pat.ExcludedFilePat.match(Filename)) continue; if (!Pat.SectionPat.match(S->Name)) continue; I->Sections.push_back(S); S->Assigned = true; } // Sort sections as instructed by SORT-family commands and --sort-section // option. Because SORT-family commands can be nested at most two depth // (e.g. SORT_BY_NAME(SORT_BY_ALIGNMENT(.text.*))) and because the command // line option is respected even if a SORT command is given, the exact // behavior we have here is a bit complicated. Here are the rules. // // 1. If two SORT commands are given, --sort-section is ignored. // 2. If one SORT command is given, and if it is not SORT_NONE, // --sort-section is handled as an inner SORT command. // 3. If one SORT command is given, and if it is SORT_NONE, don't sort. // 4. If no SORT command is given, sort according to --sort-section. InputSectionData **Begin = I->Sections.data() + SizeBefore; InputSectionData **End = I->Sections.data() + I->Sections.size(); if (Pat.SortOuter != SortSectionPolicy::None) { if (Pat.SortInner == SortSectionPolicy::Default) sortSections(Begin, End, Config->SortSection); else sortSections(Begin, End, Pat.SortInner); sortSections(Begin, End, Pat.SortOuter); } } } template void LinkerScript::discard(ArrayRef *> V) { for (InputSectionBase *S : V) { S->Live = false; reportDiscarded(S); } } template std::vector *> LinkerScript::createInputSectionList(OutputSectionCommand &OutCmd) { std::vector *> Ret; for (const std::unique_ptr &Base : OutCmd.Commands) { auto *Cmd = dyn_cast(Base.get()); if (!Cmd) continue; computeInputSections(Cmd); for (InputSectionData *S : Cmd->Sections) Ret.push_back(static_cast *>(S)); } return Ret; } template void LinkerScript::addSection(OutputSectionFactory &Factory, InputSectionBase *Sec, StringRef Name) { OutputSectionBase *OutSec; bool IsNew; std::tie(OutSec, IsNew) = Factory.create(Sec, Name); if (IsNew) OutputSections->push_back(OutSec); OutSec->addSection(Sec); } template void LinkerScript::processCommands(OutputSectionFactory &Factory) { for (unsigned I = 0; I < Opt.Commands.size(); ++I) { auto Iter = Opt.Commands.begin() + I; const std::unique_ptr &Base1 = *Iter; // Handle symbol assignments outside of any output section. if (auto *Cmd = dyn_cast(Base1.get())) { addSymbol(Cmd); continue; } if (auto *Cmd = dyn_cast(Base1.get())) { // If we don't have SECTIONS then output sections have already been // created by Writer. The LinkerScript::assignAddresses // will not be called, so ASSERT should be evaluated now. if (!Opt.HasSections) Cmd->Expression(0); continue; } if (auto *Cmd = dyn_cast(Base1.get())) { std::vector *> V = createInputSectionList(*Cmd); // The output section name `/DISCARD/' is special. // Any input section assigned to it is discarded. if (Cmd->Name == "/DISCARD/") { discard(V); continue; } // This is for ONLY_IF_RO and ONLY_IF_RW. An output section directive // ".foo : ONLY_IF_R[OW] { ... }" is handled only if all member input // sections satisfy a given constraint. If not, a directive is handled // as if it wasn't present from the beginning. // // Because we'll iterate over Commands many more times, the easiest // way to "make it as if it wasn't present" is to just remove it. if (!matchConstraints(V, Cmd->Constraint)) { for (InputSectionBase *S : V) S->Assigned = false; Opt.Commands.erase(Iter); --I; continue; } // A directive may contain symbol definitions like this: // ".foo : { ...; bar = .; }". Handle them. for (const std::unique_ptr &Base : Cmd->Commands) if (auto *OutCmd = dyn_cast(Base.get())) addSymbol(OutCmd); // Handle subalign (e.g. ".foo : SUBALIGN(32) { ... }"). If subalign // is given, input sections are aligned to that value, whether the // given value is larger or smaller than the original section alignment. if (Cmd->SubalignExpr) { uint32_t Subalign = Cmd->SubalignExpr(0); for (InputSectionBase *S : V) S->Alignment = Subalign; } // Add input sections to an output section. for (InputSectionBase *S : V) addSection(Factory, S, Cmd->Name); } } } // Add sections that didn't match any sections command. template void LinkerScript::addOrphanSections( OutputSectionFactory &Factory) { for (InputSectionBase *S : Symtab::X->Sections) if (S->Live && !S->OutSec) addSection(Factory, S, getOutputSectionName(S->Name)); } // Sets value of a section-defined symbol. Two kinds of // symbols are processed: synthetic symbols, whose value // is an offset from beginning of section and regular // symbols whose value is absolute. template static void assignSectionSymbol(SymbolAssignment *Cmd, typename ELFT::uint Value) { if (!Cmd->Sym) return; if (auto *Body = dyn_cast(Cmd->Sym)) { Body->Section = Cmd->Expression.Section(); Body->Value = Cmd->Expression(Value) - Body->Section->Addr; return; } auto *Body = cast>(Cmd->Sym); Body->Value = Cmd->Expression(Value); } template static bool isTbss(OutputSectionBase *Sec) { return (Sec->Flags & SHF_TLS) && Sec->Type == SHT_NOBITS; } template void LinkerScript::output(InputSection *S) { if (!AlreadyOutputIS.insert(S).second) return; bool IsTbss = isTbss(CurOutSec); uintX_t Pos = IsTbss ? Dot + ThreadBssOffset : Dot; Pos = alignTo(Pos, S->Alignment); S->OutSecOff = Pos - CurOutSec->Addr; Pos += S->getSize(); // Update output section size after adding each section. This is so that // SIZEOF works correctly in the case below: // .foo { *(.aaa) a = SIZEOF(.foo); *(.bbb) } CurOutSec->Size = Pos - CurOutSec->Addr; if (IsTbss) ThreadBssOffset = Pos - Dot; else Dot = Pos; } template void LinkerScript::flush() { if (!CurOutSec || !AlreadyOutputOS.insert(CurOutSec).second) return; if (auto *OutSec = dyn_cast>(CurOutSec)) { for (InputSection *I : OutSec->Sections) output(I); } else { Dot += CurOutSec->Size; } } template void LinkerScript::switchTo(OutputSectionBase *Sec) { if (CurOutSec == Sec) return; if (AlreadyOutputOS.count(Sec)) return; flush(); CurOutSec = Sec; Dot = alignTo(Dot, CurOutSec->Addralign); CurOutSec->Addr = isTbss(CurOutSec) ? Dot + ThreadBssOffset : Dot; // If neither AT nor AT> is specified for an allocatable section, the linker // will set the LMA such that the difference between VMA and LMA for the // section is the same as the preceding output section in the same region // https://sourceware.org/binutils/docs-2.20/ld/Output-Section-LMA.html CurOutSec->setLMAOffset(LMAOffset); } template void LinkerScript::process(BaseCommand &Base) { // This handles the assignments to symbol or to a location counter (.) if (auto *AssignCmd = dyn_cast(&Base)) { if (AssignCmd->Name == ".") { // Update to location counter means update to section size. uintX_t Val = AssignCmd->Expression(Dot); if (Val < Dot) error("unable to move location counter backward for: " + CurOutSec->Name); Dot = Val; CurOutSec->Size = Dot - CurOutSec->Addr; return; } assignSectionSymbol(AssignCmd, Dot); return; } // Handle BYTE(), SHORT(), LONG(), or QUAD(). if (auto *DataCmd = dyn_cast(&Base)) { DataCmd->Offset = Dot - CurOutSec->Addr; Dot += DataCmd->Size; CurOutSec->Size = Dot - CurOutSec->Addr; return; } if (auto *AssertCmd = dyn_cast(&Base)) { AssertCmd->Expression(Dot); return; } // It handles single input section description command, // calculates and assigns the offsets for each section and also // updates the output section size. auto &ICmd = cast(Base); for (InputSectionData *ID : ICmd.Sections) { // We tentatively added all synthetic sections at the beginning and removed // empty ones afterwards (because there is no way to know whether they were // going be empty or not other than actually running linker scripts.) // We need to ignore remains of empty sections. if (auto *Sec = dyn_cast>(ID)) if (Sec->empty()) continue; auto *IB = static_cast *>(ID); switchTo(IB->OutSec); if (auto *I = dyn_cast>(IB)) output(I); else flush(); } } template static std::vector findSections(StringRef Name, const std::vector &Sections) { std::vector Ret; for (OutputSectionBase *Sec : Sections) if (Sec->getName() == Name) Ret.push_back(Sec); return Ret; } // This function assigns offsets to input sections and an output section // for a single sections command (e.g. ".text { *(.text); }"). template void LinkerScript::assignOffsets(OutputSectionCommand *Cmd) { if (Cmd->LMAExpr) LMAOffset = Cmd->LMAExpr(Dot) - Dot; std::vector Sections = findSections(Cmd->Name, *OutputSections); if (Sections.empty()) return; switchTo(Sections[0]); // Find the last section output location. We will output orphan sections // there so that end symbols point to the correct location. auto E = std::find_if(Cmd->Commands.rbegin(), Cmd->Commands.rend(), [](const std::unique_ptr &Cmd) { return !isa(*Cmd); }) .base(); for (auto I = Cmd->Commands.begin(); I != E; ++I) process(**I); for (OutputSectionBase *Base : Sections) switchTo(Base); flush(); std::for_each(E, Cmd->Commands.end(), [this](std::unique_ptr &B) { process(*B.get()); }); } template void LinkerScript::removeEmptyCommands() { // It is common practice to use very generic linker scripts. So for any // given run some of the output sections in the script will be empty. // We could create corresponding empty output sections, but that would // clutter the output. // We instead remove trivially empty sections. The bfd linker seems even // more aggressive at removing them. auto Pos = std::remove_if( Opt.Commands.begin(), Opt.Commands.end(), [&](const std::unique_ptr &Base) { if (auto *Cmd = dyn_cast(Base.get())) return findSections(Cmd->Name, *OutputSections).empty(); return false; }); Opt.Commands.erase(Pos, Opt.Commands.end()); } static bool isAllSectionDescription(const OutputSectionCommand &Cmd) { for (const std::unique_ptr &I : Cmd.Commands) if (!isa(*I)) return false; return true; } template void LinkerScript::adjustSectionsBeforeSorting() { // If the output section contains only symbol assignments, create a // corresponding output section. The bfd linker seems to only create them if // '.' is assigned to, but creating these section should not have any bad // consequeces and gives us a section to put the symbol in. uintX_t Flags = SHF_ALLOC; uint32_t Type = SHT_NOBITS; for (const std::unique_ptr &Base : Opt.Commands) { auto *Cmd = dyn_cast(Base.get()); if (!Cmd) continue; std::vector Secs = findSections(Cmd->Name, *OutputSections); if (!Secs.empty()) { Flags = Secs[0]->Flags; Type = Secs[0]->Type; continue; } if (isAllSectionDescription(*Cmd)) continue; auto *OutSec = make>(Cmd->Name, Type, Flags); OutputSections->push_back(OutSec); } } template void LinkerScript::adjustSectionsAfterSorting() { placeOrphanSections(); // If output section command doesn't specify any segments, // and we haven't previously assigned any section to segment, // then we simply assign section to the very first load segment. // Below is an example of such linker script: // PHDRS { seg PT_LOAD; } // SECTIONS { .aaa : { *(.aaa) } } std::vector DefPhdrs; auto FirstPtLoad = std::find_if(Opt.PhdrsCommands.begin(), Opt.PhdrsCommands.end(), [](const PhdrsCommand &Cmd) { return Cmd.Type == PT_LOAD; }); if (FirstPtLoad != Opt.PhdrsCommands.end()) DefPhdrs.push_back(FirstPtLoad->Name); // Walk the commands and propagate the program headers to commands that don't // explicitly specify them. for (const std::unique_ptr &Base : Opt.Commands) { auto *Cmd = dyn_cast(Base.get()); if (!Cmd) continue; if (Cmd->Phdrs.empty()) Cmd->Phdrs = DefPhdrs; else DefPhdrs = Cmd->Phdrs; } removeEmptyCommands(); } // When placing orphan sections, we want to place them after symbol assignments // so that an orphan after // begin_foo = .; // foo : { *(foo) } // end_foo = .; // doesn't break the intended meaning of the begin/end symbols. // We don't want to go over sections since Writer::sortSections is the // one in charge of deciding the order of the sections. // We don't want to go over alignments, since doing so in // rx_sec : { *(rx_sec) } // . = ALIGN(0x1000); // /* The RW PT_LOAD starts here*/ // rw_sec : { *(rw_sec) } // would mean that the RW PT_LOAD would become unaligned. static bool shouldSkip(const BaseCommand &Cmd) { if (isa(Cmd)) return false; const auto *Assign = dyn_cast(&Cmd); if (!Assign) return true; return Assign->Name != "."; } // Orphan sections are sections present in the input files which are not // explicitly placed into the output file by the linker script. This just // places them in the order already decided in OutputSections. template void LinkerScript::placeOrphanSections() { // The OutputSections are already in the correct order. // This loops creates or moves commands as needed so that they are in the // correct order. int CmdIndex = 0; // As a horrible special case, skip the first . assignment if it is before any // section. We do this because it is common to set a load address by starting // the script with ". = 0xabcd" and the expectation is that every section is // after that. auto FirstSectionOrDotAssignment = std::find_if(Opt.Commands.begin(), Opt.Commands.end(), [](const std::unique_ptr &Cmd) { if (isa(*Cmd)) return true; const auto *Assign = dyn_cast(Cmd.get()); if (!Assign) return false; return Assign->Name == "."; }); if (FirstSectionOrDotAssignment != Opt.Commands.end()) { CmdIndex = FirstSectionOrDotAssignment - Opt.Commands.begin(); if (isa(**FirstSectionOrDotAssignment)) ++CmdIndex; } for (OutputSectionBase *Sec : *OutputSections) { StringRef Name = Sec->getName(); // Find the last spot where we can insert a command and still get the // correct result. auto CmdIter = Opt.Commands.begin() + CmdIndex; auto E = Opt.Commands.end(); while (CmdIter != E && shouldSkip(**CmdIter)) { ++CmdIter; ++CmdIndex; } auto Pos = std::find_if(CmdIter, E, [&](const std::unique_ptr &Base) { auto *Cmd = dyn_cast(Base.get()); return Cmd && Cmd->Name == Name; }); if (Pos == E) { Opt.Commands.insert(CmdIter, llvm::make_unique(Name)); ++CmdIndex; continue; } // Continue from where we found it. CmdIndex = (Pos - Opt.Commands.begin()) + 1; } } template void LinkerScript::assignAddresses(std::vector &Phdrs) { // Assign addresses as instructed by linker script SECTIONS sub-commands. Dot = 0; for (const std::unique_ptr &Base : Opt.Commands) { if (auto *Cmd = dyn_cast(Base.get())) { if (Cmd->Name == ".") { Dot = Cmd->Expression(Dot); } else if (Cmd->Sym) { assignSectionSymbol(Cmd, Dot); } continue; } if (auto *Cmd = dyn_cast(Base.get())) { Cmd->Expression(Dot); continue; } auto *Cmd = cast(Base.get()); if (Cmd->AddrExpr) Dot = Cmd->AddrExpr(Dot); assignOffsets(Cmd); } uintX_t MinVA = std::numeric_limits::max(); for (OutputSectionBase *Sec : *OutputSections) { if (Sec->Flags & SHF_ALLOC) MinVA = std::min(MinVA, Sec->Addr); else Sec->Addr = 0; } uintX_t HeaderSize = getHeaderSize(); // If the linker script doesn't have PHDRS, add ElfHeader and ProgramHeaders // now that we know we have space. if (HeaderSize <= MinVA && !hasPhdrsCommands()) allocateHeaders(Phdrs, *OutputSections); // ELF and Program headers need to be right before the first section in // memory. Set their addresses accordingly. MinVA = alignDown(MinVA - HeaderSize, Config->MaxPageSize); Out::ElfHeader->Addr = MinVA; Out::ProgramHeaders->Addr = Out::ElfHeader->Size + MinVA; } // Creates program headers as instructed by PHDRS linker script command. template std::vector LinkerScript::createPhdrs() { std::vector Ret; // Process PHDRS and FILEHDR keywords because they are not // real output sections and cannot be added in the following loop. for (const PhdrsCommand &Cmd : Opt.PhdrsCommands) { Ret.emplace_back(Cmd.Type, Cmd.Flags == UINT_MAX ? PF_R : Cmd.Flags); PhdrEntry &Phdr = Ret.back(); if (Cmd.HasFilehdr) Phdr.add(Out::ElfHeader); if (Cmd.HasPhdrs) Phdr.add(Out::ProgramHeaders); if (Cmd.LMAExpr) { Phdr.p_paddr = Cmd.LMAExpr(0); Phdr.HasLMA = true; } } // Add output sections to program headers. for (OutputSectionBase *Sec : *OutputSections) { if (!(Sec->Flags & SHF_ALLOC)) break; // Assign headers specified by linker script for (size_t Id : getPhdrIndices(Sec->getName())) { Ret[Id].add(Sec); if (Opt.PhdrsCommands[Id].Flags == UINT_MAX) Ret[Id].p_flags |= Sec->getPhdrFlags(); } } return Ret; } template bool LinkerScript::ignoreInterpSection() { // Ignore .interp section in case we have PHDRS specification // and PT_INTERP isn't listed. return !Opt.PhdrsCommands.empty() && llvm::find_if(Opt.PhdrsCommands, [](const PhdrsCommand &Cmd) { return Cmd.Type == PT_INTERP; }) == Opt.PhdrsCommands.end(); } template uint32_t LinkerScript::getFiller(StringRef Name) { for (const std::unique_ptr &Base : Opt.Commands) if (auto *Cmd = dyn_cast(Base.get())) if (Cmd->Name == Name) return Cmd->Filler; return 0; } template static void writeInt(uint8_t *Buf, uint64_t Data, uint64_t Size) { const endianness E = ELFT::TargetEndianness; switch (Size) { case 1: *Buf = (uint8_t)Data; break; case 2: write16(Buf, Data); break; case 4: write32(Buf, Data); break; case 8: write64(Buf, Data); break; default: llvm_unreachable("unsupported Size argument"); } } template void LinkerScript::writeDataBytes(StringRef Name, uint8_t *Buf) { int I = getSectionIndex(Name); if (I == INT_MAX) return; auto *Cmd = dyn_cast(Opt.Commands[I].get()); for (const std::unique_ptr &Base : Cmd->Commands) if (auto *Data = dyn_cast(Base.get())) writeInt(Buf + Data->Offset, Data->Expression(0), Data->Size); } template bool LinkerScript::hasLMA(StringRef Name) { for (const std::unique_ptr &Base : Opt.Commands) if (auto *Cmd = dyn_cast(Base.get())) if (Cmd->LMAExpr && Cmd->Name == Name) return true; return false; } // Returns the index of the given section name in linker script // SECTIONS commands. Sections are laid out as the same order as they // were in the script. If a given name did not appear in the script, // it returns INT_MAX, so that it will be laid out at end of file. template int LinkerScript::getSectionIndex(StringRef Name) { for (int I = 0, E = Opt.Commands.size(); I != E; ++I) if (auto *Cmd = dyn_cast(Opt.Commands[I].get())) if (Cmd->Name == Name) return I; return INT_MAX; } template bool LinkerScript::hasPhdrsCommands() { return !Opt.PhdrsCommands.empty(); } template const OutputSectionBase *LinkerScript::getOutputSection(const Twine &Loc, StringRef Name) { static OutputSectionBase FakeSec("", 0, 0); for (OutputSectionBase *Sec : *OutputSections) if (Sec->getName() == Name) return Sec; error(Loc + ": undefined section " + Name); return &FakeSec; } // This function is essentially the same as getOutputSection(Name)->Size, // but it won't print out an error message if a given section is not found. // // Linker script does not create an output section if its content is empty. // We want to allow SIZEOF(.foo) where .foo is a section which happened to // be empty. That is why this function is different from getOutputSection(). template uint64_t LinkerScript::getOutputSectionSize(StringRef Name) { for (OutputSectionBase *Sec : *OutputSections) if (Sec->getName() == Name) return Sec->Size; return 0; } template uint64_t LinkerScript::getHeaderSize() { return elf::getHeaderSize(); } template uint64_t LinkerScript::getSymbolValue(const Twine &Loc, StringRef S) { if (SymbolBody *B = Symtab::X->find(S)) return B->getVA(); error(Loc + ": symbol not found: " + S); return 0; } template bool LinkerScript::isDefined(StringRef S) { return Symtab::X->find(S) != nullptr; } template bool LinkerScript::isAbsolute(StringRef S) { SymbolBody *Sym = Symtab::X->find(S); auto *DR = dyn_cast_or_null>(Sym); return DR && !DR->Section; } // Gets section symbol belongs to. Symbol "." doesn't belong to any // specific section but isn't absolute at the same time, so we try // to find suitable section for it as well. template const OutputSectionBase *LinkerScript::getSymbolSection(StringRef S) { SymbolBody *Sym = Symtab::X->find(S); if (!Sym) { if (OutputSections->empty()) return nullptr; return CurOutSec ? CurOutSec : (*OutputSections)[0]; } - if (auto *DR = dyn_cast_or_null>(Sym)) - return DR->Section ? DR->Section->OutSec : nullptr; - if (auto *DS = dyn_cast_or_null(Sym)) - return DS->Section; - - return nullptr; + return SymbolTableSection::getOutputSection(Sym); } // Returns indices of ELF headers containing specific section, identified // by Name. Each index is a zero based number of ELF header listed within // PHDRS {} script block. template std::vector LinkerScript::getPhdrIndices(StringRef SectionName) { for (const std::unique_ptr &Base : Opt.Commands) { auto *Cmd = dyn_cast(Base.get()); if (!Cmd || Cmd->Name != SectionName) continue; std::vector Ret; for (StringRef PhdrName : Cmd->Phdrs) Ret.push_back(getPhdrIndex(Cmd->Location, PhdrName)); return Ret; } return {}; } template size_t LinkerScript::getPhdrIndex(const Twine &Loc, StringRef PhdrName) { size_t I = 0; for (PhdrsCommand &Cmd : Opt.PhdrsCommands) { if (Cmd.Name == PhdrName) return I; ++I; } error(Loc + ": section header '" + PhdrName + "' is not listed in PHDRS"); return 0; } class elf::ScriptParser final : public ScriptParserBase { typedef void (ScriptParser::*Handler)(); public: ScriptParser(MemoryBufferRef MB) : ScriptParserBase(MB), IsUnderSysroot(isUnderSysroot(MB.getBufferIdentifier())) {} void readLinkerScript(); void readVersionScript(); void readDynamicList(); private: void addFile(StringRef Path); void readAsNeeded(); void readEntry(); void readExtern(); void readGroup(); void readInclude(); void readOutput(); void readOutputArch(); void readOutputFormat(); void readPhdrs(); void readSearchDir(); void readSections(); void readVersion(); void readVersionScriptCommand(); SymbolAssignment *readAssignment(StringRef Name); BytesDataCommand *readBytesDataCommand(StringRef Tok); uint32_t readFill(); OutputSectionCommand *readOutputSectionDescription(StringRef OutSec); uint32_t readOutputSectionFiller(StringRef Tok); std::vector readOutputSectionPhdrs(); InputSectionDescription *readInputSectionDescription(StringRef Tok); StringMatcher readFilePatterns(); std::vector readInputSectionsList(); InputSectionDescription *readInputSectionRules(StringRef FilePattern); unsigned readPhdrType(); SortSectionPolicy readSortKind(); SymbolAssignment *readProvideHidden(bool Provide, bool Hidden); SymbolAssignment *readProvideOrAssignment(StringRef Tok); void readSort(); Expr readAssert(); Expr readExpr(); Expr readExpr1(Expr Lhs, int MinPrec); StringRef readParenLiteral(); Expr readPrimary(); Expr readTernary(Expr Cond); Expr readParenExpr(); // For parsing version script. std::vector readVersionExtern(); void readAnonymousDeclaration(); void readVersionDeclaration(StringRef VerStr); std::vector readSymbols(); void readLocals(); ScriptConfiguration &Opt = *ScriptConfig; bool IsUnderSysroot; }; void ScriptParser::readDynamicList() { expect("{"); readAnonymousDeclaration(); if (!atEOF()) setError("EOF expected, but got " + next()); } void ScriptParser::readVersionScript() { readVersionScriptCommand(); if (!atEOF()) setError("EOF expected, but got " + next()); } void ScriptParser::readVersionScriptCommand() { if (consume("{")) { readAnonymousDeclaration(); return; } while (!atEOF() && !Error && peek() != "}") { StringRef VerStr = next(); if (VerStr == "{") { setError("anonymous version definition is used in " "combination with other version definitions"); return; } expect("{"); readVersionDeclaration(VerStr); } } void ScriptParser::readVersion() { expect("{"); readVersionScriptCommand(); expect("}"); } void ScriptParser::readLinkerScript() { while (!atEOF()) { StringRef Tok = next(); if (Tok == ";") continue; if (Tok == "ASSERT") { Opt.Commands.emplace_back(new AssertCommand(readAssert())); } else if (Tok == "ENTRY") { readEntry(); } else if (Tok == "EXTERN") { readExtern(); } else if (Tok == "GROUP" || Tok == "INPUT") { readGroup(); } else if (Tok == "INCLUDE") { readInclude(); } else if (Tok == "OUTPUT") { readOutput(); } else if (Tok == "OUTPUT_ARCH") { readOutputArch(); } else if (Tok == "OUTPUT_FORMAT") { readOutputFormat(); } else if (Tok == "PHDRS") { readPhdrs(); } else if (Tok == "SEARCH_DIR") { readSearchDir(); } else if (Tok == "SECTIONS") { readSections(); } else if (Tok == "VERSION") { readVersion(); } else if (SymbolAssignment *Cmd = readProvideOrAssignment(Tok)) { Opt.Commands.emplace_back(Cmd); } else { setError("unknown directive: " + Tok); } } } void ScriptParser::addFile(StringRef S) { if (IsUnderSysroot && S.startswith("/")) { SmallString<128> PathData; StringRef Path = (Config->Sysroot + S).toStringRef(PathData); if (sys::fs::exists(Path)) { Driver->addFile(Saver.save(Path)); return; } } if (sys::path::is_absolute(S)) { Driver->addFile(S); } else if (S.startswith("=")) { if (Config->Sysroot.empty()) Driver->addFile(S.substr(1)); else Driver->addFile(Saver.save(Config->Sysroot + "/" + S.substr(1))); } else if (S.startswith("-l")) { Driver->addLibrary(S.substr(2)); } else if (sys::fs::exists(S)) { Driver->addFile(S); } else { if (Optional Path = findFromSearchPaths(S)) Driver->addFile(Saver.save(*Path)); else setError("unable to find " + S); } } void ScriptParser::readAsNeeded() { expect("("); bool Orig = Config->AsNeeded; Config->AsNeeded = true; while (!Error && !consume(")")) addFile(unquote(next())); Config->AsNeeded = Orig; } void ScriptParser::readEntry() { // -e takes predecence over ENTRY(). expect("("); StringRef Tok = next(); if (Config->Entry.empty()) Config->Entry = Tok; expect(")"); } void ScriptParser::readExtern() { expect("("); while (!Error && !consume(")")) Config->Undefined.push_back(next()); } void ScriptParser::readGroup() { expect("("); while (!Error && !consume(")")) { StringRef Tok = next(); if (Tok == "AS_NEEDED") readAsNeeded(); else addFile(unquote(Tok)); } } void ScriptParser::readInclude() { StringRef Tok = unquote(next()); // https://sourceware.org/binutils/docs/ld/File-Commands.html: // The file will be searched for in the current directory, and in any // directory specified with the -L option. if (sys::fs::exists(Tok)) { if (Optional MB = readFile(Tok)) tokenize(*MB); return; } if (Optional Path = findFromSearchPaths(Tok)) { if (Optional MB = readFile(*Path)) tokenize(*MB); return; } setError("cannot open " + Tok); } void ScriptParser::readOutput() { // -o takes predecence over OUTPUT(). expect("("); StringRef Tok = next(); if (Config->OutputFile.empty()) Config->OutputFile = unquote(Tok); expect(")"); } void ScriptParser::readOutputArch() { // Error checking only for now. expect("("); skip(); expect(")"); } void ScriptParser::readOutputFormat() { // Error checking only for now. expect("("); skip(); StringRef Tok = next(); if (Tok == ")") return; if (Tok != ",") { setError("unexpected token: " + Tok); return; } skip(); expect(","); skip(); expect(")"); } void ScriptParser::readPhdrs() { expect("{"); while (!Error && !consume("}")) { StringRef Tok = next(); Opt.PhdrsCommands.push_back( {Tok, PT_NULL, false, false, UINT_MAX, nullptr}); PhdrsCommand &PhdrCmd = Opt.PhdrsCommands.back(); PhdrCmd.Type = readPhdrType(); do { Tok = next(); if (Tok == ";") break; if (Tok == "FILEHDR") PhdrCmd.HasFilehdr = true; else if (Tok == "PHDRS") PhdrCmd.HasPhdrs = true; else if (Tok == "AT") PhdrCmd.LMAExpr = readParenExpr(); else if (Tok == "FLAGS") { expect("("); // Passing 0 for the value of dot is a bit of a hack. It means that // we accept expressions like ".|1". PhdrCmd.Flags = readExpr()(0); expect(")"); } else setError("unexpected header attribute: " + Tok); } while (!Error); } } void ScriptParser::readSearchDir() { expect("("); StringRef Tok = next(); if (!Config->Nostdlib) Config->SearchPaths.push_back(unquote(Tok)); expect(")"); } void ScriptParser::readSections() { Opt.HasSections = true; // -no-rosegment is used to avoid placing read only non-executable sections in // their own segment. We do the same if SECTIONS command is present in linker // script. See comment for computeFlags(). Config->SingleRoRx = true; expect("{"); while (!Error && !consume("}")) { StringRef Tok = next(); BaseCommand *Cmd = readProvideOrAssignment(Tok); if (!Cmd) { if (Tok == "ASSERT") Cmd = new AssertCommand(readAssert()); else Cmd = readOutputSectionDescription(Tok); } Opt.Commands.emplace_back(Cmd); } } static int precedence(StringRef Op) { return StringSwitch(Op) .Cases("*", "/", 5) .Cases("+", "-", 4) .Cases("<<", ">>", 3) .Cases("<", "<=", ">", ">=", "==", "!=", 2) .Cases("&", "|", 1) .Default(-1); } StringMatcher ScriptParser::readFilePatterns() { std::vector V; while (!Error && !consume(")")) V.push_back(next()); return StringMatcher(V); } SortSectionPolicy ScriptParser::readSortKind() { if (consume("SORT") || consume("SORT_BY_NAME")) return SortSectionPolicy::Name; if (consume("SORT_BY_ALIGNMENT")) return SortSectionPolicy::Alignment; if (consume("SORT_BY_INIT_PRIORITY")) return SortSectionPolicy::Priority; if (consume("SORT_NONE")) return SortSectionPolicy::None; return SortSectionPolicy::Default; } // Method reads a list of sequence of excluded files and section globs given in // a following form: ((EXCLUDE_FILE(file_pattern+))? section_pattern+)+ // Example: *(.foo.1 EXCLUDE_FILE (*a.o) .foo.2 EXCLUDE_FILE (*b.o) .foo.3) // The semantics of that is next: // * Include .foo.1 from every file. // * Include .foo.2 from every file but a.o // * Include .foo.3 from every file but b.o std::vector ScriptParser::readInputSectionsList() { std::vector Ret; while (!Error && peek() != ")") { StringMatcher ExcludeFilePat; if (consume("EXCLUDE_FILE")) { expect("("); ExcludeFilePat = readFilePatterns(); } std::vector V; while (!Error && peek() != ")" && peek() != "EXCLUDE_FILE") V.push_back(next()); if (!V.empty()) Ret.push_back({std::move(ExcludeFilePat), StringMatcher(V)}); else setError("section pattern is expected"); } return Ret; } // Reads contents of "SECTIONS" directive. That directive contains a // list of glob patterns for input sections. The grammar is as follows. // // ::= // | "(" ")" // | "(" "(" ")" ")" // // ::= "SORT" | "SORT_BY_NAME" | "SORT_BY_ALIGNMENT" // | "SORT_BY_INIT_PRIORITY" | "SORT_NONE" // // is parsed by readInputSectionsList(). InputSectionDescription * ScriptParser::readInputSectionRules(StringRef FilePattern) { auto *Cmd = new InputSectionDescription(FilePattern); expect("("); while (!Error && !consume(")")) { SortSectionPolicy Outer = readSortKind(); SortSectionPolicy Inner = SortSectionPolicy::Default; std::vector V; if (Outer != SortSectionPolicy::Default) { expect("("); Inner = readSortKind(); if (Inner != SortSectionPolicy::Default) { expect("("); V = readInputSectionsList(); expect(")"); } else { V = readInputSectionsList(); } expect(")"); } else { V = readInputSectionsList(); } for (SectionPattern &Pat : V) { Pat.SortInner = Inner; Pat.SortOuter = Outer; } std::move(V.begin(), V.end(), std::back_inserter(Cmd->SectionPatterns)); } return Cmd; } InputSectionDescription * ScriptParser::readInputSectionDescription(StringRef Tok) { // Input section wildcard can be surrounded by KEEP. // https://sourceware.org/binutils/docs/ld/Input-Section-Keep.html#Input-Section-Keep if (Tok == "KEEP") { expect("("); StringRef FilePattern = next(); InputSectionDescription *Cmd = readInputSectionRules(FilePattern); expect(")"); Opt.KeptSections.push_back(Cmd); return Cmd; } return readInputSectionRules(Tok); } void ScriptParser::readSort() { expect("("); expect("CONSTRUCTORS"); expect(")"); } Expr ScriptParser::readAssert() { expect("("); Expr E = readExpr(); expect(","); StringRef Msg = unquote(next()); expect(")"); return [=](uint64_t Dot) { uint64_t V = E(Dot); if (!V) error(Msg); return V; }; } // Reads a FILL(expr) command. We handle the FILL command as an // alias for =fillexp section attribute, which is different from // what GNU linkers do. // https://sourceware.org/binutils/docs/ld/Output-Section-Data.html uint32_t ScriptParser::readFill() { expect("("); uint32_t V = readOutputSectionFiller(next()); expect(")"); expect(";"); return V; } OutputSectionCommand * ScriptParser::readOutputSectionDescription(StringRef OutSec) { OutputSectionCommand *Cmd = new OutputSectionCommand(OutSec); Cmd->Location = getCurrentLocation(); // Read an address expression. // https://sourceware.org/binutils/docs/ld/Output-Section-Address.html#Output-Section-Address if (peek() != ":") Cmd->AddrExpr = readExpr(); expect(":"); if (consume("AT")) Cmd->LMAExpr = readParenExpr(); if (consume("ALIGN")) Cmd->AlignExpr = readParenExpr(); if (consume("SUBALIGN")) Cmd->SubalignExpr = readParenExpr(); // Parse constraints. if (consume("ONLY_IF_RO")) Cmd->Constraint = ConstraintKind::ReadOnly; if (consume("ONLY_IF_RW")) Cmd->Constraint = ConstraintKind::ReadWrite; expect("{"); while (!Error && !consume("}")) { StringRef Tok = next(); if (SymbolAssignment *Assignment = readProvideOrAssignment(Tok)) { Cmd->Commands.emplace_back(Assignment); } else if (BytesDataCommand *Data = readBytesDataCommand(Tok)) { Cmd->Commands.emplace_back(Data); } else if (Tok == "ASSERT") { Cmd->Commands.emplace_back(new AssertCommand(readAssert())); expect(";"); } else if (Tok == "FILL") { Cmd->Filler = readFill(); } else if (Tok == "SORT") { readSort(); } else if (peek() == "(") { Cmd->Commands.emplace_back(readInputSectionDescription(Tok)); } else { setError("unknown command " + Tok); } } Cmd->Phdrs = readOutputSectionPhdrs(); if (consume("=")) Cmd->Filler = readOutputSectionFiller(next()); else if (peek().startswith("=")) Cmd->Filler = readOutputSectionFiller(next().drop_front()); return Cmd; } // Read "=" where is an octal/decimal/hexadecimal number. // https://sourceware.org/binutils/docs/ld/Output-Section-Fill.html // // ld.gold is not fully compatible with ld.bfd. ld.bfd handles // hexstrings as blobs of arbitrary sizes, while ld.gold handles them // as 32-bit big-endian values. We will do the same as ld.gold does // because it's simpler than what ld.bfd does. uint32_t ScriptParser::readOutputSectionFiller(StringRef Tok) { uint32_t V; if (!Tok.getAsInteger(0, V)) return V; setError("invalid filler expression: " + Tok); return 0; } SymbolAssignment *ScriptParser::readProvideHidden(bool Provide, bool Hidden) { expect("("); SymbolAssignment *Cmd = readAssignment(next()); Cmd->Provide = Provide; Cmd->Hidden = Hidden; expect(")"); expect(";"); return Cmd; } SymbolAssignment *ScriptParser::readProvideOrAssignment(StringRef Tok) { SymbolAssignment *Cmd = nullptr; if (peek() == "=" || peek() == "+=") { Cmd = readAssignment(Tok); expect(";"); } else if (Tok == "PROVIDE") { Cmd = readProvideHidden(true, false); } else if (Tok == "HIDDEN") { Cmd = readProvideHidden(false, true); } else if (Tok == "PROVIDE_HIDDEN") { Cmd = readProvideHidden(true, true); } return Cmd; } static uint64_t getSymbolValue(const Twine &Loc, StringRef S, uint64_t Dot) { if (S == ".") return Dot; return ScriptBase->getSymbolValue(Loc, S); } static bool isAbsolute(StringRef S) { if (S == ".") return false; return ScriptBase->isAbsolute(S); } SymbolAssignment *ScriptParser::readAssignment(StringRef Name) { StringRef Op = next(); Expr E; assert(Op == "=" || Op == "+="); if (consume("ABSOLUTE")) { // The RHS may be something like "ABSOLUTE(.) & 0xff". // Call readExpr1 to read the whole expression. E = readExpr1(readParenExpr(), 0); E.IsAbsolute = [] { return true; }; } else { E = readExpr(); } if (Op == "+=") { std::string Loc = getCurrentLocation(); E = [=](uint64_t Dot) { return getSymbolValue(Loc, Name, Dot) + E(Dot); }; } return new SymbolAssignment(Name, E); } // This is an operator-precedence parser to parse a linker // script expression. Expr ScriptParser::readExpr() { return readExpr1(readPrimary(), 0); } static Expr combine(StringRef Op, Expr L, Expr R) { if (Op == "*") return [=](uint64_t Dot) { return L(Dot) * R(Dot); }; if (Op == "/") { return [=](uint64_t Dot) -> uint64_t { uint64_t RHS = R(Dot); if (RHS == 0) { error("division by zero"); return 0; } return L(Dot) / RHS; }; } if (Op == "+") return {[=](uint64_t Dot) { return L(Dot) + R(Dot); }, [=] { return L.IsAbsolute() && R.IsAbsolute(); }, [=] { const OutputSectionBase *S = L.Section(); return S ? S : R.Section(); }}; if (Op == "-") return [=](uint64_t Dot) { return L(Dot) - R(Dot); }; if (Op == "<<") return [=](uint64_t Dot) { return L(Dot) << R(Dot); }; if (Op == ">>") return [=](uint64_t Dot) { return L(Dot) >> R(Dot); }; if (Op == "<") return [=](uint64_t Dot) { return L(Dot) < R(Dot); }; if (Op == ">") return [=](uint64_t Dot) { return L(Dot) > R(Dot); }; if (Op == ">=") return [=](uint64_t Dot) { return L(Dot) >= R(Dot); }; if (Op == "<=") return [=](uint64_t Dot) { return L(Dot) <= R(Dot); }; if (Op == "==") return [=](uint64_t Dot) { return L(Dot) == R(Dot); }; if (Op == "!=") return [=](uint64_t Dot) { return L(Dot) != R(Dot); }; if (Op == "&") return [=](uint64_t Dot) { return L(Dot) & R(Dot); }; if (Op == "|") return [=](uint64_t Dot) { return L(Dot) | R(Dot); }; llvm_unreachable("invalid operator"); } // This is a part of the operator-precedence parser. This function // assumes that the remaining token stream starts with an operator. Expr ScriptParser::readExpr1(Expr Lhs, int MinPrec) { while (!atEOF() && !Error) { // Read an operator and an expression. if (consume("?")) return readTernary(Lhs); StringRef Op1 = peek(); if (precedence(Op1) < MinPrec) break; skip(); Expr Rhs = readPrimary(); // Evaluate the remaining part of the expression first if the // next operator has greater precedence than the previous one. // For example, if we have read "+" and "3", and if the next // operator is "*", then we'll evaluate 3 * ... part first. while (!atEOF()) { StringRef Op2 = peek(); if (precedence(Op2) <= precedence(Op1)) break; Rhs = readExpr1(Rhs, precedence(Op2)); } Lhs = combine(Op1, Lhs, Rhs); } return Lhs; } uint64_t static getConstant(StringRef S) { if (S == "COMMONPAGESIZE") return Target->PageSize; if (S == "MAXPAGESIZE") return Config->MaxPageSize; error("unknown constant: " + S); return 0; } // Parses Tok as an integer. Returns true if successful. // It recognizes hexadecimal (prefixed with "0x" or suffixed with "H") // and decimal numbers. Decimal numbers may have "K" (kilo) or // "M" (mega) prefixes. static bool readInteger(StringRef Tok, uint64_t &Result) { // Negative number if (Tok.startswith("-")) { if (!readInteger(Tok.substr(1), Result)) return false; Result = -Result; return true; } // Hexadecimal if (Tok.startswith_lower("0x")) return !Tok.substr(2).getAsInteger(16, Result); if (Tok.endswith_lower("H")) return !Tok.drop_back().getAsInteger(16, Result); // Decimal int Suffix = 1; if (Tok.endswith_lower("K")) { Suffix = 1024; Tok = Tok.drop_back(); } else if (Tok.endswith_lower("M")) { Suffix = 1024 * 1024; Tok = Tok.drop_back(); } if (Tok.getAsInteger(10, Result)) return false; Result *= Suffix; return true; } BytesDataCommand *ScriptParser::readBytesDataCommand(StringRef Tok) { int Size = StringSwitch(Tok) .Case("BYTE", 1) .Case("SHORT", 2) .Case("LONG", 4) .Case("QUAD", 8) .Default(-1); if (Size == -1) return nullptr; return new BytesDataCommand(readParenExpr(), Size); } StringRef ScriptParser::readParenLiteral() { expect("("); StringRef Tok = next(); expect(")"); return Tok; } Expr ScriptParser::readPrimary() { if (peek() == "(") return readParenExpr(); StringRef Tok = next(); std::string Location = getCurrentLocation(); if (Tok == "~") { Expr E = readPrimary(); return [=](uint64_t Dot) { return ~E(Dot); }; } if (Tok == "-") { Expr E = readPrimary(); return [=](uint64_t Dot) { return -E(Dot); }; } // Built-in functions are parsed here. // https://sourceware.org/binutils/docs/ld/Builtin-Functions.html. if (Tok == "ADDR") { StringRef Name = readParenLiteral(); return {[=](uint64_t Dot) { return ScriptBase->getOutputSection(Location, Name)->Addr; }, [=] { return false; }, [=] { return ScriptBase->getOutputSection(Location, Name); }}; } if (Tok == "LOADADDR") { StringRef Name = readParenLiteral(); return [=](uint64_t Dot) { return ScriptBase->getOutputSection(Location, Name)->getLMA(); }; } if (Tok == "ASSERT") return readAssert(); if (Tok == "ALIGN") { expect("("); Expr E = readExpr(); if (consume(",")) { Expr E2 = readExpr(); expect(")"); return [=](uint64_t Dot) { return alignTo(E(Dot), E2(Dot)); }; } expect(")"); return [=](uint64_t Dot) { return alignTo(Dot, E(Dot)); }; } if (Tok == "CONSTANT") { StringRef Name = readParenLiteral(); return [=](uint64_t Dot) { return getConstant(Name); }; } if (Tok == "DEFINED") { StringRef Name = readParenLiteral(); return [=](uint64_t Dot) { return ScriptBase->isDefined(Name) ? 1 : 0; }; } if (Tok == "SEGMENT_START") { expect("("); skip(); expect(","); Expr E = readExpr(); expect(")"); return [=](uint64_t Dot) { return E(Dot); }; } if (Tok == "DATA_SEGMENT_ALIGN") { expect("("); Expr E = readExpr(); expect(","); readExpr(); expect(")"); return [=](uint64_t Dot) { return alignTo(Dot, E(Dot)); }; } if (Tok == "DATA_SEGMENT_END") { expect("("); expect("."); expect(")"); return [](uint64_t Dot) { return Dot; }; } // GNU linkers implements more complicated logic to handle // DATA_SEGMENT_RELRO_END. We instead ignore the arguments and just align to // the next page boundary for simplicity. if (Tok == "DATA_SEGMENT_RELRO_END") { expect("("); readExpr(); expect(","); readExpr(); expect(")"); return [](uint64_t Dot) { return alignTo(Dot, Target->PageSize); }; } if (Tok == "SIZEOF") { StringRef Name = readParenLiteral(); return [=](uint64_t Dot) { return ScriptBase->getOutputSectionSize(Name); }; } if (Tok == "ALIGNOF") { StringRef Name = readParenLiteral(); return [=](uint64_t Dot) { return ScriptBase->getOutputSection(Location, Name)->Addralign; }; } if (Tok == "SIZEOF_HEADERS") return [=](uint64_t Dot) { return ScriptBase->getHeaderSize(); }; // Tok is a literal number. uint64_t V; if (readInteger(Tok, V)) return [=](uint64_t Dot) { return V; }; // Tok is a symbol name. if (Tok != "." && !isValidCIdentifier(Tok)) setError("malformed number: " + Tok); return {[=](uint64_t Dot) { return getSymbolValue(Location, Tok, Dot); }, [=] { return isAbsolute(Tok); }, [=] { return ScriptBase->getSymbolSection(Tok); }}; } Expr ScriptParser::readTernary(Expr Cond) { Expr L = readExpr(); expect(":"); Expr R = readExpr(); return [=](uint64_t Dot) { return Cond(Dot) ? L(Dot) : R(Dot); }; } Expr ScriptParser::readParenExpr() { expect("("); Expr E = readExpr(); expect(")"); return E; } std::vector ScriptParser::readOutputSectionPhdrs() { std::vector Phdrs; while (!Error && peek().startswith(":")) { StringRef Tok = next(); Phdrs.push_back((Tok.size() == 1) ? next() : Tok.substr(1)); } return Phdrs; } // Read a program header type name. The next token must be a // name of a program header type or a constant (e.g. "0x3"). unsigned ScriptParser::readPhdrType() { StringRef Tok = next(); uint64_t Val; if (readInteger(Tok, Val)) return Val; unsigned Ret = StringSwitch(Tok) .Case("PT_NULL", PT_NULL) .Case("PT_LOAD", PT_LOAD) .Case("PT_DYNAMIC", PT_DYNAMIC) .Case("PT_INTERP", PT_INTERP) .Case("PT_NOTE", PT_NOTE) .Case("PT_SHLIB", PT_SHLIB) .Case("PT_PHDR", PT_PHDR) .Case("PT_TLS", PT_TLS) .Case("PT_GNU_EH_FRAME", PT_GNU_EH_FRAME) .Case("PT_GNU_STACK", PT_GNU_STACK) .Case("PT_GNU_RELRO", PT_GNU_RELRO) .Case("PT_OPENBSD_RANDOMIZE", PT_OPENBSD_RANDOMIZE) .Case("PT_OPENBSD_WXNEEDED", PT_OPENBSD_WXNEEDED) .Case("PT_OPENBSD_BOOTDATA", PT_OPENBSD_BOOTDATA) .Default(-1); if (Ret == (unsigned)-1) { setError("invalid program header type: " + Tok); return PT_NULL; } return Ret; } // Reads a list of symbols, e.g. "{ global: foo; bar; local: *; };". void ScriptParser::readAnonymousDeclaration() { // Read global symbols first. "global:" is default, so if there's // no label, we assume global symbols. if (consume("global:") || peek() != "local:") Config->VersionScriptGlobals = readSymbols(); readLocals(); expect("}"); expect(";"); } void ScriptParser::readLocals() { if (!consume("local:")) return; std::vector Locals = readSymbols(); for (SymbolVersion V : Locals) { if (V.Name == "*") { Config->DefaultSymbolVersion = VER_NDX_LOCAL; continue; } Config->VersionScriptLocals.push_back(V); } } // Reads a list of symbols, e.g. "VerStr { global: foo; bar; local: *; };". void ScriptParser::readVersionDeclaration(StringRef VerStr) { // Identifiers start at 2 because 0 and 1 are reserved // for VER_NDX_LOCAL and VER_NDX_GLOBAL constants. uint16_t VersionId = Config->VersionDefinitions.size() + 2; Config->VersionDefinitions.push_back({VerStr, VersionId}); // Read global symbols. if (consume("global:") || peek() != "local:") Config->VersionDefinitions.back().Globals = readSymbols(); readLocals(); expect("}"); // Each version may have a parent version. For example, "Ver2" // defined as "Ver2 { global: foo; local: *; } Ver1;" has "Ver1" // as a parent. This version hierarchy is, probably against your // instinct, purely for hint; the runtime doesn't care about it // at all. In LLD, we simply ignore it. if (peek() != ";") skip(); expect(";"); } // Reads a list of symbols for a versions cript. std::vector ScriptParser::readSymbols() { std::vector Ret; for (;;) { if (consume("extern")) { for (SymbolVersion V : readVersionExtern()) Ret.push_back(V); continue; } if (peek() == "}" || peek() == "local:" || Error) break; StringRef Tok = next(); Ret.push_back({unquote(Tok), false, hasWildcard(Tok)}); expect(";"); } return Ret; } // Reads an "extern C++" directive, e.g., // "extern "C++" { ns::*; "f(int, double)"; };" std::vector ScriptParser::readVersionExtern() { StringRef Tok = next(); bool IsCXX = Tok == "\"C++\""; if (!IsCXX && Tok != "\"C\"") setError("Unknown language"); expect("{"); std::vector Ret; while (!Error && peek() != "}") { StringRef Tok = next(); bool HasWildcard = !Tok.startswith("\"") && hasWildcard(Tok); Ret.push_back({unquote(Tok), IsCXX, HasWildcard}); expect(";"); } expect("}"); expect(";"); return Ret; } void elf::readLinkerScript(MemoryBufferRef MB) { ScriptParser(MB).readLinkerScript(); } void elf::readVersionScript(MemoryBufferRef MB) { ScriptParser(MB).readVersionScript(); } void elf::readDynamicList(MemoryBufferRef MB) { ScriptParser(MB).readDynamicList(); } template class elf::LinkerScript; template class elf::LinkerScript; template class elf::LinkerScript; template class elf::LinkerScript; Index: vendor/lld/dist/ELF/SyntheticSections.h =================================================================== --- vendor/lld/dist/ELF/SyntheticSections.h (revision 312963) +++ vendor/lld/dist/ELF/SyntheticSections.h (revision 312964) @@ -1,747 +1,747 @@ //===- SyntheticSection.h ---------------------------------------*- C++ -*-===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef LLD_ELF_SYNTHETIC_SECTION_H #define LLD_ELF_SYNTHETIC_SECTION_H #include "GdbIndex.h" #include "InputSection.h" #include "llvm/ADT/MapVector.h" #include "llvm/MC/StringTableBuilder.h" namespace lld { namespace elf { template class SyntheticSection : public InputSection { typedef typename ELFT::uint uintX_t; public: SyntheticSection(uintX_t Flags, uint32_t Type, uintX_t Addralign, StringRef Name) : InputSection(Flags, Type, Addralign, ArrayRef(), Name, InputSectionData::Synthetic) { this->Live = true; } virtual ~SyntheticSection() = default; virtual void writeTo(uint8_t *Buf) = 0; virtual size_t getSize() const = 0; virtual void finalize() {} virtual bool empty() const { return false; } uintX_t getVA() const { return this->OutSec ? this->OutSec->Addr + this->OutSecOff : 0; } static bool classof(const InputSectionData *D) { return D->kind() == InputSectionData::Synthetic; } }; template class GotSection final : public SyntheticSection { typedef typename ELFT::uint uintX_t; public: GotSection(); void writeTo(uint8_t *Buf) override; size_t getSize() const override { return Size; } void finalize() override; bool empty() const override; void addEntry(SymbolBody &Sym); bool addDynTlsEntry(SymbolBody &Sym); bool addTlsIndex(); uintX_t getGlobalDynAddr(const SymbolBody &B) const; uintX_t getGlobalDynOffset(const SymbolBody &B) const; uintX_t getTlsIndexVA() { return this->getVA() + TlsIndexOff; } uint32_t getTlsIndexOff() const { return TlsIndexOff; } // Flag to force GOT to be in output if we have relocations // that relies on its address. bool HasGotOffRel = false; private: size_t NumEntries = 0; uint32_t TlsIndexOff = -1; uintX_t Size = 0; }; // .note.gnu.build-id section. template class BuildIdSection : public SyntheticSection { // First 16 bytes are a header. static const unsigned HeaderSize = 16; public: BuildIdSection(); void writeTo(uint8_t *Buf) override; size_t getSize() const override { return HeaderSize + HashSize; } void writeBuildId(llvm::ArrayRef Buf); private: void computeHash(llvm::ArrayRef Buf, std::function)> Hash); size_t HashSize; uint8_t *HashBuf; }; template class MipsGotSection final : public SyntheticSection { typedef typename ELFT::uint uintX_t; public: MipsGotSection(); void writeTo(uint8_t *Buf) override; size_t getSize() const override { return Size; } void finalize() override; bool empty() const override; void addEntry(SymbolBody &Sym, uintX_t Addend, RelExpr Expr); bool addDynTlsEntry(SymbolBody &Sym); bool addTlsIndex(); uintX_t getPageEntryOffset(const SymbolBody &B, uintX_t Addend) const; uintX_t getBodyEntryOffset(const SymbolBody &B, uintX_t Addend) const; uintX_t getGlobalDynOffset(const SymbolBody &B) const; // Returns the symbol which corresponds to the first entry of the global part // of GOT on MIPS platform. It is required to fill up MIPS-specific dynamic // table properties. // Returns nullptr if the global part is empty. const SymbolBody *getFirstGlobalEntry() const; // Returns the number of entries in the local part of GOT including // the number of reserved entries. unsigned getLocalEntriesNum() const; // Returns offset of TLS part of the MIPS GOT table. This part goes // after 'local' and 'global' entries. uintX_t getTlsOffset() const; uint32_t getTlsIndexOff() const { return TlsIndexOff; } uintX_t getGp() const; private: // MIPS GOT consists of three parts: local, global and tls. Each part // contains different types of entries. Here is a layout of GOT: // - Header entries | // - Page entries | Local part // - Local entries (16-bit access) | // - Local entries (32-bit access) | // - Normal global entries || Global part // - Reloc-only global entries || // - TLS entries ||| TLS part // // Header: // Two entries hold predefined value 0x0 and 0x80000000. // Page entries: // These entries created by R_MIPS_GOT_PAGE relocation and R_MIPS_GOT16 // relocation against local symbols. They are initialized by higher 16-bit // of the corresponding symbol's value. So each 64kb of address space // requires a single GOT entry. // Local entries (16-bit access): // These entries created by GOT relocations against global non-preemptible // symbols so dynamic linker is not necessary to resolve the symbol's // values. "16-bit access" means that corresponding relocations address // GOT using 16-bit index. Each unique Symbol-Addend pair has its own // GOT entry. // Local entries (32-bit access): // These entries are the same as above but created by relocations which // address GOT using 32-bit index (R_MIPS_GOT_HI16/LO16 etc). // Normal global entries: // These entries created by GOT relocations against preemptible global // symbols. They need to be initialized by dynamic linker and they ordered // exactly as the corresponding entries in the dynamic symbols table. // Reloc-only global entries: // These entries created for symbols that are referenced by dynamic // relocations R_MIPS_REL32. These entries are not accessed with gp-relative // addressing, but MIPS ABI requires that these entries be present in GOT. // TLS entries: // Entries created by TLS relocations. // Number of "Header" entries. static const unsigned HeaderEntriesNum = 2; // Number of allocated "Page" entries. uint32_t PageEntriesNum = 0; // Map output sections referenced by MIPS GOT relocations // to the first index of "Page" entries allocated for this section. llvm::SmallMapVector PageIndexMap; typedef std::pair GotEntry; typedef std::vector GotEntries; // Map from Symbol-Addend pair to the GOT index. llvm::DenseMap EntryIndexMap; // Local entries (16-bit access). GotEntries LocalEntries; // Local entries (32-bit access). GotEntries LocalEntries32; // Normal and reloc-only global entries. GotEntries GlobalEntries; // TLS entries. std::vector TlsEntries; uint32_t TlsIndexOff = -1; uintX_t Size = 0; }; template class GotPltSection final : public SyntheticSection { typedef typename ELFT::uint uintX_t; public: GotPltSection(); void addEntry(SymbolBody &Sym); size_t getSize() const override; void writeTo(uint8_t *Buf) override; bool empty() const override { return Entries.empty(); } private: std::vector Entries; }; // The IgotPltSection is a Got associated with the IpltSection for GNU Ifunc // Symbols that will be relocated by Target->IRelativeRel. // On most Targets the IgotPltSection will immediately follow the GotPltSection // on ARM the IgotPltSection will immediately follow the GotSection. template class IgotPltSection final : public SyntheticSection { typedef typename ELFT::uint uintX_t; public: IgotPltSection(); void addEntry(SymbolBody &Sym); size_t getSize() const override; void writeTo(uint8_t *Buf) override; bool empty() const override { return Entries.empty(); } private: std::vector Entries; }; template class StringTableSection final : public SyntheticSection { public: typedef typename ELFT::uint uintX_t; StringTableSection(StringRef Name, bool Dynamic); unsigned addString(StringRef S, bool HashIt = true); void writeTo(uint8_t *Buf) override; size_t getSize() const override { return Size; } bool isDynamic() const { return Dynamic; } private: const bool Dynamic; // ELF string tables start with a NUL byte, so 1. uintX_t Size = 1; llvm::DenseMap StringMap; std::vector Strings; }; template class DynamicReloc { typedef typename ELFT::uint uintX_t; public: DynamicReloc(uint32_t Type, const InputSectionBase *InputSec, uintX_t OffsetInSec, bool UseSymVA, SymbolBody *Sym, uintX_t Addend) : Type(Type), Sym(Sym), InputSec(InputSec), OffsetInSec(OffsetInSec), UseSymVA(UseSymVA), Addend(Addend) {} DynamicReloc(uint32_t Type, const OutputSectionBase *OutputSec, uintX_t OffsetInSec, bool UseSymVA, SymbolBody *Sym, uintX_t Addend) : Type(Type), Sym(Sym), OutputSec(OutputSec), OffsetInSec(OffsetInSec), UseSymVA(UseSymVA), Addend(Addend) {} uintX_t getOffset() const; uintX_t getAddend() const; uint32_t getSymIndex() const; const OutputSectionBase *getOutputSec() const { return OutputSec; } const InputSectionBase *getInputSec() const { return InputSec; } uint32_t Type; private: SymbolBody *Sym; const InputSectionBase *InputSec = nullptr; const OutputSectionBase *OutputSec = nullptr; uintX_t OffsetInSec; bool UseSymVA; uintX_t Addend; }; template class DynamicSection final : public SyntheticSection { typedef typename ELFT::Dyn Elf_Dyn; typedef typename ELFT::Rel Elf_Rel; typedef typename ELFT::Rela Elf_Rela; typedef typename ELFT::Shdr Elf_Shdr; typedef typename ELFT::Sym Elf_Sym; typedef typename ELFT::uint uintX_t; // The .dynamic section contains information for the dynamic linker. // The section consists of fixed size entries, which consist of // type and value fields. Value are one of plain integers, symbol // addresses, or section addresses. This struct represents the entry. struct Entry { int32_t Tag; union { OutputSectionBase *OutSec; InputSection *InSec; uint64_t Val; const SymbolBody *Sym; }; enum KindT { SecAddr, SecSize, SymAddr, PlainInt, InSecAddr } Kind; Entry(int32_t Tag, OutputSectionBase *OutSec, KindT Kind = SecAddr) : Tag(Tag), OutSec(OutSec), Kind(Kind) {} Entry(int32_t Tag, InputSection *Sec) : Tag(Tag), InSec(Sec), Kind(InSecAddr) {} Entry(int32_t Tag, uint64_t Val) : Tag(Tag), Val(Val), Kind(PlainInt) {} Entry(int32_t Tag, const SymbolBody *Sym) : Tag(Tag), Sym(Sym), Kind(SymAddr) {} }; // finalize() fills this vector with the section contents. finalize() // cannot directly create final section contents because when the // function is called, symbol or section addresses are not fixed yet. std::vector Entries; public: DynamicSection(); void finalize() override; void writeTo(uint8_t *Buf) override; size_t getSize() const override { return Size; } private: void addEntries(); void add(Entry E) { Entries.push_back(E); } uintX_t Size = 0; }; template class RelocationSection final : public SyntheticSection { typedef typename ELFT::Rel Elf_Rel; typedef typename ELFT::Rela Elf_Rela; typedef typename ELFT::uint uintX_t; public: RelocationSection(StringRef Name, bool Sort); void addReloc(const DynamicReloc &Reloc); unsigned getRelocOffset(); void finalize() override; void writeTo(uint8_t *Buf) override; bool empty() const override { return Relocs.empty(); } size_t getSize() const override { return Relocs.size() * this->Entsize; } size_t getRelativeRelocCount() const { return NumRelativeRelocs; } private: bool Sort; size_t NumRelativeRelocs = 0; std::vector> Relocs; }; struct SymbolTableEntry { SymbolBody *Symbol; size_t StrTabOffset; }; template class SymbolTableSection final : public SyntheticSection { public: typedef typename ELFT::Shdr Elf_Shdr; typedef typename ELFT::Sym Elf_Sym; typedef typename ELFT::SymRange Elf_Sym_Range; typedef typename ELFT::uint uintX_t; SymbolTableSection(StringTableSection &StrTabSec); void finalize() override; void writeTo(uint8_t *Buf) override; size_t getSize() const override { return getNumSymbols() * sizeof(Elf_Sym); } void addSymbol(SymbolBody *Body); StringTableSection &getStrTabSec() const { return StrTabSec; } unsigned getNumSymbols() const { return NumLocals + Symbols.size() + 1; } ArrayRef getSymbols() const { return Symbols; } + static const OutputSectionBase *getOutputSection(SymbolBody *Sym); + unsigned NumLocals = 0; StringTableSection &StrTabSec; private: void writeLocalSymbols(uint8_t *&Buf); void writeGlobalSymbols(uint8_t *Buf); - - const OutputSectionBase *getOutputSection(SymbolBody *Sym); // A vector of symbols and their string table offsets. std::vector Symbols; }; // Outputs GNU Hash section. For detailed explanation see: // https://blogs.oracle.com/ali/entry/gnu_hash_elf_sections template class GnuHashTableSection final : public SyntheticSection { typedef typename ELFT::Off Elf_Off; typedef typename ELFT::Word Elf_Word; typedef typename ELFT::uint uintX_t; public: GnuHashTableSection(); void finalize() override; void writeTo(uint8_t *Buf) override; size_t getSize() const override { return this->Size; } // Adds symbols to the hash table. // Sorts the input to satisfy GNU hash section requirements. void addSymbols(std::vector &Symbols); private: static unsigned calcNBuckets(unsigned NumHashed); static unsigned calcMaskWords(unsigned NumHashed); void writeHeader(uint8_t *&Buf); void writeBloomFilter(uint8_t *&Buf); void writeHashTable(uint8_t *Buf); struct SymbolData { SymbolBody *Body; size_t STName; uint32_t Hash; }; std::vector Symbols; unsigned MaskWords; unsigned NBuckets; unsigned Shift2; uintX_t Size = 0; }; template class HashTableSection final : public SyntheticSection { typedef typename ELFT::Word Elf_Word; public: HashTableSection(); void finalize() override; void writeTo(uint8_t *Buf) override; size_t getSize() const override { return this->Size; } private: size_t Size = 0; }; template class PltSection final : public SyntheticSection { public: PltSection(); void writeTo(uint8_t *Buf) override; size_t getSize() const override; void addEntry(SymbolBody &Sym); bool empty() const override { return Entries.empty(); } private: std::vector> Entries; }; // The IpltSection is a variant of Plt for recording entries for GNU Ifunc // symbols that will be subject to a Target->IRelativeRel // The IpltSection immediately follows the Plt section in the Output Section template class IpltSection final : public SyntheticSection { public: IpltSection(); void writeTo(uint8_t *Buf) override; size_t getSize() const override; void addEntry(SymbolBody &Sym); bool empty() const override { return Entries.empty(); } private: std::vector> Entries; }; template class GdbIndexSection final : public SyntheticSection { typedef typename ELFT::uint uintX_t; const unsigned OffsetTypeSize = 4; const unsigned CuListOffset = 6 * OffsetTypeSize; const unsigned CompilationUnitSize = 16; const unsigned AddressEntrySize = 16 + OffsetTypeSize; const unsigned SymTabEntrySize = 2 * OffsetTypeSize; public: GdbIndexSection(); void finalize() override; void writeTo(uint8_t *Buf) override; size_t getSize() const override; bool empty() const override; // Pairs of [CU Offset, CU length]. std::vector> CompilationUnits; llvm::StringTableBuilder StringPool; GdbHashTab SymbolTable; // The CU vector portion of the constant pool. std::vector>> CuVectors; std::vector> AddressArea; private: void parseDebugSections(); void readDwarf(InputSection *I); uint32_t CuTypesOffset; uint32_t SymTabOffset; uint32_t ConstantPoolOffset; uint32_t StringPoolOffset; size_t CuVectorsSize = 0; std::vector CuVectorsOffset; bool Finalized = false; }; // --eh-frame-hdr option tells linker to construct a header for all the // .eh_frame sections. This header is placed to a section named .eh_frame_hdr // and also to a PT_GNU_EH_FRAME segment. // At runtime the unwinder then can find all the PT_GNU_EH_FRAME segments by // calling dl_iterate_phdr. // This section contains a lookup table for quick binary search of FDEs. // Detailed info about internals can be found in Ian Lance Taylor's blog: // http://www.airs.com/blog/archives/460 (".eh_frame") // http://www.airs.com/blog/archives/462 (".eh_frame_hdr") template class EhFrameHeader final : public SyntheticSection { typedef typename ELFT::uint uintX_t; public: EhFrameHeader(); void writeTo(uint8_t *Buf) override; size_t getSize() const override; void addFde(uint32_t Pc, uint32_t FdeVA); bool empty() const override; private: struct FdeData { uint32_t Pc; uint32_t FdeVA; }; std::vector Fdes; }; // For more information about .gnu.version and .gnu.version_r see: // https://www.akkadia.org/drepper/symbol-versioning // The .gnu.version_d section which has a section type of SHT_GNU_verdef shall // contain symbol version definitions. The number of entries in this section // shall be contained in the DT_VERDEFNUM entry of the .dynamic section. // The section shall contain an array of Elf_Verdef structures, optionally // followed by an array of Elf_Verdaux structures. template class VersionDefinitionSection final : public SyntheticSection { typedef typename ELFT::Verdef Elf_Verdef; typedef typename ELFT::Verdaux Elf_Verdaux; public: VersionDefinitionSection(); void finalize() override; size_t getSize() const override; void writeTo(uint8_t *Buf) override; private: void writeOne(uint8_t *Buf, uint32_t Index, StringRef Name, size_t NameOff); unsigned FileDefNameOff; }; // The .gnu.version section specifies the required version of each symbol in the // dynamic symbol table. It contains one Elf_Versym for each dynamic symbol // table entry. An Elf_Versym is just a 16-bit integer that refers to a version // identifier defined in the either .gnu.version_r or .gnu.version_d section. // The values 0 and 1 are reserved. All other values are used for versions in // the own object or in any of the dependencies. template class VersionTableSection final : public SyntheticSection { typedef typename ELFT::Versym Elf_Versym; public: VersionTableSection(); void finalize() override; size_t getSize() const override; void writeTo(uint8_t *Buf) override; bool empty() const override; }; // The .gnu.version_r section defines the version identifiers used by // .gnu.version. It contains a linked list of Elf_Verneed data structures. Each // Elf_Verneed specifies the version requirements for a single DSO, and contains // a reference to a linked list of Elf_Vernaux data structures which define the // mapping from version identifiers to version names. template class VersionNeedSection final : public SyntheticSection { typedef typename ELFT::Verneed Elf_Verneed; typedef typename ELFT::Vernaux Elf_Vernaux; // A vector of shared files that need Elf_Verneed data structures and the // string table offsets of their sonames. std::vector *, size_t>> Needed; // The next available version identifier. unsigned NextIndex; public: VersionNeedSection(); void addSymbol(SharedSymbol *SS); void finalize() override; void writeTo(uint8_t *Buf) override; size_t getSize() const override; size_t getNeedNum() const { return Needed.size(); } bool empty() const override; }; // .MIPS.abiflags section. template class MipsAbiFlagsSection final : public SyntheticSection { typedef llvm::object::Elf_Mips_ABIFlags Elf_Mips_ABIFlags; public: static MipsAbiFlagsSection *create(); MipsAbiFlagsSection(Elf_Mips_ABIFlags Flags); size_t getSize() const override { return sizeof(Elf_Mips_ABIFlags); } void writeTo(uint8_t *Buf) override; private: Elf_Mips_ABIFlags Flags; }; // .MIPS.options section. template class MipsOptionsSection final : public SyntheticSection { typedef llvm::object::Elf_Mips_Options Elf_Mips_Options; typedef llvm::object::Elf_Mips_RegInfo Elf_Mips_RegInfo; public: static MipsOptionsSection *create(); MipsOptionsSection(Elf_Mips_RegInfo Reginfo); void writeTo(uint8_t *Buf) override; size_t getSize() const override { return sizeof(Elf_Mips_Options) + sizeof(Elf_Mips_RegInfo); } private: Elf_Mips_RegInfo Reginfo; }; // MIPS .reginfo section. template class MipsReginfoSection final : public SyntheticSection { typedef llvm::object::Elf_Mips_RegInfo Elf_Mips_RegInfo; public: static MipsReginfoSection *create(); MipsReginfoSection(Elf_Mips_RegInfo Reginfo); size_t getSize() const override { return sizeof(Elf_Mips_RegInfo); } void writeTo(uint8_t *Buf) override; private: Elf_Mips_RegInfo Reginfo; }; // This is a MIPS specific section to hold a space within the data segment // of executable file which is pointed to by the DT_MIPS_RLD_MAP entry. // See "Dynamic section" in Chapter 5 in the following document: // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf template class MipsRldMapSection : public SyntheticSection { public: MipsRldMapSection(); size_t getSize() const override { return sizeof(typename ELFT::uint); } void writeTo(uint8_t *Buf) override; }; template class ARMExidxSentinelSection : public SyntheticSection { public: ARMExidxSentinelSection(); size_t getSize() const override { return 8; } void writeTo(uint8_t *Buf) override; }; template InputSection *createCommonSection(); template InputSection *createInterpSection(); template MergeInputSection *createCommentSection(); // Linker generated sections which can be used as inputs. template struct In { static InputSection *ARMAttributes; static BuildIdSection *BuildId; static InputSection *Common; static DynamicSection *Dynamic; static StringTableSection *DynStrTab; static SymbolTableSection *DynSymTab; static EhFrameHeader *EhFrameHdr; static GnuHashTableSection *GnuHashTab; static GdbIndexSection *GdbIndex; static GotSection *Got; static MipsGotSection *MipsGot; static GotPltSection *GotPlt; static IgotPltSection *IgotPlt; static HashTableSection *HashTab; static InputSection *Interp; static MipsRldMapSection *MipsRldMap; static PltSection *Plt; static IpltSection *Iplt; static RelocationSection *RelaDyn; static RelocationSection *RelaPlt; static RelocationSection *RelaIplt; static StringTableSection *ShStrTab; static StringTableSection *StrTab; static SymbolTableSection *SymTab; static VersionDefinitionSection *VerDef; static VersionTableSection *VerSym; static VersionNeedSection *VerNeed; }; template InputSection *In::ARMAttributes; template BuildIdSection *In::BuildId; template InputSection *In::Common; template DynamicSection *In::Dynamic; template StringTableSection *In::DynStrTab; template SymbolTableSection *In::DynSymTab; template EhFrameHeader *In::EhFrameHdr; template GdbIndexSection *In::GdbIndex; template GnuHashTableSection *In::GnuHashTab; template GotSection *In::Got; template MipsGotSection *In::MipsGot; template GotPltSection *In::GotPlt; template IgotPltSection *In::IgotPlt; template HashTableSection *In::HashTab; template InputSection *In::Interp; template MipsRldMapSection *In::MipsRldMap; template PltSection *In::Plt; template IpltSection *In::Iplt; template RelocationSection *In::RelaDyn; template RelocationSection *In::RelaPlt; template RelocationSection *In::RelaIplt; template StringTableSection *In::ShStrTab; template StringTableSection *In::StrTab; template SymbolTableSection *In::SymTab; template VersionDefinitionSection *In::VerDef; template VersionTableSection *In::VerSym; template VersionNeedSection *In::VerNeed; } // namespace elf } // namespace lld #endif Index: vendor/lld/dist/cmake/modules/AddLLD.cmake =================================================================== --- vendor/lld/dist/cmake/modules/AddLLD.cmake (revision 312963) +++ vendor/lld/dist/cmake/modules/AddLLD.cmake (revision 312964) @@ -1,45 +1,77 @@ macro(add_lld_library name) - llvm_add_library(${name} ${ARGN}) + cmake_parse_arguments(ARG + "SHARED" + "" + "" + ${ARGN}) + if(ARG_SHARED) + set(ARG_ENABLE_SHARED SHARED) + endif() + llvm_add_library(${name} ${ARG_ENABLE_SHARED} ${ARG_UNPARSED_ARGUMENTS}) set_target_properties(${name} PROPERTIES FOLDER "lld libraries") + + if (LLD_BUILD_TOOLS) + if(${name} IN_LIST LLVM_DISTRIBUTION_COMPONENTS OR + NOT LLVM_DISTRIBUTION_COMPONENTS) + set(export_to_lldtargets EXPORT lldTargets) + set_property(GLOBAL PROPERTY LLD_HAS_EXPORTS True) + endif() + + install(TARGETS ${name} + COMPONENT ${name} + ${export_to_lldtargets} + LIBRARY DESTINATION lib${LLVM_LIBDIR_SUFFIX} + ARCHIVE DESTINATION lib${LLVM_LIBDIR_SUFFIX} + RUNTIME DESTINATION bin) + + if (${ARG_SHARED} AND NOT CMAKE_CONFIGURATION_TYPES) + add_custom_target(install-${name} + DEPENDS ${name} + COMMAND "${CMAKE_COMMAND}" + -DCMAKE_INSTALL_COMPONENT=${name} + -P "${CMAKE_BINARY_DIR}/cmake_install.cmake") + endif() + set_property(GLOBAL APPEND PROPERTY LLD_EXPORTS ${name}) + endif() endmacro(add_lld_library) macro(add_lld_executable name) add_llvm_executable(${name} ${ARGN}) set_target_properties(${name} PROPERTIES FOLDER "lld executables") endmacro(add_lld_executable) macro(add_lld_tool name) if (NOT LLD_BUILD_TOOLS) set(EXCLUDE_FROM_ALL ON) endif() add_lld_executable(${name} ${ARGN}) if (LLD_BUILD_TOOLS) if(${name} IN_LIST LLVM_DISTRIBUTION_COMPONENTS OR NOT LLVM_DISTRIBUTION_COMPONENTS) set(export_to_lldtargets EXPORT lldTargets) set_property(GLOBAL PROPERTY LLD_HAS_EXPORTS True) endif() install(TARGETS ${name} ${export_to_lldtargets} RUNTIME DESTINATION bin COMPONENT ${name}) if(NOT CMAKE_CONFIGURATION_TYPES) add_custom_target(install-${name} DEPENDS ${name} COMMAND "${CMAKE_COMMAND}" -DCMAKE_INSTALL_COMPONENT=${name} -P "${CMAKE_BINARY_DIR}/cmake_install.cmake") endif() set_property(GLOBAL APPEND PROPERTY LLD_EXPORTS ${name}) endif() endmacro() macro(add_lld_symlink name dest) add_llvm_tool_symlink(${name} ${dest} ALWAYS_GENERATE) # Always generate install targets llvm_install_symlink(${name} ${dest} ALWAYS_GENERATE) endmacro() Index: vendor/lld/dist/docs/ReleaseNotes.rst =================================================================== --- vendor/lld/dist/docs/ReleaseNotes.rst (revision 312963) +++ vendor/lld/dist/docs/ReleaseNotes.rst (revision 312964) @@ -1,35 +1,104 @@ ======================= LLD 4.0.0 Release Notes ======================= .. contents:: :local: .. warning:: These are in-progress notes for the upcoming LLVM 4.0.0 release. Introduction ============ -This document contains the release notes for the LLD linker, release 4.0.0. +LLD is a linker which supports ELF (Unix), COFF (Windows) and Mach-O +(macOS). It is generally faster than the GNU BFD/gold linkers or the +MSVC linker. + +LLD is designed to be a drop-in replacmenet for the system linkers, so +that users don't need to change their build systems other than swapping +the linker command. + +This document contains the release notes for LLD 4.0.0. Here we describe the status of LLD, including major improvements from the previous release. All LLD releases may be downloaded from the `LLVM releases web site `_. -Non-comprehensive list of changes in this release -================================================= +What's New in LLD 4.0? +====================== + ELF Improvements ---------------- -* Initial support for LTO. +LLD provides much better compatibility with the GNU linker than before. +Now it is able to link the entire FreeBSD base system including the kernel +out of the box. We are working closely with the FreeBSD project to +make it usable as the system linker in a future release of the operating +system. -COFF Improvements ------------------ +Multi-threading performance has been improved, and multi-threading +is now enabled by default. Combined with other optimizations, LLD 4.0 +is about 1.5 times faster than LLD 3.9 when linking large programs +in our test environment. -* Item 1. +Other notable changes are listed below: -MachO Improvements ------------------- +* Error messages contain more information than before. If debug info + is available, the linker prints out not only the object file name + but the source location of unresolved symbols. -* Item 1. +* Error messages are printed in red just like Clang by default. You + can disable it by passing -no-color-diagnostics. + +* LLD's version string is now embedded in a .comment section in the + result output file. You can dump it with this command: ``objdump -j -s + .comment ``. + +* The -Map option is supported. With that, you can print out section + and symbol information to a specified file. This feature is useful + for analyzing link results. + +* The file format for the -reproduce option has changed from cpio to + tar. + +* When creating a copy relocation for a symbol, LLD now scans the + DSO's header to see if the symbol is in a read-only segment. If so, + space for the copy relocation is reserved in .bss.rel.ro instead of + .bss. This fixes a security issue that read-only data in a DSO + becomes writable if it is copied by a copy relocation. This issue + was disclosed originally on the binutils mailing list at + ``. + +* Compressed input sections are supported. + +* ``--oformat binary``, ``--section-start``, ``-Tbss``, ``-Tdata``, + ``-Ttext``, ``-b binary``, ``-build-id=uuid``, ``-no-rosegment``, + ``-nopie``, ``-nostdlib``, ``-omagic``, ``-retain-symbols-file``, + ``-sort-section``, ``-z max-page-size`` and ``-z wxneeded`` are + suppoorted. + +* A lot of linker script directives have been added. + +* Default image base address for x86-64 has changed from 0x10000 to + 0x200000 to make it huge-page friendly. + +* ARM port now supports GNU ifunc, the ARM C++ exceptions ABI, TLS + relocations and static linking. Problems with dlopen() on systems + using eglibc fixed. + +* MIPS port now supports input files in new R6 revision of MIPS ABIs + or N32 ABI. Generated file now contains .MIPS.abiflags section and + complete set of ELF headers flags. + +* Relocations produced by the ``-mxgot`` compiler's flag is supported + for MIPS. Now it is possible to generate "large" GOT exceeds 64K + limit. + +COFF Improvements +----------------- + +* Performance on Windows has been improved by parallelizing parts of the + linker and optimizing file system operations. As a result of these + improvements, LLD 4.0 has been measured to be about 2.5 times faster + than LLD 3.9 when linking a large Chromium DLL. Index: vendor/lld/dist/test/ELF/linkerscript/common-assign.s =================================================================== --- vendor/lld/dist/test/ELF/linkerscript/common-assign.s (nonexistent) +++ vendor/lld/dist/test/ELF/linkerscript/common-assign.s (revision 312964) @@ -0,0 +1,48 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t +# RUN: echo "SECTIONS { . = SIZEOF_HEADERS; pfoo = foo; pbar = bar; }" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-readobj -symbols %t1 | FileCheck %s + +# CHECK: Symbol { +# CHECK: Name: bar +# CHECK-NEXT: Value: 0x134 +# CHECK-NEXT: Size: 4 +# CHECK-NEXT: Binding: Global +# CHECK-NEXT: Type: Object +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: .bss +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: foo +# CHECK-NEXT: Value: 0x138 +# CHECK-NEXT: Size: 4 +# CHECK-NEXT: Binding: Global +# CHECK-NEXT: Type: Object +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: .bss +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: pfoo +# CHECK-NEXT: Value: 0x138 +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Binding: Global +# CHECK-NEXT: Type: None +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: .bss +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: pbar +# CHECK-NEXT: Value: 0x134 +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Binding: Global +# CHECK-NEXT: Type: None +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: .bss +# CHECK-NEXT: } +# CHECK-NEXT: ] + +.comm foo,4,4 +.comm bar,4,4 +movl $1, foo(%rip) +movl $2, bar(%rip) Property changes on: vendor/lld/dist/test/ELF/linkerscript/common-assign.s ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property