mirror of
https://github.com/opnsense/src.git
synced 2026-05-28 04:12:45 -04:00
Vendor import of lld trunk r305145:
https://llvm.org/svn/llvm-project/lld/trunk@305145
This commit is contained in:
parent
b9a1baec33
commit
2079716dfb
85 changed files with 1485 additions and 739 deletions
|
|
@ -25,6 +25,7 @@ add_lld_library(lldCOFF
|
|||
|
||||
LINK_COMPONENTS
|
||||
${LLVM_TARGETS_TO_BUILD}
|
||||
BinaryFormat
|
||||
BitReader
|
||||
Core
|
||||
DebugInfoCodeView
|
||||
|
|
|
|||
|
|
@ -12,8 +12,8 @@
|
|||
#include "InputFiles.h"
|
||||
#include "Symbols.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
#include "llvm/BinaryFormat/COFF.h"
|
||||
#include "llvm/Object/COFF.h"
|
||||
#include "llvm/Support/COFF.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/Endian.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
#include "lld/Driver/Driver.h"
|
||||
#include "llvm/ADT/Optional.h"
|
||||
#include "llvm/ADT/StringSwitch.h"
|
||||
#include "llvm/BinaryFormat/Magic.h"
|
||||
#include "llvm/Object/ArchiveWriter.h"
|
||||
#include "llvm/Object/COFFImportFile.h"
|
||||
#include "llvm/Object/COFFModuleDefinition.h"
|
||||
|
|
@ -40,8 +41,6 @@ using namespace llvm;
|
|||
using namespace llvm::object;
|
||||
using namespace llvm::COFF;
|
||||
using llvm::sys::Process;
|
||||
using llvm::sys::fs::file_magic;
|
||||
using llvm::sys::fs::identify_magic;
|
||||
|
||||
namespace lld {
|
||||
namespace coff {
|
||||
|
|
@ -457,17 +456,11 @@ static void createImportLibrary() {
|
|||
static void parseModuleDefs(StringRef Path) {
|
||||
std::unique_ptr<MemoryBuffer> MB = check(
|
||||
MemoryBuffer::getFile(Path, -1, false, true), "could not open " + Path);
|
||||
MemoryBufferRef MBRef = MB->getMemBufferRef();
|
||||
COFFModuleDefinition M =
|
||||
check(parseCOFFModuleDefinition(MB->getMemBufferRef(), Config->Machine));
|
||||
|
||||
Expected<COFFModuleDefinition> Def =
|
||||
parseCOFFModuleDefinition(MBRef, Config->Machine);
|
||||
if (!Def)
|
||||
fatal(errorToErrorCode(Def.takeError()).message());
|
||||
|
||||
COFFModuleDefinition &M = *Def;
|
||||
if (Config->OutputFile.empty())
|
||||
Config->OutputFile = Saver.save(M.OutputFile);
|
||||
|
||||
if (M.ImageBase)
|
||||
Config->ImageBase = M.ImageBase;
|
||||
if (M.StackReserve)
|
||||
|
|
|
|||
|
|
@ -19,9 +19,9 @@
|
|||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/Triple.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
#include "llvm/BinaryFormat/COFF.h"
|
||||
#include "llvm/Object/Binary.h"
|
||||
#include "llvm/Object/COFF.h"
|
||||
#include "llvm/Support/COFF.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/Endian.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ add_lld_library(lldELF
|
|||
LINK_COMPONENTS
|
||||
${LLVM_TARGETS_TO_BUILD}
|
||||
Analysis
|
||||
BinaryFormat
|
||||
BitReader
|
||||
BitWriter
|
||||
Codegen
|
||||
|
|
|
|||
|
|
@ -13,9 +13,9 @@
|
|||
#include "llvm/ADT/MapVector.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/StringSet.h"
|
||||
#include "llvm/BinaryFormat/ELF.h"
|
||||
#include "llvm/Support/CachePruning.h"
|
||||
#include "llvm/Support/CodeGen.h"
|
||||
#include "llvm/Support/ELF.h"
|
||||
#include "llvm/Support/Endian.h"
|
||||
|
||||
#include <vector>
|
||||
|
|
@ -67,6 +67,12 @@ struct VersionDefinition {
|
|||
size_t NameOff = 0; // Offset in the string table
|
||||
};
|
||||
|
||||
// Structure for mapping renamed symbols
|
||||
struct RenamedSymbol {
|
||||
Symbol *Target;
|
||||
uint8_t OrigBinding;
|
||||
};
|
||||
|
||||
// This struct contains the global configuration for the linker.
|
||||
// Most fields are direct mapping from the command line options
|
||||
// and such fields have the same name as the corresponding options.
|
||||
|
|
@ -98,6 +104,7 @@ struct Configuration {
|
|||
std::vector<SymbolVersion> VersionScriptGlobals;
|
||||
std::vector<SymbolVersion> VersionScriptLocals;
|
||||
std::vector<uint8_t> BuildIdVector;
|
||||
llvm::MapVector<Symbol *, RenamedSymbol> RenamedSymbols;
|
||||
bool AllowMultipleDefinition;
|
||||
bool AsNeeded = false;
|
||||
bool Bsymbolic;
|
||||
|
|
|
|||
|
|
@ -185,7 +185,7 @@ void LinkerDriver::addFile(StringRef Path, bool WithLOption) {
|
|||
// is attempting LTO and using a default ar command that doesn't
|
||||
// understand the LLVM bitcode file. It is a pretty common error, so
|
||||
// we'll handle it as if it had a symbol table.
|
||||
if (!File->hasSymbolTable()) {
|
||||
if (!File->isEmpty() && !File->hasSymbolTable()) {
|
||||
for (const auto &P : getArchiveMembers(MBRef))
|
||||
Files.push_back(make<LazyObjectFile>(P.first, Path, P.second));
|
||||
return;
|
||||
|
|
@ -970,6 +970,14 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
|
|||
Symtab.scanShlibUndefined();
|
||||
Symtab.scanVersionScript();
|
||||
|
||||
// Create wrapped symbols for -wrap option.
|
||||
for (auto *Arg : Args.filtered(OPT_wrap))
|
||||
Symtab.addSymbolWrap(Arg->getValue());
|
||||
|
||||
// Create alias symbols for -defsym option.
|
||||
for (std::pair<StringRef, StringRef> &Def : getDefsym(Args))
|
||||
Symtab.addSymbolAlias(Def.first, Def.second);
|
||||
|
||||
Symtab.addCombinedLTOObject();
|
||||
if (ErrorCount)
|
||||
return;
|
||||
|
|
@ -979,12 +987,8 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
|
|||
for (StringRef Sym : Script->Opt.ReferencedSymbols)
|
||||
Symtab.addUndefined(Sym);
|
||||
|
||||
for (auto *Arg : Args.filtered(OPT_wrap))
|
||||
Symtab.wrap(Arg->getValue());
|
||||
|
||||
// Handle --defsym=sym=alias option.
|
||||
for (std::pair<StringRef, StringRef> &Def : getDefsym(Args))
|
||||
Symtab.alias(Def.first, Def.second);
|
||||
// Apply symbol renames for -wrap and -defsym
|
||||
Symtab.applySymbolRenames();
|
||||
|
||||
// Now that we have a complete list of input files.
|
||||
// Beyond this point, no new files are added.
|
||||
|
|
|
|||
|
|
@ -22,8 +22,8 @@
|
|||
#include "Relocations.h"
|
||||
#include "Strings.h"
|
||||
|
||||
#include "llvm/BinaryFormat/Dwarf.h"
|
||||
#include "llvm/Object/ELF.h"
|
||||
#include "llvm/Support/Dwarf.h"
|
||||
#include "llvm/Support/Endian.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
|
|
|||
|
|
@ -24,7 +24,30 @@ struct AddressEntry {
|
|||
InputSection *Section;
|
||||
uint64_t LowAddress;
|
||||
uint64_t HighAddress;
|
||||
size_t CuIndex;
|
||||
uint32_t CuIndex;
|
||||
};
|
||||
|
||||
// Struct represents single entry of compilation units list area of gdb index.
|
||||
// It consist of CU offset in .debug_info section and it's size.
|
||||
struct CompilationUnitEntry {
|
||||
uint64_t CuOffset;
|
||||
uint64_t CuLength;
|
||||
};
|
||||
|
||||
// Represents data about symbol and type names which are used
|
||||
// to build symbol table and constant pool area of gdb index.
|
||||
struct NameTypeEntry {
|
||||
StringRef Name;
|
||||
uint8_t Type;
|
||||
};
|
||||
|
||||
// We fill one GdbIndexDataChunk for each object where scan of
|
||||
// debug information performed. That information futher used
|
||||
// for filling gdb index section areas.
|
||||
struct GdbIndexChunk {
|
||||
std::vector<AddressEntry> AddressArea;
|
||||
std::vector<CompilationUnitEntry> CompilationUnits;
|
||||
std::vector<NameTypeEntry> NamesAndTypes;
|
||||
};
|
||||
|
||||
// Element of GdbHashTab hash table.
|
||||
|
|
|
|||
|
|
@ -78,8 +78,8 @@
|
|||
#include "SymbolTable.h"
|
||||
#include "Threads.h"
|
||||
#include "llvm/ADT/Hashing.h"
|
||||
#include "llvm/BinaryFormat/ELF.h"
|
||||
#include "llvm/Object/ELF.h"
|
||||
#include "llvm/Support/ELF.h"
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
|
||||
|
|
|
|||
|
|
@ -306,21 +306,23 @@ void elf::ObjectFile<ELFT>::initializeSections(
|
|||
|
||||
switch (Sec.sh_type) {
|
||||
case SHT_GROUP: {
|
||||
// We discard comdat sections usually. When -r we should not do that. We
|
||||
// still do deduplication in this case to simplify implementation, because
|
||||
// otherwise merging group sections together would requre additional
|
||||
// regeneration of its contents.
|
||||
bool New = ComdatGroups
|
||||
.insert(CachedHashStringRef(
|
||||
getShtGroupSignature(ObjSections, Sec)))
|
||||
.second;
|
||||
if (New && Config->Relocatable)
|
||||
this->Sections[I] = createInputSection(Sec, SectionStringTable);
|
||||
else
|
||||
this->Sections[I] = &InputSection::Discarded;
|
||||
if (New)
|
||||
continue;
|
||||
// De-duplicate section groups by their signatures.
|
||||
StringRef Signature = getShtGroupSignature(ObjSections, Sec);
|
||||
bool IsNew = ComdatGroups.insert(CachedHashStringRef(Signature)).second;
|
||||
this->Sections[I] = &InputSection::Discarded;
|
||||
|
||||
// If it is a new section group, we want to keep group members.
|
||||
// Group leader sections, which contain indices of group members, are
|
||||
// discarded because they are useless beyond this point. The only
|
||||
// exception is the -r option because in order to produce re-linkable
|
||||
// object files, we want to pass through basically everything.
|
||||
if (IsNew) {
|
||||
if (Config->Relocatable)
|
||||
this->Sections[I] = createInputSection(Sec, SectionStringTable);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Otherwise, discard group members.
|
||||
for (uint32_t SecIndex : getShtGroupEntries(Sec)) {
|
||||
if (SecIndex >= Size)
|
||||
fatal(toString(this) +
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
#include "Target.h"
|
||||
#include "Thunks.h"
|
||||
#include "llvm/Object/Decompressor.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/Compression.h"
|
||||
#include "llvm/Support/Endian.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
|
|
@ -72,6 +73,16 @@ InputSectionBase::InputSectionBase(InputFile *File, uint64_t Flags,
|
|||
this->Alignment = V;
|
||||
}
|
||||
|
||||
// Drop SHF_GROUP bit unless we are producing a re-linkable object file.
|
||||
// SHF_GROUP is a marker that a section belongs to some comdat group.
|
||||
// That flag doesn't make sense in an executable.
|
||||
static uint64_t getFlags(uint64_t Flags) {
|
||||
Flags &= ~(uint64_t)SHF_INFO_LINK;
|
||||
if (!Config->Relocatable)
|
||||
Flags &= ~(uint64_t)SHF_GROUP;
|
||||
return Flags;
|
||||
}
|
||||
|
||||
// GNU assembler 2.24 and LLVM 4.0.0's MC (the newest release as of
|
||||
// March 2017) fail to infer section types for sections starting with
|
||||
// ".init_array." or ".fini_array.". They set SHT_PROGBITS instead of
|
||||
|
|
@ -94,7 +105,7 @@ template <class ELFT>
|
|||
InputSectionBase::InputSectionBase(elf::ObjectFile<ELFT> *File,
|
||||
const typename ELFT::Shdr *Hdr,
|
||||
StringRef Name, Kind SectionKind)
|
||||
: InputSectionBase(File, Hdr->sh_flags & ~SHF_INFO_LINK,
|
||||
: InputSectionBase(File, getFlags(Hdr->sh_flags),
|
||||
getType(Hdr->sh_type, Name), Hdr->sh_entsize,
|
||||
Hdr->sh_link, Hdr->sh_info, Hdr->sh_addralign,
|
||||
getSectionContents(File, Hdr), Name, SectionKind) {
|
||||
|
|
@ -308,23 +319,21 @@ OutputSection *InputSection::getParent() const {
|
|||
return cast_or_null<OutputSection>(Parent);
|
||||
}
|
||||
|
||||
void InputSection::copyShtGroup(uint8_t *Buf) {
|
||||
assert(this->Type == SHT_GROUP);
|
||||
// Copy SHT_GROUP section contents. Used only for the -r option.
|
||||
template <class ELFT> void InputSection::copyShtGroup(uint8_t *Buf) {
|
||||
// ELFT::Word is the 32-bit integral type in the target endianness.
|
||||
typedef typename ELFT::Word u32;
|
||||
ArrayRef<u32> From = getDataAs<u32>();
|
||||
auto *To = reinterpret_cast<u32 *>(Buf);
|
||||
|
||||
ArrayRef<uint32_t> From = getDataAs<uint32_t>();
|
||||
uint32_t *To = reinterpret_cast<uint32_t *>(Buf);
|
||||
|
||||
// First entry is a flag word, we leave it unchanged.
|
||||
// The first entry is not a section number but a flag.
|
||||
*To++ = From[0];
|
||||
|
||||
// Here we adjust indices of sections that belong to group as it
|
||||
// might change during linking.
|
||||
// Adjust section numbers because section numbers in an input object
|
||||
// files are different in the output.
|
||||
ArrayRef<InputSectionBase *> Sections = this->File->getSections();
|
||||
for (uint32_t Val : From.slice(1)) {
|
||||
uint32_t Index = read32(&Val, Config->Endianness);
|
||||
write32(To++, Sections[Index]->getOutputSection()->SectionIndex,
|
||||
Config->Endianness);
|
||||
}
|
||||
for (uint32_t Idx : From.slice(1))
|
||||
*To++ = Sections[Idx]->getOutputSection()->SectionIndex;
|
||||
}
|
||||
|
||||
InputSectionBase *InputSection::getRelocatedSection() {
|
||||
|
|
@ -682,7 +691,7 @@ void InputSectionBase::relocateAlloc(uint8_t *Buf, uint8_t *BufEnd) {
|
|||
// Patch a nop (0x60000000) to a ld.
|
||||
if (BufLoc + 8 <= BufEnd && read32be(BufLoc + 4) == 0x60000000)
|
||||
write32be(BufLoc + 4, 0xe8410028); // ld %r2, 40(%r1)
|
||||
// fallthrough
|
||||
LLVM_FALLTHROUGH;
|
||||
default:
|
||||
Target->relocateOne(BufLoc, Type, TargetVA);
|
||||
break;
|
||||
|
|
@ -712,10 +721,9 @@ template <class ELFT> void InputSection::writeTo(uint8_t *Buf) {
|
|||
return;
|
||||
}
|
||||
|
||||
// If -r is given, linker should keep SHT_GROUP sections. We should fixup
|
||||
// them, see copyShtGroup().
|
||||
// If -r is given, we may have a SHT_GROUP section.
|
||||
if (this->Type == SHT_GROUP) {
|
||||
copyShtGroup(Buf + OutSecOff);
|
||||
copyShtGroup<ELFT>(Buf + OutSecOff);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -325,7 +325,7 @@ private:
|
|||
template <class ELFT, class RelTy>
|
||||
void copyRelocations(uint8_t *Buf, llvm::ArrayRef<RelTy> Rels);
|
||||
|
||||
void copyShtGroup(uint8_t *Buf);
|
||||
template <class ELFT> void copyShtGroup(uint8_t *Buf);
|
||||
};
|
||||
|
||||
// The list of all input sections.
|
||||
|
|
|
|||
|
|
@ -17,13 +17,13 @@
|
|||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
#include "llvm/BinaryFormat/ELF.h"
|
||||
#include "llvm/IR/DiagnosticPrinter.h"
|
||||
#include "llvm/LTO/Caching.h"
|
||||
#include "llvm/LTO/Config.h"
|
||||
#include "llvm/LTO/LTO.h"
|
||||
#include "llvm/Object/SymbolicFile.h"
|
||||
#include "llvm/Support/CodeGen.h"
|
||||
#include "llvm/Support/ELF.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
|
|
@ -136,6 +136,7 @@ void BitcodeCompiler::add(BitcodeFile &F) {
|
|||
Sym->IsUsedInRegularObj || (R.Prevailing && Sym->includeInDynsym());
|
||||
if (R.Prevailing)
|
||||
undefine(Sym);
|
||||
R.LinkerRedefined = Config->RenamedSymbols.count(Sym);
|
||||
}
|
||||
checkError(LTOObj->add(std::move(F.Obj), Resols));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,9 +25,9 @@
|
|||
#include "Writer.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/BinaryFormat/ELF.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/Compression.h"
|
||||
#include "llvm/Support/ELF.h"
|
||||
#include "llvm/Support/Endian.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
|
|
@ -54,7 +54,7 @@ uint64_t ExprValue::getValue() const {
|
|||
if (Sec) {
|
||||
if (OutputSection *OS = Sec->getOutputSection())
|
||||
return alignTo(Sec->getOffset(Val) + OS->Addr, Alignment);
|
||||
error("unable to evaluate expression: input section " + Sec->Name +
|
||||
error(Loc + ": unable to evaluate expression: input section " + Sec->Name +
|
||||
" has no output section assigned");
|
||||
}
|
||||
return alignTo(Val, Alignment);
|
||||
|
|
@ -431,6 +431,8 @@ void LinkerScript::processCommands(OutputSectionFactory &Factory) {
|
|||
if (OutputSection *Sec = Cmd->Sec) {
|
||||
assert(Sec->SectionIndex == INT_MAX);
|
||||
Sec->SectionIndex = I;
|
||||
if (Cmd->Noload)
|
||||
Sec->Type = SHT_NOBITS;
|
||||
SecToCommand[Sec] = Cmd;
|
||||
}
|
||||
}
|
||||
|
|
@ -442,7 +444,7 @@ void LinkerScript::fabricateDefaultCommands() {
|
|||
std::vector<BaseCommand *> Commands;
|
||||
|
||||
// Define start address
|
||||
uint64_t StartAddr = Config->ImageBase + elf::getHeaderSize();
|
||||
uint64_t StartAddr = -1;
|
||||
|
||||
// The Sections with -T<section> have been sorted in order of ascending
|
||||
// address. We must lower StartAddr if the lowest -T<section address> as
|
||||
|
|
@ -450,8 +452,12 @@ void LinkerScript::fabricateDefaultCommands() {
|
|||
for (auto& KV : Config->SectionStartMap)
|
||||
StartAddr = std::min(StartAddr, KV.second);
|
||||
|
||||
Commands.push_back(
|
||||
make<SymbolAssignment>(".", [=] { return StartAddr; }, ""));
|
||||
Commands.push_back(make<SymbolAssignment>(
|
||||
".",
|
||||
[=] {
|
||||
return std::min(StartAddr, Config->ImageBase + elf::getHeaderSize());
|
||||
},
|
||||
""));
|
||||
|
||||
// For each OutputSection that needs a VA fabricate an OutputSectionCommand
|
||||
// with an InputSectionDescription describing the InputSections
|
||||
|
|
@ -870,51 +876,6 @@ void LinkerScript::processNonSectionCommands() {
|
|||
}
|
||||
}
|
||||
|
||||
// Do a last effort at synchronizing the linker script "AST" and the section
|
||||
// list. This is needed to account for last minute changes, like adding a
|
||||
// .ARM.exidx terminator and sorting SHF_LINK_ORDER sections.
|
||||
//
|
||||
// FIXME: We should instead create the "AST" earlier and the above changes would
|
||||
// be done directly in the "AST".
|
||||
//
|
||||
// This can only handle new sections being added and sections being reordered.
|
||||
void LinkerScript::synchronize() {
|
||||
for (BaseCommand *Base : Opt.Commands) {
|
||||
auto *Cmd = dyn_cast<OutputSectionCommand>(Base);
|
||||
if (!Cmd)
|
||||
continue;
|
||||
ArrayRef<InputSection *> Sections = Cmd->Sec->Sections;
|
||||
std::vector<InputSection **> ScriptSections;
|
||||
DenseSet<InputSection *> ScriptSectionsSet;
|
||||
for (BaseCommand *Base : Cmd->Commands) {
|
||||
auto *ISD = dyn_cast<InputSectionDescription>(Base);
|
||||
if (!ISD)
|
||||
continue;
|
||||
for (InputSection *&IS : ISD->Sections) {
|
||||
if (IS->Live) {
|
||||
ScriptSections.push_back(&IS);
|
||||
ScriptSectionsSet.insert(IS);
|
||||
}
|
||||
}
|
||||
}
|
||||
std::vector<InputSection *> Missing;
|
||||
for (InputSection *IS : Sections)
|
||||
if (!ScriptSectionsSet.count(IS))
|
||||
Missing.push_back(IS);
|
||||
if (!Missing.empty()) {
|
||||
auto ISD = make<InputSectionDescription>("");
|
||||
ISD->Sections = Missing;
|
||||
Cmd->Commands.push_back(ISD);
|
||||
for (InputSection *&IS : ISD->Sections)
|
||||
if (IS->Live)
|
||||
ScriptSections.push_back(&IS);
|
||||
}
|
||||
assert(ScriptSections.size() == Sections.size());
|
||||
for (int I = 0, N = Sections.size(); I < N; ++I)
|
||||
*ScriptSections[I] = Sections[I];
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
allocateHeaders(std::vector<PhdrEntry> &Phdrs,
|
||||
ArrayRef<OutputSectionCommand *> OutputSectionCommands,
|
||||
|
|
@ -1071,6 +1032,81 @@ static void writeInt(uint8_t *Buf, uint64_t Data, uint64_t Size) {
|
|||
llvm_unreachable("unsupported Size argument");
|
||||
}
|
||||
|
||||
static bool compareByFilePosition(InputSection *A, InputSection *B) {
|
||||
// Synthetic doesn't have link order dependecy, stable_sort will keep it last
|
||||
if (A->kind() == InputSectionBase::Synthetic ||
|
||||
B->kind() == InputSectionBase::Synthetic)
|
||||
return false;
|
||||
InputSection *LA = A->getLinkOrderDep();
|
||||
InputSection *LB = B->getLinkOrderDep();
|
||||
OutputSection *AOut = LA->getParent();
|
||||
OutputSection *BOut = LB->getParent();
|
||||
if (AOut != BOut)
|
||||
return AOut->SectionIndex < BOut->SectionIndex;
|
||||
return LA->OutSecOff < LB->OutSecOff;
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
static void finalizeShtGroup(OutputSection *OS,
|
||||
ArrayRef<InputSection *> Sections) {
|
||||
// sh_link field for SHT_GROUP sections should contain the section index of
|
||||
// the symbol table.
|
||||
OS->Link = InX::SymTab->getParent()->SectionIndex;
|
||||
|
||||
// sh_info then contain index of an entry in symbol table section which
|
||||
// provides signature of the section group.
|
||||
elf::ObjectFile<ELFT> *Obj = Sections[0]->getFile<ELFT>();
|
||||
assert(Config->Relocatable && Sections.size() == 1);
|
||||
ArrayRef<SymbolBody *> Symbols = Obj->getSymbols();
|
||||
OS->Info = InX::SymTab->getSymbolIndex(Symbols[Sections[0]->Info - 1]);
|
||||
}
|
||||
|
||||
template <class ELFT> void OutputSectionCommand::finalize() {
|
||||
// Link order may be distributed across several InputSectionDescriptions
|
||||
// but sort must consider them all at once.
|
||||
std::vector<InputSection **> ScriptSections;
|
||||
std::vector<InputSection *> Sections;
|
||||
for (BaseCommand *Base : Commands)
|
||||
if (auto *ISD = dyn_cast<InputSectionDescription>(Base))
|
||||
for (InputSection *&IS : ISD->Sections) {
|
||||
ScriptSections.push_back(&IS);
|
||||
Sections.push_back(IS);
|
||||
}
|
||||
|
||||
if ((Sec->Flags & SHF_LINK_ORDER)) {
|
||||
std::sort(Sections.begin(), Sections.end(), compareByFilePosition);
|
||||
for (int I = 0, N = Sections.size(); I < N; ++I)
|
||||
*ScriptSections[I] = Sections[I];
|
||||
|
||||
// We must preserve the link order dependency of sections with the
|
||||
// SHF_LINK_ORDER flag. The dependency is indicated by the sh_link field. We
|
||||
// need to translate the InputSection sh_link to the OutputSection sh_link,
|
||||
// all InputSections in the OutputSection have the same dependency.
|
||||
if (auto *D = Sections.front()->getLinkOrderDep())
|
||||
Sec->Link = D->getParent()->SectionIndex;
|
||||
}
|
||||
|
||||
uint32_t Type = Sec->Type;
|
||||
if (Type == SHT_GROUP) {
|
||||
finalizeShtGroup<ELFT>(Sec, Sections);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Config->CopyRelocs || (Type != SHT_RELA && Type != SHT_REL))
|
||||
return;
|
||||
|
||||
InputSection *First = Sections[0];
|
||||
if (isa<SyntheticSection>(First))
|
||||
return;
|
||||
|
||||
Sec->Link = InX::SymTab->getParent()->SectionIndex;
|
||||
// sh_info for SHT_REL[A] sections should contain the section header index of
|
||||
// the section to which the relocation applies.
|
||||
InputSectionBase *S = First->getRelocatedSection();
|
||||
Sec->Info = S->getOutputSection()->SectionIndex;
|
||||
Sec->Flags |= SHF_INFO_LINK;
|
||||
}
|
||||
|
||||
// Compress section contents if this section contains debug info.
|
||||
template <class ELFT> void OutputSectionCommand::maybeCompress() {
|
||||
typedef typename ELFT::Chdr Elf_Chdr;
|
||||
|
|
@ -1099,6 +1135,9 @@ template <class ELFT> void OutputSectionCommand::maybeCompress() {
|
|||
}
|
||||
|
||||
template <class ELFT> void OutputSectionCommand::writeTo(uint8_t *Buf) {
|
||||
if (Sec->Type == SHT_NOBITS)
|
||||
return;
|
||||
|
||||
Sec->Loc = Buf;
|
||||
|
||||
// We may have already rendered compressed content when using
|
||||
|
|
@ -1110,9 +1149,6 @@ template <class ELFT> void OutputSectionCommand::writeTo(uint8_t *Buf) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (Sec->Type == SHT_NOBITS)
|
||||
return;
|
||||
|
||||
// Write leading padding.
|
||||
std::vector<InputSection *> Sections;
|
||||
for (BaseCommand *Cmd : Commands)
|
||||
|
|
@ -1156,12 +1192,12 @@ bool LinkerScript::hasLMA(OutputSection *Sec) {
|
|||
|
||||
ExprValue LinkerScript::getSymbolValue(const Twine &Loc, StringRef S) {
|
||||
if (S == ".")
|
||||
return {CurOutSec, Dot - CurOutSec->Addr};
|
||||
return {CurOutSec, Dot - CurOutSec->Addr, Loc};
|
||||
if (SymbolBody *B = findSymbol(S)) {
|
||||
if (auto *D = dyn_cast<DefinedRegular>(B))
|
||||
return {D->Section, D->Value};
|
||||
return {D->Section, D->Value, Loc};
|
||||
if (auto *C = dyn_cast<DefinedCommon>(B))
|
||||
return {InX::Common, C->Offset};
|
||||
return {InX::Common, C->Offset, Loc};
|
||||
}
|
||||
error(Loc + ": symbol not found: " + S);
|
||||
return 0;
|
||||
|
|
@ -1201,3 +1237,8 @@ template void OutputSectionCommand::maybeCompress<ELF32LE>();
|
|||
template void OutputSectionCommand::maybeCompress<ELF32BE>();
|
||||
template void OutputSectionCommand::maybeCompress<ELF64LE>();
|
||||
template void OutputSectionCommand::maybeCompress<ELF64BE>();
|
||||
|
||||
template void OutputSectionCommand::finalize<ELF32LE>();
|
||||
template void OutputSectionCommand::finalize<ELF32BE>();
|
||||
template void OutputSectionCommand::finalize<ELF64LE>();
|
||||
template void OutputSectionCommand::finalize<ELF64BE>();
|
||||
|
|
|
|||
|
|
@ -42,15 +42,14 @@ struct ExprValue {
|
|||
uint64_t Val;
|
||||
bool ForceAbsolute;
|
||||
uint64_t Alignment = 1;
|
||||
std::string Loc;
|
||||
|
||||
ExprValue(SectionBase *Sec, bool ForceAbsolute, uint64_t Val,
|
||||
uint64_t Alignment)
|
||||
: Sec(Sec), Val(Val), ForceAbsolute(ForceAbsolute), Alignment(Alignment) {
|
||||
}
|
||||
ExprValue(SectionBase *Sec, bool ForceAbsolute, uint64_t Val)
|
||||
: Sec(Sec), Val(Val), ForceAbsolute(ForceAbsolute) {}
|
||||
ExprValue(SectionBase *Sec, uint64_t Val) : ExprValue(Sec, false, Val) {}
|
||||
ExprValue(uint64_t Val) : ExprValue(nullptr, Val) {}
|
||||
const Twine &Loc)
|
||||
: Sec(Sec), Val(Val), ForceAbsolute(ForceAbsolute), Loc(Loc.str()) {}
|
||||
ExprValue(SectionBase *Sec, uint64_t Val, const Twine &Loc)
|
||||
: ExprValue(Sec, false, Val, Loc) {}
|
||||
ExprValue(uint64_t Val) : ExprValue(nullptr, Val, "") {}
|
||||
bool isAbsolute() const { return ForceAbsolute || Sec == nullptr; }
|
||||
uint64_t getValue() const;
|
||||
uint64_t getSecAddr() const;
|
||||
|
|
@ -135,7 +134,9 @@ struct OutputSectionCommand : BaseCommand {
|
|||
ConstraintKind Constraint = ConstraintKind::NoConstraint;
|
||||
std::string Location;
|
||||
std::string MemoryRegionName;
|
||||
bool Noload = false;
|
||||
|
||||
template <class ELFT> void finalize();
|
||||
template <class ELFT> void writeTo(uint8_t *Buf);
|
||||
template <class ELFT> void maybeCompress();
|
||||
uint32_t getFiller();
|
||||
|
|
@ -281,7 +282,6 @@ public:
|
|||
void assignOffsets(OutputSectionCommand *Cmd);
|
||||
void placeOrphanSections();
|
||||
void processNonSectionCommands();
|
||||
void synchronize();
|
||||
void assignAddresses(std::vector<PhdrEntry> &Phdrs,
|
||||
ArrayRef<OutputSectionCommand *> OutputSectionCommands);
|
||||
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@
|
|||
#include "SymbolTable.h"
|
||||
#include "Writer.h"
|
||||
|
||||
#include "llvm/BinaryFormat/ELF.h"
|
||||
#include "llvm/Object/ELF.h"
|
||||
#include "llvm/Support/ELF.h"
|
||||
#include "llvm/Support/MipsABIFlags.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
#include "SyntheticSections.h"
|
||||
#include "Target.h"
|
||||
#include "Threads.h"
|
||||
#include "llvm/Support/Dwarf.h"
|
||||
#include "llvm/BinaryFormat/Dwarf.h"
|
||||
#include "llvm/Support/MD5.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include "llvm/Support/SHA1.h"
|
||||
|
|
@ -70,67 +70,6 @@ OutputSection::OutputSection(StringRef Name, uint32_t Type, uint64_t Flags)
|
|||
/*Link*/ 0),
|
||||
SectionIndex(INT_MAX) {}
|
||||
|
||||
static bool compareByFilePosition(InputSection *A, InputSection *B) {
|
||||
// Synthetic doesn't have link order dependecy, stable_sort will keep it last
|
||||
if (A->kind() == InputSectionBase::Synthetic ||
|
||||
B->kind() == InputSectionBase::Synthetic)
|
||||
return false;
|
||||
InputSection *LA = A->getLinkOrderDep();
|
||||
InputSection *LB = B->getLinkOrderDep();
|
||||
OutputSection *AOut = LA->getParent();
|
||||
OutputSection *BOut = LB->getParent();
|
||||
if (AOut != BOut)
|
||||
return AOut->SectionIndex < BOut->SectionIndex;
|
||||
return LA->OutSecOff < LB->OutSecOff;
|
||||
}
|
||||
|
||||
template <class ELFT> static void finalizeShtGroup(OutputSection *Sec) {
|
||||
// sh_link field for SHT_GROUP sections should contain the section index of
|
||||
// the symbol table.
|
||||
Sec->Link = InX::SymTab->getParent()->SectionIndex;
|
||||
|
||||
// sh_info then contain index of an entry in symbol table section which
|
||||
// provides signature of the section group.
|
||||
elf::ObjectFile<ELFT> *Obj = Sec->Sections[0]->getFile<ELFT>();
|
||||
assert(Config->Relocatable && Sec->Sections.size() == 1);
|
||||
ArrayRef<SymbolBody *> Symbols = Obj->getSymbols();
|
||||
Sec->Info = InX::SymTab->getSymbolIndex(Symbols[Sec->Sections[0]->Info - 1]);
|
||||
}
|
||||
|
||||
template <class ELFT> void OutputSection::finalize() {
|
||||
if ((this->Flags & SHF_LINK_ORDER) && !this->Sections.empty()) {
|
||||
std::sort(Sections.begin(), Sections.end(), compareByFilePosition);
|
||||
assignOffsets();
|
||||
|
||||
// We must preserve the link order dependency of sections with the
|
||||
// SHF_LINK_ORDER flag. The dependency is indicated by the sh_link field. We
|
||||
// need to translate the InputSection sh_link to the OutputSection sh_link,
|
||||
// all InputSections in the OutputSection have the same dependency.
|
||||
if (auto *D = this->Sections.front()->getLinkOrderDep())
|
||||
this->Link = D->getParent()->SectionIndex;
|
||||
}
|
||||
|
||||
uint32_t Type = this->Type;
|
||||
if (Type == SHT_GROUP) {
|
||||
finalizeShtGroup<ELFT>(this);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Config->CopyRelocs || (Type != SHT_RELA && Type != SHT_REL))
|
||||
return;
|
||||
|
||||
InputSection *First = Sections[0];
|
||||
if (isa<SyntheticSection>(First))
|
||||
return;
|
||||
|
||||
this->Link = InX::SymTab->getParent()->SectionIndex;
|
||||
// sh_info for SHT_REL[A] sections should contain the section header index of
|
||||
// the section to which the relocation applies.
|
||||
InputSectionBase *S = First->getRelocatedSection();
|
||||
Info = S->getOutputSection()->SectionIndex;
|
||||
Flags |= SHF_INFO_LINK;
|
||||
}
|
||||
|
||||
static uint64_t updateOffset(uint64_t Off, InputSection *S) {
|
||||
Off = alignTo(Off, S->Alignment);
|
||||
S->OutSecOff = Off;
|
||||
|
|
@ -162,9 +101,12 @@ void OutputSection::addSection(InputSection *S) {
|
|||
// This function is called after we sort input sections
|
||||
// and scan relocations to setup sections' offsets.
|
||||
void OutputSection::assignOffsets() {
|
||||
OutputSectionCommand *Cmd = Script->getCmd(this);
|
||||
uint64_t Off = 0;
|
||||
for (InputSection *S : Sections)
|
||||
Off = updateOffset(Off, S);
|
||||
for (BaseCommand *Base : Cmd->Commands)
|
||||
if (auto *ISD = dyn_cast<InputSectionDescription>(Base))
|
||||
for (InputSection *S : ISD->Sections)
|
||||
Off = updateOffset(Off, S);
|
||||
this->Size = Off;
|
||||
}
|
||||
|
||||
|
|
@ -333,6 +275,31 @@ void elf::reportDiscarded(InputSectionBase *IS) {
|
|||
|
||||
void OutputSectionFactory::addInputSec(InputSectionBase *IS,
|
||||
StringRef OutsecName) {
|
||||
// Sections with the SHT_GROUP attribute reach here only when the - r option
|
||||
// is given. Such sections define "section groups", and InputFiles.cpp has
|
||||
// dedup'ed section groups by their signatures. For the -r, we want to pass
|
||||
// through all SHT_GROUP sections without merging them because merging them
|
||||
// creates broken section contents.
|
||||
if (IS->Type == SHT_GROUP) {
|
||||
OutputSection *Out = nullptr;
|
||||
addInputSec(IS, OutsecName, Out);
|
||||
return;
|
||||
}
|
||||
|
||||
// Imagine .zed : { *(.foo) *(.bar) } script. Both foo and bar may have
|
||||
// relocation sections .rela.foo and .rela.bar for example. Most tools do
|
||||
// not allow multiple REL[A] sections for output section. Hence we
|
||||
// should combine these relocation sections into single output.
|
||||
// We skip synthetic sections because it can be .rela.dyn/.rela.plt or any
|
||||
// other REL[A] sections created by linker itself.
|
||||
if (!isa<SyntheticSection>(IS) &&
|
||||
(IS->Type == SHT_REL || IS->Type == SHT_RELA)) {
|
||||
auto *Sec = cast<InputSection>(IS);
|
||||
OutputSection *Out = Sec->getRelocatedSection()->getOutputSection();
|
||||
addInputSec(IS, OutsecName, Out->RelocationSection);
|
||||
return;
|
||||
}
|
||||
|
||||
SectionKey Key = createKey(IS, OutsecName);
|
||||
OutputSection *&Sec = Map[Key];
|
||||
return addInputSec(IS, OutsecName, Sec);
|
||||
|
|
@ -346,10 +313,6 @@ void OutputSectionFactory::addInputSec(InputSectionBase *IS,
|
|||
return;
|
||||
}
|
||||
|
||||
uint64_t Flags = IS->Flags;
|
||||
if (!Config->Relocatable)
|
||||
Flags &= ~(uint64_t)SHF_GROUP;
|
||||
|
||||
if (Sec) {
|
||||
if (getIncompatibleFlags(Sec->Flags) != getIncompatibleFlags(IS->Flags))
|
||||
error("incompatible section flags for " + Sec->Name +
|
||||
|
|
@ -366,9 +329,9 @@ void OutputSectionFactory::addInputSec(InputSectionBase *IS,
|
|||
"\n>>> output section " + Sec->Name + ": " +
|
||||
getELFSectionTypeName(Config->EMachine, Sec->Type));
|
||||
}
|
||||
Sec->Flags |= Flags;
|
||||
Sec->Flags |= IS->Flags;
|
||||
} else {
|
||||
Sec = make<OutputSection>(OutsecName, IS->Type, Flags);
|
||||
Sec = make<OutputSection>(OutsecName, IS->Type, IS->Flags);
|
||||
OutputSections.push_back(Sec);
|
||||
}
|
||||
|
||||
|
|
@ -405,8 +368,3 @@ template void OutputSection::writeHeaderTo<ELF32LE>(ELF32LE::Shdr *Shdr);
|
|||
template void OutputSection::writeHeaderTo<ELF32BE>(ELF32BE::Shdr *Shdr);
|
||||
template void OutputSection::writeHeaderTo<ELF64LE>(ELF64LE::Shdr *Shdr);
|
||||
template void OutputSection::writeHeaderTo<ELF64BE>(ELF64BE::Shdr *Shdr);
|
||||
|
||||
template void OutputSection::finalize<ELF32LE>();
|
||||
template void OutputSection::finalize<ELF32BE>();
|
||||
template void OutputSection::finalize<ELF64LE>();
|
||||
template void OutputSection::finalize<ELF64BE>();
|
||||
|
|
|
|||
|
|
@ -67,6 +67,11 @@ public:
|
|||
// formula: Off = Off_first + VA - VA_first.
|
||||
OutputSection *FirstInPtLoad = nullptr;
|
||||
|
||||
// Pointer to a relocation section for this section. Usually nullptr because
|
||||
// we consume relocations, but if --emit-relocs is specified (which is rare),
|
||||
// it may have a non-null value.
|
||||
OutputSection *RelocationSection = nullptr;
|
||||
|
||||
// The following fields correspond to Elf_Shdr members.
|
||||
uint64_t Size = 0;
|
||||
uint64_t Offset = 0;
|
||||
|
|
@ -78,7 +83,6 @@ public:
|
|||
void sort(std::function<int(InputSectionBase *S)> Order);
|
||||
void sortInitFini();
|
||||
void sortCtorsDtors();
|
||||
template <class ELFT> void finalize();
|
||||
void assignOffsets();
|
||||
std::vector<InputSection *> Sections;
|
||||
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@
|
|||
|
||||
#include "Relocations.h"
|
||||
#include "Config.h"
|
||||
#include "LinkerScript.h"
|
||||
#include "Memory.h"
|
||||
#include "OutputSections.h"
|
||||
#include "Strings.h"
|
||||
|
|
@ -967,48 +968,51 @@ template <class ELFT> void elf::scanRelocations(InputSectionBase &S) {
|
|||
// in the Sections vector, and recalculate the InputSection output section
|
||||
// offsets.
|
||||
// This may invalidate any output section offsets stored outside of InputSection
|
||||
void ThunkCreator::mergeThunks(OutputSection *OS,
|
||||
std::vector<ThunkSection *> &Thunks) {
|
||||
// Order Thunks in ascending OutSecOff
|
||||
auto ThunkCmp = [](const ThunkSection *A, const ThunkSection *B) {
|
||||
return A->OutSecOff < B->OutSecOff;
|
||||
};
|
||||
std::stable_sort(Thunks.begin(), Thunks.end(), ThunkCmp);
|
||||
void ThunkCreator::mergeThunks() {
|
||||
for (auto &KV : ThunkSections) {
|
||||
std::vector<InputSection *> *ISR = KV.first;
|
||||
std::vector<ThunkSection *> &Thunks = KV.second;
|
||||
|
||||
// Merge sorted vectors of Thunks and InputSections by OutSecOff
|
||||
std::vector<InputSection *> Tmp;
|
||||
Tmp.reserve(OS->Sections.size() + Thunks.size());
|
||||
auto MergeCmp = [](const InputSection *A, const InputSection *B) {
|
||||
// std::merge requires a strict weak ordering.
|
||||
if (A->OutSecOff < B->OutSecOff)
|
||||
return true;
|
||||
if (A->OutSecOff == B->OutSecOff)
|
||||
// Check if Thunk is immediately before any specific Target InputSection
|
||||
// for example Mips LA25 Thunks.
|
||||
if (auto *TA = dyn_cast<ThunkSection>(A))
|
||||
if (TA && TA->getTargetInputSection() == B)
|
||||
return true;
|
||||
return false;
|
||||
};
|
||||
std::merge(OS->Sections.begin(), OS->Sections.end(), Thunks.begin(),
|
||||
Thunks.end(), std::back_inserter(Tmp), MergeCmp);
|
||||
OS->Sections = std::move(Tmp);
|
||||
OS->assignOffsets();
|
||||
// Order Thunks in ascending OutSecOff
|
||||
auto ThunkCmp = [](const ThunkSection *A, const ThunkSection *B) {
|
||||
return A->OutSecOff < B->OutSecOff;
|
||||
};
|
||||
std::stable_sort(Thunks.begin(), Thunks.end(), ThunkCmp);
|
||||
|
||||
// Merge sorted vectors of Thunks and InputSections by OutSecOff
|
||||
std::vector<InputSection *> Tmp;
|
||||
Tmp.reserve(ISR->size() + Thunks.size());
|
||||
auto MergeCmp = [](const InputSection *A, const InputSection *B) {
|
||||
// std::merge requires a strict weak ordering.
|
||||
if (A->OutSecOff < B->OutSecOff)
|
||||
return true;
|
||||
if (A->OutSecOff == B->OutSecOff)
|
||||
// Check if Thunk is immediately before any specific Target InputSection
|
||||
// for example Mips LA25 Thunks.
|
||||
if (auto *TA = dyn_cast<ThunkSection>(A))
|
||||
if (TA && TA->getTargetInputSection() == B)
|
||||
return true;
|
||||
return false;
|
||||
};
|
||||
std::merge(ISR->begin(), ISR->end(), Thunks.begin(), Thunks.end(),
|
||||
std::back_inserter(Tmp), MergeCmp);
|
||||
*ISR = std::move(Tmp);
|
||||
}
|
||||
}
|
||||
|
||||
ThunkSection *ThunkCreator::getOSThunkSec(ThunkSection *&TS,
|
||||
OutputSection *OS) {
|
||||
if (TS == nullptr) {
|
||||
ThunkSection *ThunkCreator::getOSThunkSec(OutputSection *OS,
|
||||
std::vector<InputSection *> *ISR) {
|
||||
if (CurTS == nullptr) {
|
||||
uint32_t Off = 0;
|
||||
for (auto *IS : OS->Sections) {
|
||||
Off = IS->OutSecOff + IS->getSize();
|
||||
if ((IS->Flags & SHF_EXECINSTR) == 0)
|
||||
break;
|
||||
}
|
||||
TS = make<ThunkSection>(OS, Off);
|
||||
ThunkSections[OS].push_back(TS);
|
||||
CurTS = make<ThunkSection>(OS, Off);
|
||||
ThunkSections[ISR].push_back(CurTS);
|
||||
}
|
||||
return TS;
|
||||
return CurTS;
|
||||
}
|
||||
|
||||
ThunkSection *ThunkCreator::getISThunkSec(InputSection *IS, OutputSection *OS) {
|
||||
|
|
@ -1017,7 +1021,21 @@ ThunkSection *ThunkCreator::getISThunkSec(InputSection *IS, OutputSection *OS) {
|
|||
return TS;
|
||||
auto *TOS = IS->getParent();
|
||||
TS = make<ThunkSection>(TOS, IS->OutSecOff);
|
||||
ThunkSections[TOS].push_back(TS);
|
||||
|
||||
// Find InputSectionRange within TOS that IS is in
|
||||
OutputSectionCommand *C = Script->getCmd(TOS);
|
||||
std::vector<InputSection *> *Range = nullptr;
|
||||
for (BaseCommand *BC : C->Commands)
|
||||
if (auto *ISD = dyn_cast<InputSectionDescription> (BC)) {
|
||||
InputSection *first = ISD->Sections.front();
|
||||
InputSection *last = ISD->Sections.back();
|
||||
if (IS->OutSecOff >= first->OutSecOff &&
|
||||
IS->OutSecOff <= last->OutSecOff) {
|
||||
Range = &ISD->Sections;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ThunkSections[Range].push_back(TS);
|
||||
ThunkedSections[IS] = TS;
|
||||
return TS;
|
||||
}
|
||||
|
|
@ -1030,6 +1048,27 @@ std::pair<Thunk *, bool> ThunkCreator::getThunk(SymbolBody &Body,
|
|||
return std::make_pair(res.first->second, res.second);
|
||||
}
|
||||
|
||||
// Call Fn on every executable InputSection accessed via the linker script
|
||||
// InputSectionDescription::Sections.
|
||||
void ThunkCreator::forEachExecInputSection(
|
||||
ArrayRef<OutputSectionCommand *> OutputSections,
|
||||
std::function<void(OutputSection *, std::vector<InputSection *> *,
|
||||
InputSection *)>
|
||||
Fn) {
|
||||
for (OutputSectionCommand *Cmd : OutputSections) {
|
||||
OutputSection *OS = Cmd->Sec;
|
||||
if (!(OS->Flags & SHF_ALLOC) || !(OS->Flags & SHF_EXECINSTR))
|
||||
continue;
|
||||
if (OutputSectionCommand *C = Script->getCmd(OS))
|
||||
for (BaseCommand *BC : C->Commands)
|
||||
if (auto *ISD = dyn_cast<InputSectionDescription>(BC)) {
|
||||
CurTS = nullptr;
|
||||
for (InputSection* IS : ISD->Sections)
|
||||
Fn(OS, &ISD->Sections, IS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Process all relocations from the InputSections that have been assigned
|
||||
// to OutputSections and redirect through Thunks if needed.
|
||||
//
|
||||
|
|
@ -1040,42 +1079,41 @@ std::pair<Thunk *, bool> ThunkCreator::getThunk(SymbolBody &Body,
|
|||
//
|
||||
// FIXME: All Thunks are assumed to be in range of the relocation. Range
|
||||
// extension Thunks are not yet supported.
|
||||
bool ThunkCreator::createThunks(ArrayRef<OutputSection *> OutputSections) {
|
||||
bool ThunkCreator::createThunks(
|
||||
ArrayRef<OutputSectionCommand *> OutputSections) {
|
||||
// Create all the Thunks and insert them into synthetic ThunkSections. The
|
||||
// ThunkSections are later inserted back into the OutputSection.
|
||||
|
||||
// We separate the creation of ThunkSections from the insertion of the
|
||||
// ThunkSections back into the OutputSection as ThunkSections are not always
|
||||
// inserted into the same OutputSection as the caller.
|
||||
for (OutputSection *OS : OutputSections) {
|
||||
ThunkSection *OSTS = nullptr;
|
||||
for (InputSection *IS : OS->Sections) {
|
||||
for (Relocation &Rel : IS->Relocations) {
|
||||
SymbolBody &Body = *Rel.Sym;
|
||||
if (!Target->needsThunk(Rel.Expr, Rel.Type, IS->File, Body))
|
||||
continue;
|
||||
Thunk *T;
|
||||
bool IsNew;
|
||||
std::tie(T, IsNew) = getThunk(Body, Rel.Type);
|
||||
if (IsNew) {
|
||||
// Find or create a ThunkSection for the new Thunk
|
||||
ThunkSection *TS;
|
||||
if (auto *TIS = T->getTargetInputSection())
|
||||
TS = getISThunkSec(TIS, OS);
|
||||
else
|
||||
TS = getOSThunkSec(OSTS, OS);
|
||||
TS->addThunk(T);
|
||||
forEachExecInputSection(
|
||||
OutputSections, [=](OutputSection *OS, std::vector<InputSection*> *ISR,
|
||||
InputSection *IS) {
|
||||
for (Relocation &Rel : IS->Relocations) {
|
||||
SymbolBody &Body = *Rel.Sym;
|
||||
if (!Target->needsThunk(Rel.Expr, Rel.Type, IS->File, Body))
|
||||
continue;
|
||||
Thunk *T;
|
||||
bool IsNew;
|
||||
std::tie(T, IsNew) = getThunk(Body, Rel.Type);
|
||||
if (IsNew) {
|
||||
// Find or create a ThunkSection for the new Thunk
|
||||
ThunkSection *TS;
|
||||
if (auto *TIS = T->getTargetInputSection())
|
||||
TS = getISThunkSec(TIS, OS);
|
||||
else
|
||||
TS = getOSThunkSec(OS, ISR);
|
||||
TS->addThunk(T);
|
||||
}
|
||||
// Redirect relocation to Thunk, we never go via the PLT to a Thunk
|
||||
Rel.Sym = T->ThunkSym;
|
||||
Rel.Expr = fromPlt(Rel.Expr);
|
||||
}
|
||||
// Redirect relocation to Thunk, we never go via the PLT to a Thunk
|
||||
Rel.Sym = T->ThunkSym;
|
||||
Rel.Expr = fromPlt(Rel.Expr);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Merge all created synthetic ThunkSections back into OutputSection
|
||||
for (auto &KV : ThunkSections)
|
||||
mergeThunks(KV.first, KV.second);
|
||||
mergeThunks();
|
||||
return !ThunkSections.empty();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ class SymbolBody;
|
|||
class InputSection;
|
||||
class InputSectionBase;
|
||||
class OutputSection;
|
||||
struct OutputSectionCommand;
|
||||
|
||||
// List of target-independent relocation types. Relocations read
|
||||
// from files are converted to these types so that the main code
|
||||
|
|
@ -123,12 +124,18 @@ class Thunk;
|
|||
class ThunkCreator {
|
||||
public:
|
||||
// Return true if Thunks have been added to OutputSections
|
||||
bool createThunks(ArrayRef<OutputSection *> OutputSections);
|
||||
bool createThunks(ArrayRef<OutputSectionCommand *> OutputSections);
|
||||
|
||||
private:
|
||||
void mergeThunks(OutputSection *OS, std::vector<ThunkSection *> &Thunks);
|
||||
ThunkSection *getOSThunkSec(ThunkSection *&TS, OutputSection *OS);
|
||||
void mergeThunks();
|
||||
ThunkSection *getOSThunkSec(OutputSection *OS,
|
||||
std::vector<InputSection *> *ISR);
|
||||
ThunkSection *getISThunkSec(InputSection *IS, OutputSection *OS);
|
||||
void forEachExecInputSection(
|
||||
ArrayRef<OutputSectionCommand *> OutputSections,
|
||||
std::function<void(OutputSection *, std::vector<InputSection *> *,
|
||||
InputSection *)>
|
||||
Fn);
|
||||
std::pair<Thunk *, bool> getThunk(SymbolBody &Body, uint32_t Type);
|
||||
|
||||
// Track Symbols that already have a Thunk
|
||||
|
|
@ -138,7 +145,11 @@ private:
|
|||
llvm::DenseMap<InputSection *, ThunkSection *> ThunkedSections;
|
||||
|
||||
// Track the ThunksSections that need to be inserted into an OutputSection
|
||||
std::map<OutputSection *, std::vector<ThunkSection *>> ThunkSections;
|
||||
std::map<std::vector<InputSection *> *, std::vector<ThunkSection *>>
|
||||
ThunkSections;
|
||||
|
||||
// The ThunkSection for this vector of InputSections
|
||||
ThunkSection *CurTS;
|
||||
};
|
||||
|
||||
// Return a int64_t to make sure we get the sign extension out of the way as
|
||||
|
|
|
|||
|
|
@ -25,8 +25,8 @@
|
|||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/StringSwitch.h"
|
||||
#include "llvm/BinaryFormat/ELF.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/ELF.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
|
|
@ -76,6 +76,7 @@ private:
|
|||
BytesDataCommand *readBytesDataCommand(StringRef Tok);
|
||||
uint32_t readFill();
|
||||
uint32_t parseFill(StringRef Tok);
|
||||
void readSectionAddressType(OutputSectionCommand *Cmd);
|
||||
OutputSectionCommand *readOutputSectionDescription(StringRef OutSec);
|
||||
std::vector<StringRef> readOutputSectionPhdrs();
|
||||
InputSectionDescription *readInputSectionDescription(StringRef Tok);
|
||||
|
|
@ -127,16 +128,16 @@ static void moveAbsRight(ExprValue &A, ExprValue &B) {
|
|||
if (A.isAbsolute())
|
||||
std::swap(A, B);
|
||||
if (!B.isAbsolute())
|
||||
error("At least one side of the expression must be absolute");
|
||||
error(A.Loc + ": at least one side of the expression must be absolute");
|
||||
}
|
||||
|
||||
static ExprValue add(ExprValue A, ExprValue B) {
|
||||
moveAbsRight(A, B);
|
||||
return {A.Sec, A.ForceAbsolute, A.Val + B.getValue()};
|
||||
return {A.Sec, A.ForceAbsolute, A.Val + B.getValue(), A.Loc};
|
||||
}
|
||||
|
||||
static ExprValue sub(ExprValue A, ExprValue B) {
|
||||
return {A.Sec, A.Val - B.getValue()};
|
||||
return {A.Sec, A.Val - B.getValue(), A.Loc};
|
||||
}
|
||||
|
||||
static ExprValue mul(ExprValue A, ExprValue B) {
|
||||
|
|
@ -153,13 +154,13 @@ static ExprValue div(ExprValue A, ExprValue B) {
|
|||
static ExprValue bitAnd(ExprValue A, ExprValue B) {
|
||||
moveAbsRight(A, B);
|
||||
return {A.Sec, A.ForceAbsolute,
|
||||
(A.getValue() & B.getValue()) - A.getSecAddr()};
|
||||
(A.getValue() & B.getValue()) - A.getSecAddr(), A.Loc};
|
||||
}
|
||||
|
||||
static ExprValue bitOr(ExprValue A, ExprValue B) {
|
||||
moveAbsRight(A, B);
|
||||
return {A.Sec, A.ForceAbsolute,
|
||||
(A.getValue() | B.getValue()) - A.getSecAddr()};
|
||||
(A.getValue() | B.getValue()) - A.getSecAddr(), A.Loc};
|
||||
}
|
||||
|
||||
void ScriptParser::readDynamicList() {
|
||||
|
|
@ -563,16 +564,42 @@ uint32_t ScriptParser::readFill() {
|
|||
return V;
|
||||
}
|
||||
|
||||
// Reads an expression and/or the special directive "(NOLOAD)" for an
|
||||
// output section definition.
|
||||
//
|
||||
// An output section name can be followed by an address expression
|
||||
// and/or by "(NOLOAD)". This grammar is not LL(1) because "(" can be
|
||||
// interpreted as either the beginning of some expression or "(NOLOAD)".
|
||||
//
|
||||
// https://sourceware.org/binutils/docs/ld/Output-Section-Address.html
|
||||
// https://sourceware.org/binutils/docs/ld/Output-Section-Type.html
|
||||
void ScriptParser::readSectionAddressType(OutputSectionCommand *Cmd) {
|
||||
if (consume("(")) {
|
||||
if (consume("NOLOAD")) {
|
||||
expect(")");
|
||||
Cmd->Noload = true;
|
||||
return;
|
||||
}
|
||||
Cmd->AddrExpr = readExpr();
|
||||
expect(")");
|
||||
} else {
|
||||
Cmd->AddrExpr = readExpr();
|
||||
}
|
||||
|
||||
if (consume("(")) {
|
||||
expect("NOLOAD");
|
||||
expect(")");
|
||||
Cmd->Noload = true;
|
||||
}
|
||||
}
|
||||
|
||||
OutputSectionCommand *
|
||||
ScriptParser::readOutputSectionDescription(StringRef OutSec) {
|
||||
OutputSectionCommand *Cmd =
|
||||
Script->createOutputSectionCommand(OutSec, getCurrentLocation());
|
||||
|
||||
// Read an address expression.
|
||||
// https://sourceware.org/binutils/docs/ld/Output-Section-Address.html
|
||||
if (peek() != ":")
|
||||
Cmd->AddrExpr = readExpr();
|
||||
|
||||
readSectionAddressType(Cmd);
|
||||
expect(":");
|
||||
|
||||
if (consume("AT"))
|
||||
|
|
@ -859,7 +886,9 @@ Expr ScriptParser::readPrimary() {
|
|||
if (Tok == "ADDR") {
|
||||
StringRef Name = readParenLiteral();
|
||||
OutputSectionCommand *Cmd = Script->getOrCreateOutputSectionCommand(Name);
|
||||
return [=]() -> ExprValue { return {checkSection(Cmd, Location), 0}; };
|
||||
return [=]() -> ExprValue {
|
||||
return {checkSection(Cmd, Location), 0, Location};
|
||||
};
|
||||
}
|
||||
if (Tok == "ALIGN") {
|
||||
expect("(");
|
||||
|
|
|
|||
|
|
@ -156,7 +156,7 @@ template <class ELFT> void SymbolTable<ELFT>::trace(StringRef Name) {
|
|||
|
||||
// Rename SYM as __wrap_SYM. The original symbol is preserved as __real_SYM.
|
||||
// Used to implement --wrap.
|
||||
template <class ELFT> void SymbolTable<ELFT>::wrap(StringRef Name) {
|
||||
template <class ELFT> void SymbolTable<ELFT>::addSymbolWrap(StringRef Name) {
|
||||
SymbolBody *B = find(Name);
|
||||
if (!B)
|
||||
return;
|
||||
|
|
@ -164,16 +164,16 @@ template <class ELFT> void SymbolTable<ELFT>::wrap(StringRef Name) {
|
|||
Symbol *Real = addUndefined(Saver.save("__real_" + Name));
|
||||
Symbol *Wrap = addUndefined(Saver.save("__wrap_" + Name));
|
||||
|
||||
// We rename symbols by replacing the old symbol's SymbolBody with the new
|
||||
// symbol's SymbolBody. This causes all SymbolBody pointers referring to the
|
||||
// old symbol to instead refer to the new symbol.
|
||||
memcpy(Real->Body.buffer, Sym->Body.buffer, sizeof(Sym->Body));
|
||||
memcpy(Sym->Body.buffer, Wrap->Body.buffer, sizeof(Wrap->Body));
|
||||
// Tell LTO not to eliminate this symbol
|
||||
Wrap->IsUsedInRegularObj = true;
|
||||
|
||||
Config->RenamedSymbols[Real] = RenamedSymbol{Sym, Real->Binding};
|
||||
Config->RenamedSymbols[Sym] = RenamedSymbol{Wrap, Sym->Binding};
|
||||
}
|
||||
|
||||
// Creates alias for symbol. Used to implement --defsym=ALIAS=SYM.
|
||||
template <class ELFT>
|
||||
void SymbolTable<ELFT>::alias(StringRef Alias, StringRef Name) {
|
||||
template <class ELFT> void SymbolTable<ELFT>::addSymbolAlias(StringRef Alias,
|
||||
StringRef Name) {
|
||||
SymbolBody *B = find(Name);
|
||||
if (!B) {
|
||||
error("-defsym: undefined symbol: " + Name);
|
||||
|
|
@ -181,7 +181,27 @@ void SymbolTable<ELFT>::alias(StringRef Alias, StringRef Name) {
|
|||
}
|
||||
Symbol *Sym = B->symbol();
|
||||
Symbol *AliasSym = addUndefined(Alias);
|
||||
memcpy(AliasSym->Body.buffer, Sym->Body.buffer, sizeof(AliasSym->Body));
|
||||
|
||||
// Tell LTO not to eliminate this symbol
|
||||
Sym->IsUsedInRegularObj = true;
|
||||
Config->RenamedSymbols[AliasSym] = RenamedSymbol{Sym, AliasSym->Binding};
|
||||
}
|
||||
|
||||
// Apply symbol renames created by -wrap and -defsym. The renames are created
|
||||
// before LTO in addSymbolWrap() and addSymbolAlias() to have a chance to inform
|
||||
// LTO (if LTO is running) not to include these symbols in IPO. Now that the
|
||||
// symbols are finalized, we can perform the replacement.
|
||||
template <class ELFT> void SymbolTable<ELFT>::applySymbolRenames() {
|
||||
for (auto &KV : Config->RenamedSymbols) {
|
||||
Symbol *Sym = KV.first;
|
||||
Symbol *Rename = KV.second.Target;
|
||||
Sym->Binding = KV.second.OrigBinding;
|
||||
|
||||
// We rename symbols by replacing the old symbol's SymbolBody with the new
|
||||
// symbol's SymbolBody. This causes all SymbolBody pointers referring to the
|
||||
// old symbol to instead refer to the new symbol.
|
||||
memcpy(Sym->Body.buffer, Rename->Body.buffer, sizeof(Sym->Body));
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t getMinVisibility(uint8_t VA, uint8_t VB) {
|
||||
|
|
|
|||
|
|
@ -39,6 +39,9 @@ template <class ELFT> class SymbolTable {
|
|||
public:
|
||||
void addFile(InputFile *File);
|
||||
void addCombinedLTOObject();
|
||||
void addSymbolAlias(StringRef Alias, StringRef Name);
|
||||
void addSymbolWrap(StringRef Name);
|
||||
void applySymbolRenames();
|
||||
|
||||
ArrayRef<Symbol *> getSymbols() const { return SymVector; }
|
||||
ArrayRef<ObjectFile<ELFT> *> getObjectFiles() const { return ObjectFiles; }
|
||||
|
|
@ -85,8 +88,6 @@ public:
|
|||
SymbolBody *findInCurrentDSO(StringRef Name);
|
||||
|
||||
void trace(StringRef Name);
|
||||
void wrap(StringRef Name);
|
||||
void alias(StringRef Alias, StringRef Name);
|
||||
|
||||
private:
|
||||
std::vector<SymbolBody *> findByVersion(SymbolVersion Ver);
|
||||
|
|
|
|||
|
|
@ -264,15 +264,14 @@ Defined::Defined(Kind K, StringRefZ Name, bool IsLocal, uint8_t StOther,
|
|||
: SymbolBody(K, Name, IsLocal, StOther, Type) {}
|
||||
|
||||
template <class ELFT> bool DefinedRegular::isMipsPIC() const {
|
||||
typedef typename ELFT::Ehdr Elf_Ehdr;
|
||||
if (!Section || !isFunc())
|
||||
return false;
|
||||
|
||||
auto *Sec = cast<InputSectionBase>(Section);
|
||||
const Elf_Ehdr *Hdr = Sec->template getFile<ELFT>()->getObj().getHeader();
|
||||
return (this->StOther & STO_MIPS_MIPS16) == STO_MIPS_PIC ||
|
||||
(cast<InputSectionBase>(Section)
|
||||
->template getFile<ELFT>()
|
||||
->getObj()
|
||||
.getHeader()
|
||||
->e_flags &
|
||||
EF_MIPS_PIC);
|
||||
(Hdr->e_flags & EF_MIPS_PIC);
|
||||
}
|
||||
|
||||
Undefined::Undefined(StringRefZ Name, bool IsLocal, uint8_t StOther,
|
||||
|
|
|
|||
|
|
@ -27,9 +27,9 @@
|
|||
#include "Threads.h"
|
||||
#include "Writer.h"
|
||||
#include "lld/Config/Version.h"
|
||||
#include "llvm/BinaryFormat/Dwarf.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFDebugPubTable.h"
|
||||
#include "llvm/Object/ELFObjectFile.h"
|
||||
#include "llvm/Support/Dwarf.h"
|
||||
#include "llvm/Support/Endian.h"
|
||||
#include "llvm/Support/MD5.h"
|
||||
#include "llvm/Support/RandomNumberGenerator.h"
|
||||
|
|
@ -1691,49 +1691,44 @@ static uint32_t hash(StringRef Str) {
|
|||
return R;
|
||||
}
|
||||
|
||||
static std::vector<std::pair<uint64_t, uint64_t>>
|
||||
readCuList(DWARFContext &Dwarf, InputSection *Sec) {
|
||||
std::vector<std::pair<uint64_t, uint64_t>> Ret;
|
||||
static std::vector<CompilationUnitEntry> readCuList(DWARFContext &Dwarf,
|
||||
InputSection *Sec) {
|
||||
std::vector<CompilationUnitEntry> Ret;
|
||||
for (std::unique_ptr<DWARFCompileUnit> &CU : Dwarf.compile_units())
|
||||
Ret.push_back({Sec->OutSecOff + CU->getOffset(), CU->getLength() + 4});
|
||||
return Ret;
|
||||
}
|
||||
|
||||
static InputSection *findSection(ArrayRef<InputSectionBase *> Arr,
|
||||
uint64_t Offset) {
|
||||
for (InputSectionBase *S : Arr)
|
||||
if (auto *IS = dyn_cast_or_null<InputSection>(S))
|
||||
if (IS != &InputSection::Discarded && IS->Live &&
|
||||
Offset >= IS->getOffsetInFile() &&
|
||||
Offset < IS->getOffsetInFile() + IS->getSize())
|
||||
return IS;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static std::vector<AddressEntry>
|
||||
readAddressArea(DWARFContext &Dwarf, InputSection *Sec, size_t CurrentCU) {
|
||||
static std::vector<AddressEntry> readAddressArea(DWARFContext &Dwarf,
|
||||
InputSection *Sec) {
|
||||
std::vector<AddressEntry> Ret;
|
||||
|
||||
uint32_t CurrentCu = 0;
|
||||
for (std::unique_ptr<DWARFCompileUnit> &CU : Dwarf.compile_units()) {
|
||||
DWARFAddressRangesVector Ranges;
|
||||
CU->collectAddressRanges(Ranges);
|
||||
|
||||
ArrayRef<InputSectionBase *> Sections = Sec->File->getSections();
|
||||
for (DWARFAddressRange &R : Ranges)
|
||||
if (InputSection *S = findSection(Sections, R.LowPC))
|
||||
Ret.push_back({S, R.LowPC - S->getOffsetInFile(),
|
||||
R.HighPC - S->getOffsetInFile(), CurrentCU});
|
||||
++CurrentCU;
|
||||
for (DWARFAddressRange &R : Ranges) {
|
||||
InputSectionBase *S = Sections[R.SectionIndex];
|
||||
if (!S || S == &InputSection::Discarded || !S->Live)
|
||||
continue;
|
||||
// Range list with zero size has no effect.
|
||||
if (R.LowPC == R.HighPC)
|
||||
continue;
|
||||
Ret.push_back({cast<InputSection>(S), R.LowPC, R.HighPC, CurrentCu});
|
||||
}
|
||||
++CurrentCu;
|
||||
}
|
||||
return Ret;
|
||||
}
|
||||
|
||||
static std::vector<std::pair<StringRef, uint8_t>>
|
||||
readPubNamesAndTypes(DWARFContext &Dwarf, bool IsLE) {
|
||||
static std::vector<NameTypeEntry> readPubNamesAndTypes(DWARFContext &Dwarf,
|
||||
bool IsLE) {
|
||||
StringRef Data[] = {Dwarf.getGnuPubNamesSection(),
|
||||
Dwarf.getGnuPubTypesSection()};
|
||||
|
||||
std::vector<std::pair<StringRef, uint8_t>> Ret;
|
||||
std::vector<NameTypeEntry> Ret;
|
||||
for (StringRef D : Data) {
|
||||
DWARFDebugPubTable PubTable(D, IsLE, true);
|
||||
for (const DWARFDebugPubTable::Set &Set : PubTable.getData())
|
||||
|
|
@ -1743,52 +1738,77 @@ readPubNamesAndTypes(DWARFContext &Dwarf, bool IsLE) {
|
|||
return Ret;
|
||||
}
|
||||
|
||||
class ObjInfoTy : public llvm::LoadedObjectInfo {
|
||||
uint64_t getSectionLoadAddress(const object::SectionRef &Sec) const override {
|
||||
auto &S = static_cast<const object::ELFSectionRef &>(Sec);
|
||||
if (S.getFlags() & ELF::SHF_ALLOC)
|
||||
return S.getOffset();
|
||||
return 0;
|
||||
static std::vector<InputSection *> getDebugInfoSections() {
|
||||
std::vector<InputSection *> Ret;
|
||||
for (InputSectionBase *S : InputSections)
|
||||
if (InputSection *IS = dyn_cast<InputSection>(S))
|
||||
if (IS->getParent() && IS->Name == ".debug_info")
|
||||
Ret.push_back(IS);
|
||||
return Ret;
|
||||
}
|
||||
|
||||
void GdbIndexSection::buildIndex() {
|
||||
std::vector<InputSection *> V = getDebugInfoSections();
|
||||
if (V.empty())
|
||||
return;
|
||||
|
||||
for (InputSection *Sec : V)
|
||||
Chunks.push_back(readDwarf(Sec));
|
||||
|
||||
uint32_t CuId = 0;
|
||||
for (GdbIndexChunk &D : Chunks) {
|
||||
for (AddressEntry &E : D.AddressArea)
|
||||
E.CuIndex += CuId;
|
||||
|
||||
// Populate constant pool area.
|
||||
for (NameTypeEntry &NameType : D.NamesAndTypes) {
|
||||
uint32_t Hash = hash(NameType.Name);
|
||||
size_t Offset = StringPool.add(NameType.Name);
|
||||
|
||||
bool IsNew;
|
||||
GdbSymbol *Sym;
|
||||
std::tie(IsNew, Sym) = SymbolTable.add(Hash, Offset);
|
||||
if (IsNew) {
|
||||
Sym->CuVectorIndex = CuVectors.size();
|
||||
CuVectors.resize(CuVectors.size() + 1);
|
||||
}
|
||||
|
||||
CuVectors[Sym->CuVectorIndex].insert(CuId | (NameType.Type << 24));
|
||||
}
|
||||
|
||||
CuId += D.CompilationUnits.size();
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<llvm::LoadedObjectInfo> clone() const override { return {}; }
|
||||
};
|
||||
|
||||
void GdbIndexSection::readDwarf(InputSection *Sec) {
|
||||
GdbIndexChunk GdbIndexSection::readDwarf(InputSection *Sec) {
|
||||
Expected<std::unique_ptr<object::ObjectFile>> Obj =
|
||||
object::ObjectFile::createObjectFile(Sec->File->MB);
|
||||
if (!Obj) {
|
||||
error(toString(Sec->File) + ": error creating DWARF context");
|
||||
return;
|
||||
return {};
|
||||
}
|
||||
|
||||
ObjInfoTy ObjInfo;
|
||||
DWARFContextInMemory Dwarf(*Obj.get(), &ObjInfo);
|
||||
DWARFContextInMemory Dwarf(*Obj.get());
|
||||
|
||||
size_t CuId = CompilationUnits.size();
|
||||
for (std::pair<uint64_t, uint64_t> &P : readCuList(Dwarf, Sec))
|
||||
CompilationUnits.push_back(P);
|
||||
GdbIndexChunk Ret;
|
||||
Ret.CompilationUnits = readCuList(Dwarf, Sec);
|
||||
Ret.AddressArea = readAddressArea(Dwarf, Sec);
|
||||
Ret.NamesAndTypes = readPubNamesAndTypes(Dwarf, Config->IsLE);
|
||||
return Ret;
|
||||
}
|
||||
|
||||
for (AddressEntry &Ent : readAddressArea(Dwarf, Sec, CuId))
|
||||
AddressArea.push_back(Ent);
|
||||
static size_t getCuSize(std::vector<GdbIndexChunk> &C) {
|
||||
size_t Ret = 0;
|
||||
for (GdbIndexChunk &D : C)
|
||||
Ret += D.CompilationUnits.size();
|
||||
return Ret;
|
||||
}
|
||||
|
||||
std::vector<std::pair<StringRef, uint8_t>> NamesAndTypes =
|
||||
readPubNamesAndTypes(Dwarf, Config->IsLE);
|
||||
|
||||
for (std::pair<StringRef, uint8_t> &Pair : NamesAndTypes) {
|
||||
uint32_t Hash = hash(Pair.first);
|
||||
size_t Offset = StringPool.add(Pair.first);
|
||||
|
||||
bool IsNew;
|
||||
GdbSymbol *Sym;
|
||||
std::tie(IsNew, Sym) = SymbolTable.add(Hash, Offset);
|
||||
if (IsNew) {
|
||||
Sym->CuVectorIndex = CuVectors.size();
|
||||
CuVectors.resize(CuVectors.size() + 1);
|
||||
}
|
||||
|
||||
CuVectors[Sym->CuVectorIndex].insert((Pair.second << 24) | (uint32_t)CuId);
|
||||
}
|
||||
static size_t getAddressAreaSize(std::vector<GdbIndexChunk> &C) {
|
||||
size_t Ret = 0;
|
||||
for (GdbIndexChunk &D : C)
|
||||
Ret += D.AddressArea.size();
|
||||
return Ret;
|
||||
}
|
||||
|
||||
void GdbIndexSection::finalizeContents() {
|
||||
|
|
@ -1796,17 +1816,14 @@ void GdbIndexSection::finalizeContents() {
|
|||
return;
|
||||
Finalized = true;
|
||||
|
||||
for (InputSectionBase *S : InputSections)
|
||||
if (InputSection *IS = dyn_cast<InputSection>(S))
|
||||
if (IS->getParent() && IS->Name == ".debug_info")
|
||||
readDwarf(IS);
|
||||
buildIndex();
|
||||
|
||||
SymbolTable.finalizeContents();
|
||||
|
||||
// GdbIndex header consist from version fields
|
||||
// and 5 more fields with different kinds of offsets.
|
||||
CuTypesOffset = CuListOffset + CompilationUnits.size() * CompilationUnitSize;
|
||||
SymTabOffset = CuTypesOffset + AddressArea.size() * AddressEntrySize;
|
||||
CuTypesOffset = CuListOffset + getCuSize(Chunks) * CompilationUnitSize;
|
||||
SymTabOffset = CuTypesOffset + getAddressAreaSize(Chunks) * AddressEntrySize;
|
||||
|
||||
ConstantPoolOffset =
|
||||
SymTabOffset + SymbolTable.getCapacity() * SymTabEntrySize;
|
||||
|
|
@ -1835,19 +1852,24 @@ void GdbIndexSection::writeTo(uint8_t *Buf) {
|
|||
Buf += 24;
|
||||
|
||||
// Write the CU list.
|
||||
for (std::pair<uint64_t, uint64_t> CU : CompilationUnits) {
|
||||
write64le(Buf, CU.first);
|
||||
write64le(Buf + 8, CU.second);
|
||||
Buf += 16;
|
||||
for (GdbIndexChunk &D : Chunks) {
|
||||
for (CompilationUnitEntry &Cu : D.CompilationUnits) {
|
||||
write64le(Buf, Cu.CuOffset);
|
||||
write64le(Buf + 8, Cu.CuLength);
|
||||
Buf += 16;
|
||||
}
|
||||
}
|
||||
|
||||
// Write the address area.
|
||||
for (AddressEntry &E : AddressArea) {
|
||||
uint64_t BaseAddr = E.Section->getParent()->Addr + E.Section->getOffset(0);
|
||||
write64le(Buf, BaseAddr + E.LowAddress);
|
||||
write64le(Buf + 8, BaseAddr + E.HighAddress);
|
||||
write32le(Buf + 16, E.CuIndex);
|
||||
Buf += 20;
|
||||
for (GdbIndexChunk &D : Chunks) {
|
||||
for (AddressEntry &E : D.AddressArea) {
|
||||
uint64_t BaseAddr =
|
||||
E.Section->getParent()->Addr + E.Section->getOffset(0);
|
||||
write64le(Buf, BaseAddr + E.LowAddress);
|
||||
write64le(Buf + 8, BaseAddr + E.HighAddress);
|
||||
write32le(Buf + 16, E.CuIndex);
|
||||
Buf += 20;
|
||||
}
|
||||
}
|
||||
|
||||
// Write the symbol table.
|
||||
|
|
|
|||
|
|
@ -509,20 +509,23 @@ public:
|
|||
size_t getSize() const override;
|
||||
bool empty() const override;
|
||||
|
||||
// Pairs of [CU Offset, CU length].
|
||||
std::vector<std::pair<uint64_t, uint64_t>> CompilationUnits;
|
||||
|
||||
llvm::StringTableBuilder StringPool;
|
||||
|
||||
// Symbol table is a hash table for types and names.
|
||||
// It is the area of gdb index.
|
||||
GdbHashTab SymbolTable;
|
||||
|
||||
// The CU vector portion of the constant pool.
|
||||
// CU vector is a part of constant pool area of section.
|
||||
std::vector<std::set<uint32_t>> CuVectors;
|
||||
|
||||
std::vector<AddressEntry> AddressArea;
|
||||
// String pool is also a part of constant pool, it follows CU vectors.
|
||||
llvm::StringTableBuilder StringPool;
|
||||
|
||||
// Each chunk contains information gathered from a debug sections of single
|
||||
// object and used to build different areas of gdb index.
|
||||
std::vector<GdbIndexChunk> Chunks;
|
||||
|
||||
private:
|
||||
void readDwarf(InputSection *Sec);
|
||||
GdbIndexChunk readDwarf(InputSection *Sec);
|
||||
void buildIndex();
|
||||
|
||||
uint32_t CuTypesOffset;
|
||||
uint32_t SymTabOffset;
|
||||
|
|
|
|||
|
|
@ -35,8 +35,8 @@
|
|||
#include "Thunks.h"
|
||||
#include "Writer.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/BinaryFormat/ELF.h"
|
||||
#include "llvm/Object/ELF.h"
|
||||
#include "llvm/Support/ELF.h"
|
||||
#include "llvm/Support/Endian.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
|
@ -537,7 +537,17 @@ void X86TargetInfo::relocateOne(uint8_t *Loc, uint32_t Type,
|
|||
write16le(Loc, Val);
|
||||
break;
|
||||
case R_386_PC16:
|
||||
checkInt<16>(Loc, Val, Type);
|
||||
// R_386_PC16 is normally used with 16 bit code. In that situation
|
||||
// the PC is 16 bits, just like the addend. This means that it can
|
||||
// point from any 16 bit address to any other if the possibility
|
||||
// of wrapping is included.
|
||||
// The only restriction we have to check then is that the destination
|
||||
// address fits in 16 bits. That is impossible to do here. The problem is
|
||||
// that we are passed the final value, which already had the
|
||||
// current location subtracted from it.
|
||||
// We just check that Val fits in 17 bits. This misses some cases, but
|
||||
// should have no false positives.
|
||||
checkInt<17>(Loc, Val, Type);
|
||||
write16le(Loc, Val);
|
||||
break;
|
||||
default:
|
||||
|
|
@ -2085,7 +2095,7 @@ RelExpr MipsTargetInfo<ELFT>::getRelExpr(uint32_t Type, const SymbolBody &S,
|
|||
return R_MIPS_GOT_GP_PC;
|
||||
if (&S == ElfSym::MipsLocalGp)
|
||||
return R_MIPS_GOT_GP;
|
||||
// fallthrough
|
||||
LLVM_FALLTHROUGH;
|
||||
case R_MIPS_GOT_OFST:
|
||||
return R_ABS;
|
||||
case R_MIPS_PC32:
|
||||
|
|
@ -2099,7 +2109,7 @@ RelExpr MipsTargetInfo<ELFT>::getRelExpr(uint32_t Type, const SymbolBody &S,
|
|||
case R_MIPS_GOT16:
|
||||
if (S.isLocal())
|
||||
return R_MIPS_GOT_LOCAL_PAGE;
|
||||
// fallthrough
|
||||
LLVM_FALLTHROUGH;
|
||||
case R_MIPS_CALL16:
|
||||
case R_MIPS_GOT_DISP:
|
||||
case R_MIPS_TLS_GOTTPREL:
|
||||
|
|
@ -2353,7 +2363,7 @@ void MipsTargetInfo<ELFT>::relocateOne(uint8_t *Loc, uint32_t Type,
|
|||
case R_MIPS_TLS_GD:
|
||||
case R_MIPS_TLS_LDM:
|
||||
checkInt<16>(Loc, Val, Type);
|
||||
// fallthrough
|
||||
LLVM_FALLTHROUGH;
|
||||
case R_MIPS_CALL16:
|
||||
case R_MIPS_CALL_LO16:
|
||||
case R_MIPS_GOT_LO16:
|
||||
|
|
|
|||
|
|
@ -30,8 +30,8 @@
|
|||
#include "Symbols.h"
|
||||
#include "SyntheticSections.h"
|
||||
#include "Target.h"
|
||||
#include "llvm/BinaryFormat/ELF.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/ELF.h"
|
||||
#include "llvm/Support/Endian.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
|
|
@ -143,7 +143,7 @@ void ThumbV7ABSLongThunk::writeTo(uint8_t *Buf, ThunkSection &IS) const {
|
|||
void ThumbV7ABSLongThunk::addSymbols(ThunkSection &IS) {
|
||||
ThunkSym = addSyntheticLocal(
|
||||
Saver.save("__Thumbv7ABSLongThunk_" + Destination.getName()), STT_FUNC,
|
||||
Offset, size(), &IS);
|
||||
Offset | 0x1, size(), &IS);
|
||||
addSyntheticLocal("$t", STT_NOTYPE, Offset, 0, &IS);
|
||||
}
|
||||
|
||||
|
|
@ -176,7 +176,7 @@ void ThumbV7PILongThunk::writeTo(uint8_t *Buf, ThunkSection &IS) const {
|
|||
0x60, 0x47, // bx r12
|
||||
};
|
||||
uint64_t S = getARMThunkDestVA(Destination);
|
||||
uint64_t P = ThunkSym->getVA();
|
||||
uint64_t P = ThunkSym->getVA() & ~0x1;
|
||||
memcpy(Buf, Data, sizeof(Data));
|
||||
Target->relocateOne(Buf, R_ARM_THM_MOVW_PREL_NC, S - P - 12);
|
||||
Target->relocateOne(Buf + 4, R_ARM_THM_MOVT_PREL, S - P - 8);
|
||||
|
|
@ -185,7 +185,7 @@ void ThumbV7PILongThunk::writeTo(uint8_t *Buf, ThunkSection &IS) const {
|
|||
void ThumbV7PILongThunk::addSymbols(ThunkSection &IS) {
|
||||
ThunkSym = addSyntheticLocal(
|
||||
Saver.save("__ThumbV7PILongThunk_" + Destination.getName()), STT_FUNC,
|
||||
Offset, size(), &IS);
|
||||
Offset | 0x1, size(), &IS);
|
||||
addSyntheticLocal("$t", STT_NOTYPE, Offset, 0, &IS);
|
||||
}
|
||||
|
||||
|
|
|
|||
101
ELF/Writer.cpp
101
ELF/Writer.cpp
|
|
@ -93,21 +93,14 @@ private:
|
|||
} // anonymous namespace
|
||||
|
||||
StringRef elf::getOutputSectionName(StringRef Name) {
|
||||
// ".zdebug_" is a prefix for ZLIB-compressed sections.
|
||||
// Because we decompressed input sections, we want to remove 'z'.
|
||||
if (Name.startswith(".zdebug_"))
|
||||
return Saver.save("." + Name.substr(2));
|
||||
|
||||
if (Config->Relocatable)
|
||||
return Name;
|
||||
|
||||
// If -emit-relocs is given (which is rare), we need to copy
|
||||
// relocation sections to the output. If input section .foo is
|
||||
// output as .bar, we want to rename .rel.foo .rel.bar as well.
|
||||
if (Config->EmitRelocs) {
|
||||
for (StringRef V : {".rel.", ".rela."}) {
|
||||
if (Name.startswith(V)) {
|
||||
StringRef Inner = getOutputSectionName(Name.substr(V.size() - 1));
|
||||
return Saver.save(V.drop_back() + Inner);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (StringRef V :
|
||||
{".text.", ".rodata.", ".data.rel.ro.", ".data.", ".bss.rel.ro.",
|
||||
".bss.", ".init_array.", ".fini_array.", ".ctors.", ".dtors.", ".tbss.",
|
||||
|
|
@ -122,10 +115,6 @@ StringRef elf::getOutputSectionName(StringRef Name) {
|
|||
if (Name == "COMMON")
|
||||
return ".bss";
|
||||
|
||||
// ".zdebug_" is a prefix for ZLIB-compressed sections.
|
||||
// Because we decompressed input sections, we want to remove 'z'.
|
||||
if (Name.startswith(".zdebug_"))
|
||||
return Saver.save("." + Name.substr(2));
|
||||
return Name;
|
||||
}
|
||||
|
||||
|
|
@ -257,18 +246,7 @@ template <class ELFT> void Writer<ELFT>::run() {
|
|||
if (ErrorCount)
|
||||
return;
|
||||
|
||||
if (!Script->Opt.HasSections)
|
||||
Script->fabricateDefaultCommands();
|
||||
else
|
||||
Script->synchronize();
|
||||
|
||||
for (BaseCommand *Base : Script->Opt.Commands)
|
||||
if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base))
|
||||
OutputSectionCommands.push_back(Cmd);
|
||||
|
||||
clearOutputSections();
|
||||
|
||||
if (!Script->Opt.HasSections &&!Config->Relocatable)
|
||||
if (!Script->Opt.HasSections && !Config->Relocatable)
|
||||
fixSectionAlignments();
|
||||
|
||||
// If -compressed-debug-sections is specified, we need to compress
|
||||
|
|
@ -278,22 +256,24 @@ template <class ELFT> void Writer<ELFT>::run() {
|
|||
OutputSectionCommands.begin(), OutputSectionCommands.end(),
|
||||
[](OutputSectionCommand *Cmd) { Cmd->maybeCompress<ELFT>(); });
|
||||
|
||||
if (Config->Relocatable) {
|
||||
Script->assignAddresses(Phdrs, OutputSectionCommands);
|
||||
|
||||
// Remove empty PT_LOAD to avoid causing the dynamic linker to try to mmap a
|
||||
// 0 sized region. This has to be done late since only after assignAddresses
|
||||
// we know the size of the sections.
|
||||
removeEmptyPTLoad();
|
||||
|
||||
if (!Config->OFormatBinary)
|
||||
assignFileOffsets();
|
||||
else
|
||||
assignFileOffsetsBinary();
|
||||
|
||||
setPhdrs();
|
||||
|
||||
if (Config->Relocatable) {
|
||||
for (OutputSectionCommand *Cmd : OutputSectionCommands)
|
||||
Cmd->Sec->Addr = 0;
|
||||
} else {
|
||||
Script->assignAddresses(Phdrs, OutputSectionCommands);
|
||||
|
||||
// Remove empty PT_LOAD to avoid causing the dynamic linker to try to mmap a
|
||||
// 0 sized region. This has to be done late since only after assignAddresses
|
||||
// we know the size of the sections.
|
||||
removeEmptyPTLoad();
|
||||
|
||||
if (!Config->OFormatBinary)
|
||||
assignFileOffsets();
|
||||
else
|
||||
assignFileOffsetsBinary();
|
||||
|
||||
setPhdrs();
|
||||
fixPredefinedSymbols();
|
||||
}
|
||||
|
||||
|
|
@ -915,7 +895,14 @@ template <class ELFT> void Writer<ELFT>::addReservedSymbols() {
|
|||
// this symbol unconditionally even when using a linker script, which
|
||||
// differs from the behavior implemented by GNU linker which only define
|
||||
// this symbol if ELF headers are in the memory mapped segment.
|
||||
addOptionalRegular<ELFT>("__ehdr_start", Out::ElfHeader, 0, STV_HIDDEN);
|
||||
// __executable_start is not documented, but the expectation of at
|
||||
// least the android libc is that it points to the elf header too.
|
||||
// __dso_handle symbol is passed to cxa_finalize as a marker to identify
|
||||
// each DSO. The address of the symbol doesn't matter as long as they are
|
||||
// different in different DSOs, so we chose the start address of the DSO.
|
||||
for (const char *Name :
|
||||
{"__ehdr_start", "__executable_start", "__dso_handle"})
|
||||
addOptionalRegular<ELFT>(Name, Out::ElfHeader, 0, STV_HIDDEN);
|
||||
|
||||
// If linker script do layout we do not need to create any standart symbols.
|
||||
if (Script->Opt.HasSections)
|
||||
|
|
@ -1011,9 +998,6 @@ template <class ELFT> void Writer<ELFT>::createSections() {
|
|||
sortInitFini(findSection(".fini_array"));
|
||||
sortCtorsDtors(findSection(".ctors"));
|
||||
sortCtorsDtors(findSection(".dtors"));
|
||||
|
||||
for (OutputSection *Sec : OutputSections)
|
||||
Sec->assignOffsets();
|
||||
}
|
||||
|
||||
// We want to find how similar two ranks are.
|
||||
|
|
@ -1116,10 +1100,8 @@ template <class ELFT> void Writer<ELFT>::sortSections() {
|
|||
static void applySynthetic(const std::vector<SyntheticSection *> &Sections,
|
||||
std::function<void(SyntheticSection *)> Fn) {
|
||||
for (SyntheticSection *SS : Sections)
|
||||
if (SS && SS->getParent() && !SS->empty()) {
|
||||
if (SS && SS->getParent() && !SS->empty())
|
||||
Fn(SS);
|
||||
SS->getParent()->assignOffsets();
|
||||
}
|
||||
}
|
||||
|
||||
// We need to add input synthetic sections early in createSyntheticSections()
|
||||
|
|
@ -1225,6 +1207,12 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
|
|||
Sec->ShName = InX::ShStrTab->addString(Sec->Name);
|
||||
}
|
||||
|
||||
if (!Script->Opt.HasSections)
|
||||
Script->fabricateDefaultCommands();
|
||||
for (BaseCommand *Base : Script->Opt.Commands)
|
||||
if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base))
|
||||
OutputSectionCommands.push_back(Cmd);
|
||||
|
||||
// Binary and relocatable output does not have PHDRS.
|
||||
// The headers have to be created before finalize as that can influence the
|
||||
// image base and the dynamic section on mips includes the image base.
|
||||
|
|
@ -1234,6 +1222,14 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
|
|||
Out::ProgramHeaders->Size = sizeof(Elf_Phdr) * Phdrs.size();
|
||||
}
|
||||
|
||||
clearOutputSections();
|
||||
|
||||
// Compute the size of .rela.dyn and .rela.plt early since we need
|
||||
// them to populate .dynamic.
|
||||
for (SyntheticSection *SS : {In<ELFT>::RelaDyn, In<ELFT>::RelaPlt})
|
||||
if (SS->getParent() && !SS->empty())
|
||||
SS->getParent()->assignOffsets();
|
||||
|
||||
// Dynamic section must be the last one in this list and dynamic
|
||||
// symbol table section (DynSymTab) must be the first one.
|
||||
applySynthetic({InX::DynSymTab, InX::Bss, InX::BssRelRo,
|
||||
|
|
@ -1257,15 +1253,16 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
|
|||
// are out of range. This will need to turn into a loop that converges
|
||||
// when no more Thunks are added
|
||||
ThunkCreator TC;
|
||||
if (TC.createThunks(OutputSections))
|
||||
if (TC.createThunks(OutputSectionCommands))
|
||||
applySynthetic({InX::MipsGot},
|
||||
[](SyntheticSection *SS) { SS->updateAllocSize(); });
|
||||
}
|
||||
|
||||
// Fill other section headers. The dynamic table is finalized
|
||||
// at the end because some tags like RELSZ depend on result
|
||||
// of finalizing other sections.
|
||||
for (OutputSection *Sec : OutputSections)
|
||||
Sec->finalize<ELFT>();
|
||||
for (OutputSectionCommand *Cmd : OutputSectionCommands)
|
||||
Cmd->finalize<ELFT>();
|
||||
|
||||
// createThunks may have added local symbols to the static symbol table
|
||||
applySynthetic({InX::SymTab, InX::ShStrTab, InX::StrTab},
|
||||
|
|
|
|||
|
|
@ -13,14 +13,13 @@
|
|||
#include "lld/Core/LLVM.h"
|
||||
#include "lld/Core/Reference.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/BinaryFormat/Magic.h"
|
||||
#include "llvm/Support/ErrorOr.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
using llvm::sys::fs::file_magic;
|
||||
|
||||
namespace llvm {
|
||||
namespace yaml {
|
||||
class IO;
|
||||
|
|
@ -45,7 +44,7 @@ public:
|
|||
/// The method is called with:
|
||||
/// 1) the file_magic enumeration returned by identify_magic()
|
||||
/// 2) the whole file content buffer if the above is not enough.
|
||||
virtual bool canParse(file_magic magic, MemoryBufferRef mb) const = 0;
|
||||
virtual bool canParse(llvm::file_magic magic, MemoryBufferRef mb) const = 0;
|
||||
|
||||
/// \brief Parse a supplied buffer (already filled with the contents of a
|
||||
/// file) and create a File object.
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@
|
|||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/ADT/StringSet.h"
|
||||
#include "llvm/BinaryFormat/MachO.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/MachO.h"
|
||||
#include <set>
|
||||
|
||||
using llvm::MachO::HeaderFileType;
|
||||
|
|
|
|||
|
|
@ -18,9 +18,10 @@ add_lld_library(lldCore
|
|||
${LLD_INCLUDE_DIR}/lld/Core
|
||||
|
||||
LINK_COMPONENTS
|
||||
BinaryFormat
|
||||
MC
|
||||
Support
|
||||
|
||||
|
||||
LINK_LIBS
|
||||
${LLVM_PTHREAD_LIB}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,12 +11,16 @@
|
|||
#include "lld/Core/File.h"
|
||||
#include "lld/Core/Reference.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/BinaryFormat/Magic.h"
|
||||
#include "llvm/Support/Errc.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
|
||||
using llvm::file_magic;
|
||||
using llvm::identify_magic;
|
||||
|
||||
namespace lld {
|
||||
|
||||
YamlIOTaggedDocumentHandler::~YamlIOTaggedDocumentHandler() = default;
|
||||
|
|
@ -33,7 +37,7 @@ ErrorOr<std::unique_ptr<File>>
|
|||
Registry::loadFile(std::unique_ptr<MemoryBuffer> mb) const {
|
||||
// Get file magic.
|
||||
StringRef content(mb->getBufferStart(), mb->getBufferSize());
|
||||
llvm::sys::fs::file_magic fileType = llvm::sys::fs::identify_magic(content);
|
||||
file_magic fileType = identify_magic(content);
|
||||
|
||||
// Ask each registered reader if it can handle this file type or extension.
|
||||
for (const std::unique_ptr<Reader> &reader : _readers) {
|
||||
|
|
|
|||
|
|
@ -161,7 +161,7 @@ bool SymbolTable::addByName(const Atom &newAtom) {
|
|||
llvm::errs() << "Size mismatch: "
|
||||
<< existing->name() << " (" << existingSize << ") "
|
||||
<< newAtom.name() << " (" << newSize << ")\n";
|
||||
// fallthrough
|
||||
LLVM_FALLTHROUGH;
|
||||
}
|
||||
case MCR_Error:
|
||||
llvm::errs() << "Duplicate symbols: "
|
||||
|
|
|
|||
|
|
@ -18,30 +18,30 @@
|
|||
#include "lld/Core/File.h"
|
||||
#include "lld/Core/Instrumentation.h"
|
||||
#include "lld/Core/LLVM.h"
|
||||
#include "lld/Core/LinkingContext.h"
|
||||
#include "lld/Core/Node.h"
|
||||
#include "lld/Core/PassManager.h"
|
||||
#include "lld/Core/Resolver.h"
|
||||
#include "lld/Core/SharedLibraryFile.h"
|
||||
#include "lld/Core/Simple.h"
|
||||
#include "lld/Core/LinkingContext.h"
|
||||
#include "lld/ReaderWriter/MachOLinkingContext.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/Optional.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
#include "llvm/BinaryFormat/MachO.h"
|
||||
#include "llvm/Option/Arg.h"
|
||||
#include "llvm/Option/ArgList.h"
|
||||
#include "llvm/Option/Option.h"
|
||||
#include "llvm/Option/OptTable.h"
|
||||
#include "llvm/Option/Option.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include "llvm/Support/ErrorOr.h"
|
||||
#include "llvm/Support/Format.h"
|
||||
#include "llvm/Support/MachO.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
|
|
|
|||
|
|
@ -11,15 +11,16 @@
|
|||
#include "lld/Core/File.h"
|
||||
#include "lld/Core/LLVM.h"
|
||||
#include "lld/Core/Reader.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Object/Archive.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/Format.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/BinaryFormat/Magic.h"
|
||||
#include "llvm/Object/Archive.h"
|
||||
#include "llvm/Object/Error.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/ErrorOr.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
#include "llvm/Support/Format.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <memory>
|
||||
#include <set>
|
||||
|
|
@ -30,6 +31,8 @@
|
|||
#include <vector>
|
||||
|
||||
using llvm::object::Archive;
|
||||
using llvm::file_magic;
|
||||
using llvm::identify_magic;
|
||||
|
||||
namespace lld {
|
||||
|
||||
|
|
@ -201,7 +204,7 @@ public:
|
|||
ArchiveReader(bool logLoading) : _logLoading(logLoading) {}
|
||||
|
||||
bool canParse(file_magic magic, MemoryBufferRef) const override {
|
||||
return magic == llvm::sys::fs::file_magic::archive;
|
||||
return magic == file_magic::archive;
|
||||
}
|
||||
|
||||
ErrorOr<std::unique_ptr<File>> loadFile(std::unique_ptr<MemoryBuffer> mb,
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
#include "Atoms.h"
|
||||
#include "File.h"
|
||||
|
||||
#include "llvm/Support/MachO.h"
|
||||
#include "llvm/BinaryFormat/MachO.h"
|
||||
|
||||
#include "lld/Core/DefinedAtom.h"
|
||||
#include "lld/Core/File.h"
|
||||
|
|
|
|||
|
|
@ -22,11 +22,11 @@
|
|||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/ADT/Triple.h"
|
||||
#include "llvm/BinaryFormat/MachO.h"
|
||||
#include "llvm/Demangle/Demangle.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/Errc.h"
|
||||
#include "llvm/Support/Host.h"
|
||||
#include "llvm/Support/MachO.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
#include <algorithm>
|
||||
|
||||
|
|
|
|||
|
|
@ -48,10 +48,10 @@
|
|||
#include "lld/ReaderWriter/MachOLinkingContext.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/BinaryFormat/MachO.h"
|
||||
#include "llvm/Support/Allocator.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/ErrorOr.h"
|
||||
#include "llvm/Support/MachO.h"
|
||||
#include "llvm/Support/YAMLTraits.h"
|
||||
|
||||
using llvm::BumpPtrAllocator;
|
||||
|
|
|
|||
|
|
@ -21,24 +21,25 @@
|
|||
/// | normalized |
|
||||
/// +------------+
|
||||
|
||||
#include "MachONormalizedFile.h"
|
||||
#include "ArchHandler.h"
|
||||
#include "MachONormalizedFile.h"
|
||||
#include "MachONormalizedFileBinaryUtils.h"
|
||||
#include "lld/Core/Error.h"
|
||||
#include "lld/Core/LLVM.h"
|
||||
#include "lld/Core/SharedLibraryFile.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/StringSwitch.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
#include "llvm/BinaryFormat/MachO.h"
|
||||
#include "llvm/BinaryFormat/Magic.h"
|
||||
#include "llvm/Object/MachO.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/Errc.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/FileOutputBuffer.h"
|
||||
#include "llvm/Support/Host.h"
|
||||
#include "llvm/Support/MachO.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <functional>
|
||||
|
|
@ -46,6 +47,7 @@
|
|||
|
||||
using namespace llvm::MachO;
|
||||
using llvm::object::ExportEntry;
|
||||
using llvm::file_magic;
|
||||
using llvm::object::MachOObjectFile;
|
||||
|
||||
namespace lld {
|
||||
|
|
@ -531,8 +533,7 @@ public:
|
|||
MachOObjectReader(MachOLinkingContext &ctx) : _ctx(ctx) {}
|
||||
|
||||
bool canParse(file_magic magic, MemoryBufferRef mb) const override {
|
||||
return (magic == llvm::sys::fs::file_magic::macho_object &&
|
||||
mb.getBufferSize() > 32);
|
||||
return (magic == file_magic::macho_object && mb.getBufferSize() > 32);
|
||||
}
|
||||
|
||||
ErrorOr<std::unique_ptr<File>>
|
||||
|
|
@ -553,8 +554,8 @@ public:
|
|||
|
||||
bool canParse(file_magic magic, MemoryBufferRef mb) const override {
|
||||
switch (magic) {
|
||||
case llvm::sys::fs::file_magic::macho_dynamically_linked_shared_lib:
|
||||
case llvm::sys::fs::file_magic::macho_dynamically_linked_shared_lib_stub:
|
||||
case file_magic::macho_dynamically_linked_shared_lib:
|
||||
case file_magic::macho_dynamically_linked_shared_lib_stub:
|
||||
return mb.getBufferSize() > 32;
|
||||
default:
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -14,12 +14,12 @@
|
|||
#include "lld/Core/Error.h"
|
||||
#include "lld/Core/LLVM.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/BinaryFormat/MachO.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/Endian.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/Host.h"
|
||||
#include "llvm/Support/LEB128.h"
|
||||
#include "llvm/Support/MachO.h"
|
||||
#include <system_error>
|
||||
|
||||
namespace lld {
|
||||
|
|
|
|||
|
|
@ -25,11 +25,12 @@
|
|||
#include "MachONormalizedFileBinaryUtils.h"
|
||||
#include "lld/Core/Error.h"
|
||||
#include "lld/Core/LLVM.h"
|
||||
#include "llvm/ADT/ilist.h"
|
||||
#include "llvm/ADT/ilist_node.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/ilist.h"
|
||||
#include "llvm/ADT/ilist_node.h"
|
||||
#include "llvm/BinaryFormat/MachO.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/Errc.h"
|
||||
|
|
@ -37,7 +38,6 @@
|
|||
#include "llvm/Support/FileOutputBuffer.h"
|
||||
#include "llvm/Support/Format.h"
|
||||
#include "llvm/Support/Host.h"
|
||||
#include "llvm/Support/MachO.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <functional>
|
||||
|
|
|
|||
|
|
@ -20,19 +20,19 @@
|
|||
/// | Atoms |
|
||||
/// +-------+
|
||||
|
||||
#include "MachONormalizedFile.h"
|
||||
#include "ArchHandler.h"
|
||||
#include "DebugInfo.h"
|
||||
#include "MachONormalizedFile.h"
|
||||
#include "MachONormalizedFileBinaryUtils.h"
|
||||
#include "lld/Core/Error.h"
|
||||
#include "lld/Core/LLVM.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/StringSwitch.h"
|
||||
#include "llvm/BinaryFormat/MachO.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/Format.h"
|
||||
#include "llvm/Support/MachO.h"
|
||||
#include <map>
|
||||
#include <system_error>
|
||||
#include <unordered_set>
|
||||
|
|
@ -515,6 +515,7 @@ void Util::organizeSections() {
|
|||
// Main executables, need a zero-page segment
|
||||
segmentForName("__PAGEZERO");
|
||||
// Fall into next case.
|
||||
LLVM_FALLTHROUGH;
|
||||
case llvm::MachO::MH_DYLIB:
|
||||
case llvm::MachO::MH_BUNDLE:
|
||||
// All dynamic code needs TEXT segment to hold the load commands.
|
||||
|
|
|
|||
|
|
@ -20,20 +20,20 @@
|
|||
/// | Atoms |
|
||||
/// +-------+
|
||||
|
||||
#include "MachONormalizedFile.h"
|
||||
#include "ArchHandler.h"
|
||||
#include "Atoms.h"
|
||||
#include "File.h"
|
||||
#include "MachONormalizedFile.h"
|
||||
#include "MachONormalizedFileBinaryUtils.h"
|
||||
#include "lld/Core/Error.h"
|
||||
#include "lld/Core/LLVM.h"
|
||||
#include "llvm/BinaryFormat/Dwarf.h"
|
||||
#include "llvm/BinaryFormat/MachO.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
|
||||
#include "llvm/Support/DataExtractor.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/Dwarf.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include "llvm/Support/Format.h"
|
||||
#include "llvm/Support/MachO.h"
|
||||
#include "llvm/Support/LEB128.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -23,17 +23,16 @@
|
|||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/StringSwitch.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
#include "llvm/BinaryFormat/MachO.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/Format.h"
|
||||
#include "llvm/Support/MachO.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
#include "llvm/Support/SourceMgr.h"
|
||||
#include "llvm/Support/YAMLTraits.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <system_error>
|
||||
|
||||
|
||||
using llvm::StringRef;
|
||||
using namespace llvm::yaml;
|
||||
using namespace llvm::MachO;
|
||||
|
|
|
|||
|
|
@ -12,10 +12,10 @@
|
|||
#include "lld/Core/File.h"
|
||||
#include "lld/Core/Writer.h"
|
||||
#include "lld/ReaderWriter/MachOLinkingContext.h"
|
||||
#include "llvm/BinaryFormat/MachO.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/FileOutputBuffer.h"
|
||||
#include "llvm/Support/MachO.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <system_error>
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
#include "llvm/BinaryFormat/Magic.h"
|
||||
#include "llvm/Support/Allocator.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
|
|
@ -43,6 +44,7 @@
|
|||
#include <system_error>
|
||||
#include <vector>
|
||||
|
||||
using llvm::file_magic;
|
||||
using llvm::yaml::MappingTraits;
|
||||
using llvm::yaml::ScalarEnumerationTraits;
|
||||
using llvm::yaml::ScalarTraits;
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ if (NOT LLD_BUILT_STANDALONE)
|
|||
list(APPEND LLD_TEST_DEPS
|
||||
FileCheck count not llvm-ar llvm-as llvm-dis llvm-dwarfdump llvm-nm
|
||||
llc llvm-config llvm-objdump llvm-readobj yaml2obj obj2yaml
|
||||
llvm-mc llvm-lib llvm-pdbdump opt
|
||||
llvm-mc llvm-lib llvm-pdbutil opt
|
||||
)
|
||||
endif()
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
# RUN: lld-link /debug /debugtype:pdata /pdb:%t.pdb /dll /out:%t.dll /entry:main /nodefaultlib \
|
||||
# RUN: %t1.obj %t2.obj
|
||||
|
||||
# RUN: llvm-pdbdump pdb2yaml -pdb-stream %t.pdb | FileCheck %s
|
||||
# RUN: llvm-pdbutil pdb2yaml -pdb-stream %t.pdb | FileCheck %s
|
||||
|
||||
# CHECK: PdbStream:
|
||||
# CHECK-NEXT: Age: 0
|
||||
|
|
|
|||
|
|
@ -3,10 +3,10 @@
|
|||
# RUN: lld-link /debug /pdb:%t.pdb /dll /out:%t.dll /entry:main /nodefaultlib \
|
||||
# RUN: %t1.obj %t2.obj
|
||||
|
||||
# RUN: llvm-pdbdump pdb2yaml -stream-metadata -stream-directory -pdb-stream \
|
||||
# RUN: llvm-pdbutil pdb2yaml -stream-metadata -stream-directory -pdb-stream \
|
||||
# RUN: -dbi-stream -ipi-stream -tpi-stream %t.pdb | FileCheck %s
|
||||
|
||||
# RUN: llvm-pdbdump raw -modules -section-map -section-headers -section-contribs \
|
||||
# RUN: llvm-pdbutil raw -modules -section-map -section-headers -section-contribs \
|
||||
# RUN: -tpi-records %t.pdb | FileCheck -check-prefix RAW %s
|
||||
|
||||
# CHECK: MSF:
|
||||
|
|
|
|||
2
test/ELF/Inputs/relocatable-comdat-multiple.s
Normal file
2
test/ELF/Inputs/relocatable-comdat-multiple.s
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
.section .text.c,"axG",@progbits,bbb,comdat
|
||||
.section .text.d,"axG",@progbits,bbb,comdat
|
||||
|
|
@ -33,13 +33,13 @@ _start:
|
|||
|
||||
// CHECK: Disassembly of section .text:
|
||||
// 131076 = 0x20004
|
||||
// CHECK: 20000: 01 80 00 14 b #131076
|
||||
// CHECK-NEXT: 20004: 02 80 00 94 bl #131080
|
||||
// CHECK-NEXT: 20008: 60 00 10 54 b.eq #131084
|
||||
// CHECK-NEXT: 2000c: 81 00 10 b4 cbz x1, #131088
|
||||
// CHECK-NEXT: 20010: 00 00 00 10 adr x0, #0
|
||||
// CHECK-NEXT: 20014: 00 00 00 90 adrp x0, #0
|
||||
// CHECK: 20018: 00 00 00 00 .word 0x00000000
|
||||
// CHECK-NEXT: 2001c: 00 00 00 00 .word 0x00000000
|
||||
// CHECK-NEXT: 20020: 00 00 00 00 .word 0x00000000
|
||||
// CHECK-NEXT: 20024: 00 00 .short 0x0000
|
||||
// CHECK: 20000: {{.*}} b #131076
|
||||
// CHECK-NEXT: 20004: {{.*}} bl #131080
|
||||
// CHECK-NEXT: 20008: {{.*}} b.eq #131084
|
||||
// CHECK-NEXT: 2000c: {{.*}} cbz x1, #131088
|
||||
// CHECK-NEXT: 20010: {{.*}} adr x0, #0
|
||||
// CHECK-NEXT: 20014: {{.*}} adrp x0, #0
|
||||
// CHECK: 20018: {{.*}} .word 0x00000000
|
||||
// CHECK-NEXT: 2001c: {{.*}} .word 0x00000000
|
||||
// CHECK-NEXT: 20020: {{.*}} .word 0x00000000
|
||||
// CHECK-NEXT: 20024: {{.*}} .short 0x0000
|
||||
|
|
|
|||
|
|
@ -1,130 +1,56 @@
|
|||
# RUN: llvm-mc -filetype=obj -triple amdgcn--amdhsa -mcpu=kaveri %s -o %t.o
|
||||
# RUN: ld.lld %t.o -o %t
|
||||
# RUN: ld.lld -shared %t.o -o %t
|
||||
# RUN: llvm-readobj -sections -symbols -program-headers %t | FileCheck %s
|
||||
|
||||
# REQUIRES: amdgpu
|
||||
|
||||
.amdgpu_hsa_module_global module_global_program
|
||||
.size module_global_program, 4
|
||||
.hsadata_global_program
|
||||
module_global_program:
|
||||
.long 0 ; 0x0
|
||||
.type glob0, @object
|
||||
.data
|
||||
.globl glob0
|
||||
glob0:
|
||||
.long 1
|
||||
.size glob0, 4
|
||||
|
||||
.amdgpu_hsa_program_global program_global_program
|
||||
.size program_global_program, 4
|
||||
.hsadata_global_program
|
||||
program_global_program:
|
||||
.long 0 ; 0x0
|
||||
|
||||
.amdgpu_hsa_module_global module_global_agent
|
||||
.size module_global_agent, 4
|
||||
.hsadata_global_agent
|
||||
module_global_agent:
|
||||
.long 0 ; 0x0
|
||||
|
||||
.amdgpu_hsa_program_global program_global_agent
|
||||
.size program_global_agent, 4
|
||||
.hsadata_global_agent
|
||||
program_global_agent:
|
||||
.long 0 ; 0x0
|
||||
|
||||
.amdgpu_hsa_module_global module_global_readonly
|
||||
.size module_global_readonly, 4
|
||||
.hsatext
|
||||
module_global_readonly:
|
||||
.long 0 ; 0x0
|
||||
|
||||
.amdgpu_hsa_program_global program_global_readonly
|
||||
.size program_global_readonly, 4
|
||||
.hsatext
|
||||
program_global_readonly:
|
||||
.long 0 ; 0x0
|
||||
.type glob1, @object
|
||||
.section .rodata, #alloc
|
||||
.globl glob1
|
||||
glob1:
|
||||
.long 2
|
||||
.size glob1, 4
|
||||
|
||||
# CHECK: Section {
|
||||
# CHECK: Name: .hsatext
|
||||
# CHECK: Type: SHT_PROGBITS
|
||||
# CHECK: Flags [ (0xC00007)
|
||||
# CHECK: SHF_ALLOC (0x2)
|
||||
# CHECK: SHF_AMDGPU_HSA_AGENT (0x800000)
|
||||
# CHECK: SHF_AMDGPU_HSA_CODE (0x400000)
|
||||
# CHECK: SHF_EXECINSTR (0x4)
|
||||
# CHECK: SHF_WRITE (0x1)
|
||||
# CHECK: ]
|
||||
# CHECK: Address: [[HSATEXT_ADDR:[0-9xa-f]+]]
|
||||
# CHECK: Name: .rodata
|
||||
# CHECK: Type: SHT_PROGBITS
|
||||
# CHECK: Flags [ (0x2)
|
||||
# CHECK: SHF_ALLOC (0x2)
|
||||
# CHECK: ]
|
||||
# CHECK: Address: [[RODATA_ADDR:[0-9xa-f]+]]
|
||||
# CHECK: }
|
||||
|
||||
# CHECK: Section {
|
||||
# CHECK: Name: .hsadata_global_program
|
||||
# CHECK: Type: SHT_PROGBITS (0x1)
|
||||
# CHECK: Flags [ (0x100003)
|
||||
# CHECK: SHF_ALLOC (0x2)
|
||||
# CHECK: SHF_AMDGPU_HSA_GLOBAL (0x100000)
|
||||
# CHECK: SHF_WRITE (0x1)
|
||||
# CHECK: ]
|
||||
# CHECK: Address: [[HSADATA_GLOBAL_PROGRAM_ADDR:[0-9xa-f]+]]
|
||||
# CHECK: }
|
||||
|
||||
# CHECK: Section {
|
||||
# CHECK: Name: .hsadata_global_agent
|
||||
# CHECK: Type: SHT_PROGBITS (0x1)
|
||||
# CHECK: Flags [ (0x900003)
|
||||
# CHECK: SHF_ALLOC (0x2)
|
||||
# CHECK: SHF_AMDGPU_HSA_AGENT (0x800000)
|
||||
# CHECK: SHF_AMDGPU_HSA_GLOBAL (0x100000)
|
||||
# CHECK: SHF_WRITE (0x1)
|
||||
# CHECK: ]
|
||||
# CHECK: Name: .data
|
||||
# CHECK: Type: SHT_PROGBITS
|
||||
# CHECK: Flags [ (0x3)
|
||||
# CHECK: SHF_ALLOC (0x2)
|
||||
# CHECK: SHF_WRITE (0x1)
|
||||
# CHECK: ]
|
||||
# CHECK: Address: [[DATA_ADDR:[0-9xa-f]+]]
|
||||
# CHECK: }
|
||||
|
||||
# CHECK: Symbol {
|
||||
# CHECK: Name: module_global_agent
|
||||
# CHECK: Value:
|
||||
# CHECK: Size: 4
|
||||
# CHECK: Binding: Local
|
||||
# CHECK: Section: .hsadata_global_agent
|
||||
# CHECK: Name: glob0
|
||||
# CHECK: Value: [[DATA_ADDR]]
|
||||
# CHECK: Size: 4
|
||||
# CHECK: Type: Object
|
||||
# CHECK: Section: .data
|
||||
# CHECK: }
|
||||
|
||||
# CHECK: Symbol {
|
||||
# CHECK: Name: module_global_program
|
||||
# CHECK: Value:
|
||||
# CHECK: Size: 4
|
||||
# CHECK: Binding: Local
|
||||
# CHECK: Section: .hsadata_global_program
|
||||
# CHECK: }
|
||||
|
||||
# CHECK: Symbol {
|
||||
# CHECK: Name: module_global_readonly
|
||||
# CHECK: Value:
|
||||
# CHECK: Size: 4
|
||||
# CHECK: Binding: Local
|
||||
# CHECK: Type: Object
|
||||
# CHECK: Section: .hsatext
|
||||
# CHECK: }
|
||||
|
||||
# CHECK: Symbol {
|
||||
# CHECK: Name: program_global_agent
|
||||
# CHECK: Value:
|
||||
# CHECK: Size: 4
|
||||
# CHECK: Binding: Global
|
||||
# CHECK: Type: Object
|
||||
# CHECK: Section: .hsadata_global_agent
|
||||
# CHECK: }
|
||||
|
||||
# CHECK: Symbol {
|
||||
# CHECK: Name: program_global_program
|
||||
# CHECK: Value:
|
||||
# CHECK: Size: 4
|
||||
# CHECK: Binding: Global
|
||||
# CHECK: Type: Object
|
||||
# CHECK: Section: .hsadata_global_program
|
||||
# CHECK: }
|
||||
|
||||
# CHECK: Symbol {
|
||||
# CHECK: Name: program_global_readonly
|
||||
# CHECK: Value:
|
||||
# CHECK: Size: 4
|
||||
# CHECK: Binding: Global
|
||||
# CHECK: Type: Object
|
||||
# CHECK: Section: .hsatext
|
||||
# CHECK: Name: glob1
|
||||
# CHECK: Value: [[RODATA_ADDR]]
|
||||
# CHECK: Size: 4
|
||||
# CHECK: Type: Object
|
||||
# CHECK: Section: .rodata
|
||||
# CHECK: }
|
||||
|
||||
# CHECK: ProgramHeader {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# RUN: llvm-mc -filetype=obj -triple amdgcn--amdhsa -mcpu=kaveri %s -o %t.o
|
||||
# RUN: ld.lld %t.o -o %t
|
||||
# RUN: ld.lld -shared %t.o -o %t
|
||||
# RUN: llvm-readobj -sections -symbols -program-headers %t | FileCheck %s
|
||||
|
||||
# REQUIRES: amdgpu
|
||||
|
|
@ -7,7 +7,7 @@
|
|||
.hsa_code_object_version 1,0
|
||||
.hsa_code_object_isa 7,0,0,"AMD","AMDGPU"
|
||||
|
||||
.hsatext
|
||||
.text
|
||||
.globl kernel0
|
||||
.align 256
|
||||
.amdgpu_hsa_kernel kernel0
|
||||
|
|
@ -27,16 +27,12 @@ kernel1:
|
|||
|
||||
|
||||
# CHECK: Section {
|
||||
# CHECK: Name: .hsatext
|
||||
# CHECK: Name: .text
|
||||
# CHECK: Type: SHT_PROGBITS
|
||||
# CHECK: Flags [ (0xC00007)
|
||||
# CHECK: Flags [ (0x6)
|
||||
# CHECK: SHF_ALLOC (0x2)
|
||||
# CHECK: SHF_AMDGPU_HSA_AGENT (0x800000)
|
||||
# CHECK: SHF_AMDGPU_HSA_CODE (0x400000)
|
||||
# CHECK: SHF_EXECINSTR (0x4)
|
||||
# CHECK: SHF_WRITE (0x1)
|
||||
# CHECK: ]
|
||||
# CHECK: Address: [[HSATEXT_ADDR:[0-9xa-f]+]]
|
||||
# CHECK: }
|
||||
|
||||
# CHECK: Symbol {
|
||||
|
|
@ -45,7 +41,7 @@ kernel1:
|
|||
# CHECK: Size: 4
|
||||
# CHECK: Binding: Global
|
||||
# CHECK: Type: AMDGPU_HSA_KERNEL
|
||||
# CHECK: Section: .hsatext
|
||||
# CHECK: Section: .text
|
||||
# CHECK: }
|
||||
|
||||
# CHECK: Symbol {
|
||||
|
|
@ -54,7 +50,7 @@ kernel1:
|
|||
# CHECK: Size: 8
|
||||
# CHECK: Binding: Global
|
||||
# CHECK: Type: AMDGPU_HSA_KERNEL
|
||||
# CHECK: Section: .hsatext
|
||||
# CHECK: Section: .text
|
||||
# CHECK: }
|
||||
|
||||
# CHECK: ProgramHeader {
|
||||
|
|
|
|||
|
|
@ -19,13 +19,15 @@ g:
|
|||
.section .text.h
|
||||
.global __aeabi_unwind_cpp_pr0
|
||||
__aeabi_unwind_cpp_pr0:
|
||||
nop
|
||||
bx lr
|
||||
|
||||
// CHECK: Disassembly of section .text:
|
||||
// CHECK-NEXT: f:
|
||||
// CHECK-NEXT: 11000: 1e ff 2f e1 bx lr
|
||||
// CHECK: __aeabi_unwind_cpp_pr0:
|
||||
// CHECK-NEXT: 11004: 1e ff 2f e1 bx lr
|
||||
// CHECK-NEXT: 11004: 00 f0 20 e3 nop
|
||||
// CHECK-NEXT: 11008: 1e ff 2f e1 bx lr
|
||||
|
||||
// CHECK: Contents of section .ARM.exidx:
|
||||
// CHECK-NEXT: 100d4 2c0f0000 b0b0b080 280f0000 01000000
|
||||
|
|
|
|||
|
|
@ -19,6 +19,6 @@ _start:
|
|||
// CHECK: Disassembly of section .text:
|
||||
// CHECK-NEXT: _start:
|
||||
// 69636 = 0x11004 = next instruction
|
||||
// CHECK: 11000: 11 f0 02 f8 bl #69636
|
||||
// CHECK-NEXT: 11004: 11 f0 04 b8 b.w #69640
|
||||
// CHECK-NEXT: 11008: 11 f0 06 b8 b.w #69644
|
||||
// CHECK: 11000: {{.*}} bl #69636
|
||||
// CHECK-NEXT: 11004: {{.*}} b.w #69640
|
||||
// CHECK-NEXT: 11008: {{.*}} b.w #69644
|
||||
|
|
|
|||
42
test/ELF/arm-thumb-thunk-symbols.s
Normal file
42
test/ELF/arm-thumb-thunk-symbols.s
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t
|
||||
// RUN: ld.lld %t -o %t2 2>&1
|
||||
// RUN: llvm-readobj --symbols %t2 | FileCheck %s
|
||||
// RUN: ld.lld --shared %t -o %t3 2>&1
|
||||
// RUN: llvm-readobj --symbols %t3 | FileCheck -check-prefix=CHECK-PI %s
|
||||
// REQUIRES: arm
|
||||
|
||||
// Check that the symbols generated for Thunks have the correct symbol type
|
||||
// of STT_FUNC and the correct value of bit 0 (0 for ARM 1 for Thumb)
|
||||
.syntax unified
|
||||
.section .text.thumb, "ax", %progbits
|
||||
.thumb
|
||||
.balign 0x1000
|
||||
.globl thumb_fn
|
||||
.type thumb_fn, %function
|
||||
thumb_fn:
|
||||
b.w arm_fn
|
||||
|
||||
.section .text.arm, "ax", %progbits
|
||||
.arm
|
||||
.balign 0x1000
|
||||
.globl arm_fn
|
||||
.type arm_fn, %function
|
||||
arm_fn:
|
||||
b thumb_fn
|
||||
|
||||
// CHECK: Name: __Thumbv7ABSLongThunk_arm_fn
|
||||
// CHECK-NEXT: Value: 0x11005
|
||||
// CHECK-NEXT: Size: 10
|
||||
// CHECK-NEXT: Binding: Local (0x0)
|
||||
// CHECK-NEXT: Type: Function (0x2)
|
||||
// CHECK: Name: __ARMv7ABSLongThunk_thumb_fn
|
||||
// CHECK-NEXT: Value: 0x11010
|
||||
// CHECK-NEXT: Size: 12
|
||||
// CHECK-NEXT: Binding: Local (0x0)
|
||||
// CHECK-NEXT: Type: Function (0x2)
|
||||
|
||||
// CHECK-PI: Name: __ThumbV7PILongThunk_arm_fn
|
||||
// CHECK-PI-NEXT: Value: 0x1005
|
||||
// CHECK-PI-NEXT: Size: 12
|
||||
// CHECK-PI-NEXT: Binding: Local (0x0)
|
||||
// CHECK-PI-NEXT: Type: Function (0x2)
|
||||
|
|
@ -29,10 +29,10 @@ _start:
|
|||
|
||||
// CHECK: Disassembly of section .text:
|
||||
// 69636 = 0x11004
|
||||
// CHECK: 11000: 11 f0 02 80 beq.w #69636
|
||||
// CHECK-NEXT: 11004: 11 f0 04 b8 b.w #69640
|
||||
// CHECK-NEXT: 11008: 11 f0 06 f8 bl #69644
|
||||
// CHECK: 11000: {{.*}} beq.w #69636
|
||||
// CHECK-NEXT: 11004: {{.*}} b.w #69640
|
||||
// CHECK-NEXT: 11008: {{.*}} bl #69644
|
||||
// blx is transformed into bl so we don't change state
|
||||
// CHECK-NEXT: 1100c: 11 f0 08 f8 bl #69648
|
||||
// CHECK-NEXT: 11010: c0 f2 00 00 movt r0, #0
|
||||
// CHECK-NEXT: 11014: 40 f2 00 00 movw r0, #0
|
||||
// CHECK-NEXT: 1100c: {{.*}} bl #69648
|
||||
// CHECK-NEXT: 11010: {{.*}} movt r0, #0
|
||||
// CHECK-NEXT: 11014: {{.*}} movw r0, #0
|
||||
|
|
|
|||
|
|
@ -29,11 +29,11 @@ _start:
|
|||
|
||||
// CHECK: Disassembly of section .text:
|
||||
// 69636 = 0x11004
|
||||
// CHECK: 11000: 01 44 00 ea b #69636
|
||||
// CHECK-NEXT: 11004: 02 44 00 eb bl #69640
|
||||
// CHECK: 11000: {{.*}} b #69636
|
||||
// CHECK-NEXT: 11004: {{.*}} bl #69640
|
||||
// blx is transformed into bl so we don't change state
|
||||
// CHECK-NEXT: 11008: 03 44 00 eb bl #69644
|
||||
// CHECK-NEXT: 1100c: 00 00 40 e3 movt r0, #0
|
||||
// CHECK-NEXT: 11010: 00 00 00 e3 movw r0, #0
|
||||
// CHECK: 11014: 00 00 00 00 .word 0x00000000
|
||||
// CHECK-NEXT: 11008: {{.*}} bl #69644
|
||||
// CHECK-NEXT: 1100c: {{.*}} movt r0, #0
|
||||
// CHECK-NEXT: 11010: {{.*}} movw r0, #0
|
||||
// CHECK: 11014: {{.*}} .word 0x00000000
|
||||
|
||||
|
|
|
|||
19
test/ELF/dso_handle.s
Normal file
19
test/ELF/dso_handle.s
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
# REQUIRES: x86
|
||||
|
||||
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
|
||||
# RUN: ld.lld -shared %t.o -o %t
|
||||
# RUN: llvm-readobj -symbols %t | FileCheck %s
|
||||
# CHECK: Name: __dso_handle
|
||||
# CHECK-NEXT: Value: 0x0
|
||||
# CHECK-NEXT: Size: 0
|
||||
# CHECK-NEXT: Binding: Local
|
||||
# CHECK-NEXT: Type: None
|
||||
# CHECK-NEXT: Other [
|
||||
# CHECK-NEXT: STV_HIDDEN
|
||||
# CHECK-NEXT: ]
|
||||
# CHECK-NEXT: Section: .dynsym
|
||||
|
||||
.text
|
||||
.global foo, __dso_handle
|
||||
foo:
|
||||
lea __dso_handle(%rip),%rax
|
||||
|
|
@ -13,10 +13,21 @@
|
|||
# CHECK-NEXT: ]
|
||||
# CHECK-NEXT: Section: .text (0x1)
|
||||
|
||||
# CHECK: Name: __executable_start
|
||||
# CHECK-NEXT: Value: 0x200000
|
||||
# CHECK-NEXT: Size: 0
|
||||
# CHECK-NEXT: Binding: Local
|
||||
# CHECK-NEXT: Type: None
|
||||
# CHECK-NEXT: Other [
|
||||
# CHECK-NEXT: STV_HIDDEN
|
||||
# CHECK-NEXT: ]
|
||||
# CHECK-NEXT: Section: .text
|
||||
|
||||
.text
|
||||
.global _start, __ehdr_start
|
||||
_start:
|
||||
.quad __ehdr_start
|
||||
.quad __executable_start
|
||||
|
||||
# RUN: ld.lld -r %t.o -o %t.r
|
||||
# RUN: llvm-readobj -symbols %t.r | FileCheck %s --check-prefix=RELOCATABLE
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
# CHECK-NEXT: 0x1000 R_X86_64_64 zed 0x0
|
||||
# CHECK-NEXT: 0x1008 R_X86_64_64 zed 0x0
|
||||
# CHECK-NEXT: }
|
||||
# CHECK-NEXT: Section ({{.*}}) .rela.data {
|
||||
# CHECK-NEXT: Section ({{.*}}) .rela.data.foo {
|
||||
# CHECK-NEXT: 0x1000 R_X86_64_64 zed 0x0
|
||||
# CHECK-NEXT: 0x1008 R_X86_64_64 zed 0x0
|
||||
# CHECK-NEXT: }
|
||||
|
|
|
|||
|
|
@ -8,109 +8,73 @@
|
|||
# echo "void _start() { __builtin_unreachable(); }" | \
|
||||
# clang -Os -g -S -o gdb-index-empty.s -x c - -Xclang -fdebug-compilation-dir -Xclang .
|
||||
|
||||
.text
|
||||
.file "-"
|
||||
.globl _start
|
||||
.type _start,@function
|
||||
_start: # @_start
|
||||
.text
|
||||
.globl _start
|
||||
.type _start,@function
|
||||
_start:
|
||||
.Lfunc_begin0:
|
||||
.cfi_startproc
|
||||
# BB#0: # %entry
|
||||
.Lfunc_end0:
|
||||
.size _start, .Lfunc_end0-_start
|
||||
.cfi_endproc
|
||||
|
||||
.file 1 "<stdin>"
|
||||
.section .debug_str,"MS",@progbits,1
|
||||
.Linfo_string0:
|
||||
.asciz "clang version 5.0.0 " # string offset=0
|
||||
.Linfo_string1:
|
||||
.asciz "-" # string offset=21
|
||||
.Linfo_string2:
|
||||
.asciz "." # string offset=23
|
||||
.Linfo_string3:
|
||||
.asciz "_start" # string offset=25
|
||||
.section .debug_loc,"",@progbits
|
||||
.section .debug_abbrev,"",@progbits
|
||||
.byte 1 # Abbreviation Code
|
||||
.byte 17 # DW_TAG_compile_unit
|
||||
.byte 1 # DW_CHILDREN_yes
|
||||
.byte 37 # DW_AT_producer
|
||||
.byte 14 # DW_FORM_strp
|
||||
.byte 19 # DW_AT_language
|
||||
.byte 5 # DW_FORM_data2
|
||||
.byte 3 # DW_AT_name
|
||||
.byte 14 # DW_FORM_strp
|
||||
.byte 16 # DW_AT_stmt_list
|
||||
.byte 23 # DW_FORM_sec_offset
|
||||
.byte 27 # DW_AT_comp_dir
|
||||
.byte 14 # DW_FORM_strp
|
||||
.byte 17 # DW_AT_low_pc
|
||||
.byte 1 # DW_FORM_addr
|
||||
.byte 18 # DW_AT_high_pc
|
||||
.byte 6 # DW_FORM_data4
|
||||
.byte 0 # EOM(1)
|
||||
.byte 0 # EOM(2)
|
||||
.byte 2 # Abbreviation Code
|
||||
.byte 46 # DW_TAG_subprogram
|
||||
.byte 0 # DW_CHILDREN_no
|
||||
.byte 17 # DW_AT_low_pc
|
||||
.byte 1 # DW_FORM_addr
|
||||
.byte 18 # DW_AT_high_pc
|
||||
.byte 6 # DW_FORM_data4
|
||||
.byte 64 # DW_AT_frame_base
|
||||
.byte 24 # DW_FORM_exprloc
|
||||
.byte 3 # DW_AT_name
|
||||
.byte 14 # DW_FORM_strp
|
||||
.byte 58 # DW_AT_decl_file
|
||||
.byte 11 # DW_FORM_data1
|
||||
.byte 59 # DW_AT_decl_line
|
||||
.byte 11 # DW_FORM_data1
|
||||
.byte 63 # DW_AT_external
|
||||
.byte 25 # DW_FORM_flag_present
|
||||
.byte 0 # EOM(1)
|
||||
.byte 0 # EOM(2)
|
||||
.byte 0 # EOM(3)
|
||||
.section .debug_info,"",@progbits
|
||||
.Lcu_begin0:
|
||||
.long 60 # Length of Unit
|
||||
.short 4 # DWARF version number
|
||||
.long .debug_abbrev # Offset Into Abbrev. Section
|
||||
.byte 8 # Address Size (in bytes)
|
||||
.byte 1 # Abbrev [1] 0xb:0x35 DW_TAG_compile_unit
|
||||
.long .Linfo_string0 # DW_AT_producer
|
||||
.short 12 # DW_AT_language
|
||||
.long .Linfo_string1 # DW_AT_name
|
||||
.long .Lline_table_start0 # DW_AT_stmt_list
|
||||
.long .Linfo_string2 # DW_AT_comp_dir
|
||||
.quad .Lfunc_begin0 # DW_AT_low_pc
|
||||
.long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
|
||||
.byte 2 # Abbrev [2] 0x2a:0x15 DW_TAG_subprogram
|
||||
.quad .Lfunc_begin0 # DW_AT_low_pc
|
||||
.long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
|
||||
.byte 1 # DW_AT_frame_base
|
||||
.byte 87
|
||||
.long .Linfo_string3 # DW_AT_name
|
||||
.byte 1 # DW_AT_decl_file
|
||||
.byte 1 # DW_AT_decl_line
|
||||
# DW_AT_external
|
||||
.byte 0 # End Of Children Mark
|
||||
.section .debug_ranges,"",@progbits
|
||||
.section .debug_macinfo,"",@progbits
|
||||
.Lcu_macro_begin0:
|
||||
.byte 0 # End Of Macro List Mark
|
||||
.section .debug_pubnames,"",@progbits
|
||||
.long .LpubNames_end0-.LpubNames_begin0 # Length of Public Names Info
|
||||
.LpubNames_begin0:
|
||||
.short 2 # DWARF Version
|
||||
.long .Lcu_begin0 # Offset of Compilation Unit Info
|
||||
.long 64 # Compilation Unit Length
|
||||
.long 42 # DIE offset
|
||||
.asciz "_start" # External Name
|
||||
.long 0 # End Mark
|
||||
.LpubNames_end0:
|
||||
.section .debug_abbrev,"",@progbits
|
||||
.byte 1 # Abbreviation Code
|
||||
.byte 17 # DW_TAG_compile_unit
|
||||
.byte 1 # DW_CHILDREN_yes
|
||||
.byte 37 # DW_AT_producer
|
||||
.byte 14 # DW_FORM_strp
|
||||
.byte 19 # DW_AT_language
|
||||
.byte 5 # DW_FORM_data2
|
||||
.byte 3 # DW_AT_name
|
||||
.byte 14 # DW_FORM_strp
|
||||
.byte 16 # DW_AT_stmt_list
|
||||
.byte 23 # DW_FORM_sec_offset
|
||||
.byte 27 # DW_AT_comp_dir
|
||||
.byte 14 # DW_FORM_strp
|
||||
.byte 17 # DW_AT_low_pc
|
||||
.byte 1 # DW_FORM_addr
|
||||
.byte 18 # DW_AT_high_pc
|
||||
.byte 6 # DW_FORM_data4
|
||||
.byte 0 # EOM(1)
|
||||
.byte 0 # EOM(2)
|
||||
.byte 2 # Abbreviation Code
|
||||
.byte 46 # DW_TAG_subprogram
|
||||
.byte 0 # DW_CHILDREN_no
|
||||
.byte 17 # DW_AT_low_pc
|
||||
.byte 1 # DW_FORM_addr
|
||||
.byte 18 # DW_AT_high_pc
|
||||
.byte 6 # DW_FORM_data4
|
||||
.byte 64 # DW_AT_frame_base
|
||||
.byte 24 # DW_FORM_exprloc
|
||||
.byte 3 # DW_AT_name
|
||||
.byte 14 # DW_FORM_strp
|
||||
.byte 58 # DW_AT_decl_file
|
||||
.byte 11 # DW_FORM_data1
|
||||
.byte 59 # DW_AT_decl_line
|
||||
.byte 11 # DW_FORM_data1
|
||||
.byte 63 # DW_AT_external
|
||||
.byte 25 # DW_FORM_flag_present
|
||||
.byte 0 # EOM(1)
|
||||
.byte 0 # EOM(2)
|
||||
.byte 0 # EOM(3)
|
||||
|
||||
.ident "clang version 5.0.0 "
|
||||
.section ".note.GNU-stack","",@progbits
|
||||
.section .debug_line,"",@progbits
|
||||
.Lline_table_start0:
|
||||
.section .debug_info,"",@progbits
|
||||
.long 60 # Length of Unit
|
||||
.short 4 # DWARF version number
|
||||
.long .debug_abbrev # Offset Into Abbrev. Section
|
||||
.byte 8 # Address Size (in bytes)
|
||||
.byte 1 # Abbrev [1] 0xb:0x35 DW_TAG_compile_unit
|
||||
.long 0 # DW_AT_producer
|
||||
.short 12 # DW_AT_language
|
||||
.long 0 # DW_AT_name
|
||||
.long 0 # DW_AT_stmt_list
|
||||
.long 0 # DW_AT_comp_dir
|
||||
.quad .Lfunc_begin0 # DW_AT_low_pc
|
||||
.long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
|
||||
.byte 2 # Abbrev [2] 0x2a:0x15 DW_TAG_subprogram
|
||||
.quad .Lfunc_begin0 # DW_AT_low_pc
|
||||
.long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
|
||||
.byte 1 # DW_AT_frame_base
|
||||
.byte 87
|
||||
.long 0 # DW_AT_name
|
||||
.byte 1 # DW_AT_decl_file
|
||||
.byte 1 # DW_AT_decl_line
|
||||
.byte 0 # End Of Children Mark
|
||||
|
|
|
|||
15
test/ELF/i386-reloc-large-addend.s
Normal file
15
test/ELF/i386-reloc-large-addend.s
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
// RUN: llvm-mc %s -o %t.o -triple i386-pc-linux-code16 -filetype=obj
|
||||
|
||||
// RUN: echo ".global foo; foo = 0x1" > %t1.s
|
||||
// RUN: llvm-mc %t1.s -o %t1.o -triple i386-pc-linux -filetype=obj
|
||||
|
||||
// RUN: ld.lld -Ttext 0x7000 %t.o %t1.o -o %t
|
||||
// RUN: llvm-objdump -d -triple=i386-pc-linux-code16 %t | FileCheck %s
|
||||
|
||||
// CHECK: Disassembly of section .text:
|
||||
// CHECK-NEXT: _start:
|
||||
// CHECK-NEXT: 7000: e9 fe 1f jmp 8190
|
||||
// 0x1 + 0x9000 - 0x7003 == 8190
|
||||
.global _start
|
||||
_start:
|
||||
jmp foo + 0x9000
|
||||
22
test/ELF/i386-reloc-range.s
Normal file
22
test/ELF/i386-reloc-range.s
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
// RUN: llvm-mc %s -o %t.o -triple i386-pc-linux-code16 -filetype=obj
|
||||
|
||||
// RUN: echo ".global foo; foo = 0x10202" > %t1.s
|
||||
// RUN: llvm-mc %t1.s -o %t1.o -triple i386-pc-linux -filetype=obj
|
||||
// RUN: echo ".global foo; foo = 0x10203" > %t2.s
|
||||
// RUN: llvm-mc %t2.s -o %t2.o -triple i386-pc-linux -filetype=obj
|
||||
|
||||
// RUN: ld.lld -Ttext 0x200 %t.o %t1.o -o %t1
|
||||
// RUN: llvm-objdump -d -triple=i386-pc-linux-code16 %t1 | FileCheck %s
|
||||
|
||||
// CHECK: Disassembly of section .text:
|
||||
// CHECK-NEXT: _start:
|
||||
// CHECK-NEXT: 200: {{.*}} jmp -1
|
||||
// 0x10202 - 0x203 == 0xffff
|
||||
|
||||
// RUN: not ld.lld -Ttext 0x200 %t.o %t2.o -o %t2 2>&1 | FileCheck --check-prefix=ERR %s
|
||||
|
||||
// ERR: {{.*}}:(.text+0x1): relocation R_386_PC16 out of range
|
||||
|
||||
.global _start
|
||||
_start:
|
||||
jmp foo
|
||||
23
test/ELF/icf-comdat.s
Normal file
23
test/ELF/icf-comdat.s
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
# REQUIRES: x86
|
||||
|
||||
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
|
||||
# RUN: ld.lld %t -o %t2 --icf=all --verbose | FileCheck %s
|
||||
|
||||
# CHECK: selected .text.f1
|
||||
# CHECK: removed .text.f2
|
||||
|
||||
.globl _start, f1, f2
|
||||
_start:
|
||||
ret
|
||||
|
||||
.section .text.f1,"ax"
|
||||
f1:
|
||||
mov $60, %rax
|
||||
mov $42, %rdi
|
||||
syscall
|
||||
|
||||
.section .text.f2,"axG",@progbits,foo,comdat
|
||||
f2:
|
||||
mov $60, %rax
|
||||
mov $42, %rdi
|
||||
syscall
|
||||
|
|
@ -7,7 +7,7 @@
|
|||
# RUN: echo "SECTIONS { aaa = ABSOLUTE(foo - 1) + 1; .text : { *(.text*) } }" > %t2.script
|
||||
# RUN: not ld.lld -o %t --script %t2.script %t.o 2>&1 | FileCheck %s
|
||||
|
||||
# CHECK: error: unable to evaluate expression: input section .text has no output section assigned
|
||||
# CHECK: error: {{.*}}.script:1: unable to evaluate expression: input section .text has no output section assigned
|
||||
|
||||
.section .text
|
||||
.globl foo
|
||||
|
|
|
|||
20
test/ELF/linkerscript/emit-relocs-multiple.s
Normal file
20
test/ELF/linkerscript/emit-relocs-multiple.s
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
# REQUIRES: x86
|
||||
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
|
||||
# RUN: echo "SECTIONS { .zed : { *(.foo) *(.bar) } }" > %t.script
|
||||
# RUN: ld.lld --emit-relocs --script %t.script %t.o -o %t1
|
||||
# RUN: llvm-readobj -r %t1 | FileCheck %s
|
||||
|
||||
# CHECK: Relocations [
|
||||
# CHECK-NEXT: Section {{.*}} .rela.foo {
|
||||
# CHECK-NEXT: 0x1 R_X86_64_32 .zed 0x0
|
||||
# CHECK-NEXT: 0x6 R_X86_64_32 .zed 0x5
|
||||
# CHECK-NEXT: }
|
||||
# CHECK-NEXT: ]
|
||||
|
||||
.section .foo,"ax",@progbits
|
||||
aaa:
|
||||
movl $aaa, %edx
|
||||
|
||||
.section .bar,"ax",@progbits
|
||||
bbb:
|
||||
movl $bbb, %edx
|
||||
|
|
@ -3,4 +3,4 @@
|
|||
# RUN: echo "SECTIONS { foo = ADDR(.text) + ADDR(.text); };" > %t.script
|
||||
# RUN: not ld.lld -o %t.so --script %t.script %t.o -shared 2>&1 | FileCheck %s
|
||||
|
||||
# CHECK: At least one side of the expression must be absolute
|
||||
# CHECK: error: {{.*}}.script:1: at least one side of the expression must be absolute
|
||||
|
|
|
|||
46
test/ELF/linkerscript/noload.s
Normal file
46
test/ELF/linkerscript/noload.s
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
# REQUIRES: x86
|
||||
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
|
||||
# RUN: echo "SECTIONS { \
|
||||
# RUN: .data_noload_a (NOLOAD) : { *(.data_noload_a) } \
|
||||
# RUN: .data_noload_b (0x10000) (NOLOAD) : { *(.data_noload_b) } };" > %t.script
|
||||
# RUN: ld.lld -o %t --script %t.script %t.o
|
||||
# RUN: llvm-readobj --symbols -sections %t
|
||||
|
||||
# CHECK: Section {
|
||||
# CHECK-NEXT: Index: 2
|
||||
# CHECK-NEXT: Name: .data_noload_a
|
||||
# CHECK-NEXT: Type: SHT_NOBITS
|
||||
# CHECK-NEXT: Flags [
|
||||
# CHECK-NEXT: SHF_ALLOC
|
||||
# CHECK-NEXT: SHF_WRITE
|
||||
# CHECK-NEXT: ]
|
||||
# CHECK-NEXT: Address: 0x0
|
||||
# CHECK-NEXT: Offset: 0x1000
|
||||
# CHECK-NEXT: Size: 4096
|
||||
# CHECK-NEXT: Link: 0
|
||||
# CHECK-NEXT: Info: 0
|
||||
# CHECK-NEXT: AddressAlignment: 1
|
||||
# CHECK-NEXT: EntrySize: 0
|
||||
# CHECK-NEXT: }
|
||||
# CHECK-NEXT: Section {
|
||||
# CHECK-NEXT: Index: 3
|
||||
# CHECK-NEXT: Name: .data_noload_b
|
||||
# CHECK-NEXT: Type: SHT_NOBITS
|
||||
# CHECK-NEXT: Flags [
|
||||
# CHECK-NEXT: SHF_ALLOC
|
||||
# CHECK-NEXT: SHF_WRITE
|
||||
# CHECK-NEXT: ]
|
||||
# CHECK-NEXT: Address: 0x10000
|
||||
# CHECK-NEXT: Offset: 0x1000
|
||||
# CHECK-NEXT: Size: 4096
|
||||
# CHECK-NEXT: Link: 0
|
||||
# CHECK-NEXT: Info: 0
|
||||
# CHECK-NEXT: AddressAlignment: 1
|
||||
# CHECK-NEXT: EntrySize: 0
|
||||
# CHECK-NEXT: }
|
||||
|
||||
.section .data_noload_a,"aw",@progbits
|
||||
.zero 4096
|
||||
|
||||
.section .data_noload_b,"aw",@progbits
|
||||
.zero 4096
|
||||
21
test/ELF/lto/Inputs/defsym-bar.ll
Normal file
21
test/ELF/lto/Inputs/defsym-bar.ll
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64-unknown-linux-gnu"
|
||||
|
||||
declare void @this_is_bar1()
|
||||
declare void @this_is_bar2()
|
||||
declare void @this_is_bar3()
|
||||
|
||||
define hidden void @bar1() {
|
||||
call void @this_is_bar1()
|
||||
ret void
|
||||
}
|
||||
|
||||
define hidden void @bar2() {
|
||||
call void @this_is_bar2()
|
||||
ret void
|
||||
}
|
||||
|
||||
define hidden void @bar3() {
|
||||
call void @this_is_bar3()
|
||||
ret void
|
||||
}
|
||||
14
test/ELF/lto/Inputs/wrap-bar.ll
Normal file
14
test/ELF/lto/Inputs/wrap-bar.ll
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64-unknown-linux-gnu"
|
||||
|
||||
define hidden void @bar() {
|
||||
ret void
|
||||
}
|
||||
|
||||
define hidden void @__real_bar() {
|
||||
ret void
|
||||
}
|
||||
|
||||
define hidden void @__wrap_bar() {
|
||||
ret void
|
||||
}
|
||||
28
test/ELF/lto/defsym.ll
Normal file
28
test/ELF/lto/defsym.ll
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
; REQUIRES: x86
|
||||
; RUN: llvm-as %s -o %t.o
|
||||
; RUN: llvm-as %S/Inputs/defsym-bar.ll -o %t1.o
|
||||
; RUN: ld.lld %t.o %t1.o -shared -o %t.so -defsym=bar2=bar3
|
||||
; RUN: llvm-objdump -d %t.so | FileCheck %s
|
||||
|
||||
; Call to bar2() should not be inlined and should be routed to bar3()
|
||||
; Symbol bar3 should not be eliminated
|
||||
|
||||
; CHECK: foo:
|
||||
; CHECK-NEXT: pushq %rax
|
||||
; CHECK-NEXT: callq
|
||||
; CHECK-NEXT: callq{{.*}}<bar3>
|
||||
; CHECK-NEXT: callq
|
||||
|
||||
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64-unknown-linux-gnu"
|
||||
|
||||
declare void @bar1()
|
||||
declare void @bar2()
|
||||
declare void @bar3()
|
||||
|
||||
define void @foo() {
|
||||
call void @bar1()
|
||||
call void @bar2()
|
||||
call void @bar3()
|
||||
ret void
|
||||
}
|
||||
35
test/ELF/lto/wrap-1.ll
Normal file
35
test/ELF/lto/wrap-1.ll
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
; REQUIRES: x86
|
||||
; RUN: llvm-as %s -o %t.o
|
||||
; RUN: ld.lld %t.o -o %t.out -wrap=bar -save-temps
|
||||
; RUN: llvm-readobj -t %t.out | FileCheck %s
|
||||
; RUN: cat %t.out.resolution.txt | FileCheck -check-prefix=RESOLS %s
|
||||
|
||||
; CHECK: Name: __wrap_bar
|
||||
; CHECK-NEXT: Value:
|
||||
; CHECK-NEXT: Size:
|
||||
; CHECK-NEXT: Binding: Global
|
||||
; CHECK-NEXT: Type: Function
|
||||
|
||||
; Make sure that the 'r' (linker redefined) bit is set for bar and __wrap_bar
|
||||
; in the resolutions file.
|
||||
; RESOLS: ,bar,r
|
||||
; RESOLS: ,__wrap_bar,px
|
||||
; RESOLS: ,__real_bar,pxr
|
||||
|
||||
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64-unknown-linux-gnu"
|
||||
|
||||
declare void @bar()
|
||||
|
||||
define void @_start() {
|
||||
call void @bar()
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @__wrap_bar() {
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @__real_bar() {
|
||||
ret void
|
||||
}
|
||||
36
test/ELF/lto/wrap-2.ll
Normal file
36
test/ELF/lto/wrap-2.ll
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
; REQUIRES: x86
|
||||
; RUN: llvm-as %s -o %t.o
|
||||
; RUN: llvm-as %S/Inputs/wrap-bar.ll -o %t1.o
|
||||
; RUN: ld.lld %t.o %t1.o -shared -o %t.so -wrap=bar
|
||||
; RUN: llvm-objdump -d %t.so | FileCheck %s
|
||||
; RUN: llvm-readobj -t %t.so | FileCheck -check-prefix=BIND %s
|
||||
|
||||
; Make sure that calls in foo() are not eliminated and that bar is
|
||||
; routed to __wrap_bar and __real_bar is routed to bar.
|
||||
|
||||
; CHECK: foo:
|
||||
; CHECK-NEXT: pushq %rax
|
||||
; CHECK-NEXT: callq{{.*}}<__wrap_bar>
|
||||
; CHECK-NEXT: callq{{.*}}<bar>
|
||||
|
||||
; Check that bar and __wrap_bar retain their original binding.
|
||||
; BIND: Name: bar
|
||||
; BIND-NEXT: Value:
|
||||
; BIND-NEXT: Size:
|
||||
; BIND-NEXT: Binding: Local
|
||||
; BIND: Name: __wrap_bar
|
||||
; BIND-NEXT: Value:
|
||||
; BIND-NEXT: Size:
|
||||
; BIND-NEXT: Binding: Local
|
||||
|
||||
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64-unknown-linux-gnu"
|
||||
|
||||
declare void @bar()
|
||||
declare void @__real_bar()
|
||||
|
||||
define void @foo() {
|
||||
call void @bar()
|
||||
call void @__real_bar()
|
||||
ret void
|
||||
}
|
||||
255
test/ELF/mips-npic-call-pic-script.s
Normal file
255
test/ELF/mips-npic-call-pic-script.s
Normal file
|
|
@ -0,0 +1,255 @@
|
|||
# REQUIRES: mips
|
||||
# Check LA25 stubs creation. This stub code is necessary when
|
||||
# non-PIC code calls PIC function.
|
||||
# RUN: echo "SECTIONS { .out 0x20000 : { *(.text.*) . = . + 0x100 ; *(.text) } }" > %t1.script
|
||||
# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \
|
||||
# RUN: %p/Inputs/mips-fpic.s -o %t-fpic.o
|
||||
# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \
|
||||
# RUN: %p/Inputs/mips-fnpic.s -o %t-fnpic.o
|
||||
# RUN: ld.lld -r %t-fpic.o %t-fnpic.o -o %t-sto-pic.o
|
||||
# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \
|
||||
# RUN: %p/Inputs/mips-pic.s -o %t-pic.o
|
||||
# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t-npic.o
|
||||
# RUN: ld.lld --script %t1.script %t-npic.o %t-pic.o %t-sto-pic.o -o %t.exe
|
||||
# RUN: llvm-objdump -d %t.exe | FileCheck %s
|
||||
|
||||
# CHECK: Disassembly of section .out:
|
||||
# CHECK-NEXT: __LA25Thunk_foo1a:
|
||||
# CHECK-NEXT: 20000: 3c 19 00 02 lui $25, 2
|
||||
# CHECK-NEXT: 20004: 08 00 80 08 j 131104 <foo1a>
|
||||
# CHECK-NEXT: 20008: 27 39 00 20 addiu $25, $25, 32
|
||||
# CHECK-NEXT: 2000c: 00 00 00 00 nop
|
||||
# CHECK: __LA25Thunk_foo1b:
|
||||
# CHECK-NEXT: 20010: 3c 19 00 02 lui $25, 2
|
||||
# CHECK-NEXT: 20014: 08 00 80 09 j 131108 <foo1b>
|
||||
# CHECK-NEXT: 20018: 27 39 00 24 addiu $25, $25, 36
|
||||
# CHECK-NEXT: 2001c: 00 00 00 00 nop
|
||||
# CHECK: foo1a:
|
||||
# CHECK-NEXT: 20020: 00 00 00 00 nop
|
||||
# CHECK: foo1b:
|
||||
# CHECK-NEXT: 20024: 00 00 00 00 nop
|
||||
# CHECK: __LA25Thunk_foo2:
|
||||
# CHECK-NEXT: 20028: 3c 19 00 02 lui $25, 2
|
||||
# CHECK-NEXT: 2002c: 08 00 80 10 j 131136 <foo2>
|
||||
# CHECK-NEXT: 20030: 27 39 00 40 addiu $25, $25, 64
|
||||
# CHECK-NEXT: 20034: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 20038: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 2003c: 00 00 00 00 nop
|
||||
# CHECK: foo2:
|
||||
# CHECK-NEXT: 20040: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 20044: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 20048: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 2004c: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 20050: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 20054: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 20058: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 2005c: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 20060: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 20064: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 20068: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 2006c: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 20070: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 20074: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 20078: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 2007c: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 20080: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 20084: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 20088: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 2008c: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 20090: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 20094: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 20098: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 2009c: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 200a0: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 200a4: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 200a8: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 200ac: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 200b0: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 200b4: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 200b8: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 200bc: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 200c0: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 200c4: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 200c8: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 200cc: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 200d0: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 200d4: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 200d8: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 200dc: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 200e0: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 200e4: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 200e8: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 200ec: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 200f0: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 200f4: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 200f8: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 200fc: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 20100: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 20104: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 20108: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 2010c: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 20110: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 20114: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 20118: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 2011c: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 20120: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 20124: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 20128: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 2012c: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 20130: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 20134: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 20138: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 2013c: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 20140: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 20144: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 20148: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 2014c: 00 00 00 00 nop
|
||||
# CHECK: __start:
|
||||
# CHECK-NEXT: 20150: 0c 00 80 00 jal 131072 <__LA25Thunk_foo1a>
|
||||
# CHECK-NEXT: 20154: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 20158: 0c 00 80 0a jal 131112 <__LA25Thunk_foo2>
|
||||
# CHECK-NEXT: 2015c: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 20160: 0c 00 80 04 jal 131088 <__LA25Thunk_foo1b>
|
||||
# CHECK-NEXT: 20164: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 20168: 0c 00 80 0a jal 131112 <__LA25Thunk_foo2>
|
||||
# CHECK-NEXT: 2016c: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 20170: 0c 00 80 60 jal 131456 <__LA25Thunk_fpic>
|
||||
# CHECK-NEXT: 20174: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 20178: 0c 00 80 68 jal 131488 <fnpic>
|
||||
# CHECK-NEXT: 2017c: 00 00 00 00 nop
|
||||
# CHECK: __LA25Thunk_fpic:
|
||||
# CHECK-NEXT: 20180: 3c 19 00 02 lui $25, 2
|
||||
# CHECK-NEXT: 20184: 08 00 80 64 j 131472 <fpic>
|
||||
# CHECK-NEXT: 20188: 27 39 01 90 addiu $25, $25, 400
|
||||
# CHECK-NEXT: 2018c: 00 00 00 00 nop
|
||||
# CHECK: fpic:
|
||||
# CHECK-NEXT: 20190: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 20194: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 20198: 00 00 00 00 nop
|
||||
# CHECK-NEXT: 2019c: 00 00 00 00 nop
|
||||
# CHECK: fnpic:
|
||||
# CHECK-NEXT: 201a0: 00 00 00 00 nop
|
||||
|
||||
.text
|
||||
.globl __start
|
||||
__start:
|
||||
jal foo1a
|
||||
jal foo2
|
||||
jal foo1b
|
||||
jal foo2
|
||||
jal fpic
|
||||
jal fnpic
|
||||
|
||||
# Test script with orphans added to existing OutputSection, the .text.1 and
|
||||
# .text.2 sections will be added to .text
|
||||
# RUN: echo "SECTIONS { .text 0x20000 : { *(.text) } }" > %t2.script
|
||||
# RUN: ld.lld --script %t2.script %t-npic.o %t-pic.o %t-sto-pic.o -o %t2.exe
|
||||
# RUN: llvm-objdump -d %t2.exe | FileCheck -check-prefix=ORPH1 %s
|
||||
# ORPH1: Disassembly of section .text:
|
||||
# ORPH1-NEXT: __start:
|
||||
# ORPH1-NEXT: 20000: 0c 00 80 15 jal 131156 <__LA25Thunk_foo1a>
|
||||
# ORPH1-NEXT: 20004: 00 00 00 00 nop
|
||||
# ORPH1-NEXT: 20008: 0c 00 80 22 jal 131208 <__LA25Thunk_foo2>
|
||||
# ORPH1-NEXT: 2000c: 00 00 00 00 nop
|
||||
# ORPH1-NEXT: 20010: 0c 00 80 19 jal 131172 <__LA25Thunk_foo1b>
|
||||
# ORPH1-NEXT: 20014: 00 00 00 00 nop
|
||||
# ORPH1-NEXT: 20018: 0c 00 80 22 jal 131208 <__LA25Thunk_foo2>
|
||||
# ORPH1-NEXT: 2001c: 00 00 00 00 nop
|
||||
# ORPH1-NEXT: 20020: 0c 00 80 0c jal 131120 <__LA25Thunk_fpic>
|
||||
# ORPH1-NEXT: 20024: 00 00 00 00 nop
|
||||
# ORPH1-NEXT: 20028: 0c 00 80 14 jal 131152 <fnpic>
|
||||
# ORPH1-NEXT: 2002c: 00 00 00 00 nop
|
||||
# ORPH1: __LA25Thunk_fpic:
|
||||
# ORPH1-NEXT: 20030: 3c 19 00 02 lui $25, 2
|
||||
# ORPH1-NEXT: 20034: 08 00 80 10 j 131136 <fpic>
|
||||
# ORPH1-NEXT: 20038: 27 39 00 40 addiu $25, $25, 64
|
||||
# ORPH1-NEXT: 2003c: 00 00 00 00 nop
|
||||
# ORPH1: fpic:
|
||||
# ORPH1-NEXT: 20040: 00 00 00 00 nop
|
||||
# ORPH1-NEXT: 20044: 00 00 00 00 nop
|
||||
# ORPH1-NEXT: 20048: 00 00 00 00 nop
|
||||
# ORPH1-NEXT: 2004c: 00 00 00 00 nop
|
||||
# ORPH1: fnpic:
|
||||
# ORPH1-NEXT: 20050: 00 00 00 00 nop
|
||||
# ORPH1: __LA25Thunk_foo1a:
|
||||
# ORPH1-NEXT: 20054: 3c 19 00 02 lui $25, 2
|
||||
# ORPH1-NEXT: 20058: 08 00 80 20 j 131200 <foo1a>
|
||||
# ORPH1-NEXT: 2005c: 27 39 00 80 addiu $25, $25, 128
|
||||
# ORPH1-NEXT: 20060: 00 00 00 00 nop
|
||||
# ORPH1: __LA25Thunk_foo1b:
|
||||
# ORPH1-NEXT: 20064: 3c 19 00 02 lui $25, 2
|
||||
# ORPH1-NEXT: 20068: 08 00 80 21 j 131204 <foo1b>
|
||||
# ORPH1-NEXT: 2006c: 27 39 00 84 addiu $25, $25, 132
|
||||
# ORPH1-NEXT: 20070: 00 00 00 00 nop
|
||||
# ORPH1-NEXT: 20074: 00 00 00 00 nop
|
||||
# ORPH1-NEXT: 20078: 00 00 00 00 nop
|
||||
# ORPH1-NEXT: 2007c: 00 00 00 00 nop
|
||||
# ORPH1: foo1a:
|
||||
# ORPH1-NEXT: 20080: 00 00 00 00 nop
|
||||
# ORPH1: foo1b:
|
||||
# ORPH1-NEXT: 20084: 00 00 00 00 nop
|
||||
# ORPH1: __LA25Thunk_foo2:
|
||||
# ORPH1-NEXT: 20088: 3c 19 00 02 lui $25, 2
|
||||
# ORPH1-NEXT: 2008c: 08 00 80 28 j 131232 <foo2>
|
||||
# ORPH1-NEXT: 20090: 27 39 00 a0 addiu $25, $25, 160
|
||||
# ORPH1-NEXT: 20094: 00 00 00 00 nop
|
||||
# ORPH1-NEXT: 20098: 00 00 00 00 nop
|
||||
# ORPH1-NEXT: 2009c: 00 00 00 00 nop
|
||||
# ORPH1: foo2:
|
||||
# ORPH1-NEXT: 200a0: 00 00 00 00 nop
|
||||
|
||||
# Test script with orphans added to new OutputSection, the .text.1 and
|
||||
# .text.2 sections will form a new OutputSection .text
|
||||
# RUN: echo "SECTIONS { .out 0x20000 : { *(.text) } }" > %t3.script
|
||||
# RUN: ld.lld --script %t3.script %t-npic.o %t-pic.o %t-sto-pic.o -o %t3.exe
|
||||
# RUN: llvm-objdump -d %t3.exe | FileCheck -check-prefix=ORPH2 %s
|
||||
# ORPH2: Disassembly of section .out:
|
||||
# ORPH2-NEXT: __start:
|
||||
# ORPH2-NEXT: 20000: 0c 00 80 18 jal 131168 <__LA25Thunk_foo1a>
|
||||
# ORPH2-NEXT: 20004: 00 00 00 00 nop
|
||||
# ORPH2-NEXT: 20008: 0c 00 80 22 jal 131208 <__LA25Thunk_foo2>
|
||||
# ORPH2-NEXT: 2000c: 00 00 00 00 nop
|
||||
# ORPH2-NEXT: 20010: 0c 00 80 1c jal 131184 <__LA25Thunk_foo1b>
|
||||
# ORPH2-NEXT: 20014: 00 00 00 00 nop
|
||||
# ORPH2-NEXT: 20018: 0c 00 80 22 jal 131208 <__LA25Thunk_foo2>
|
||||
# ORPH2-NEXT: 2001c: 00 00 00 00 nop
|
||||
# ORPH2-NEXT: 20020: 0c 00 80 0c jal 131120 <__LA25Thunk_fpic>
|
||||
# ORPH2-NEXT: 20024: 00 00 00 00 nop
|
||||
# ORPH2-NEXT: 20028: 0c 00 80 14 jal 131152 <fnpic>
|
||||
# ORPH2-NEXT: 2002c: 00 00 00 00 nop
|
||||
# ORPH2: __LA25Thunk_fpic:
|
||||
# ORPH2-NEXT: 20030: 3c 19 00 02 lui $25, 2
|
||||
# ORPH2-NEXT: 20034: 08 00 80 10 j 131136 <fpic>
|
||||
# ORPH2-NEXT: 20038: 27 39 00 40 addiu $25, $25, 64
|
||||
# ORPH2-NEXT: 2003c: 00 00 00 00 nop
|
||||
# ORPH2: fpic:
|
||||
# ORPH2-NEXT: 20040: 00 00 00 00 nop
|
||||
# ORPH2-NEXT: 20044: 00 00 00 00 nop
|
||||
# ORPH2-NEXT: 20048: 00 00 00 00 nop
|
||||
# ORPH2-NEXT: 2004c: 00 00 00 00 nop
|
||||
# ORPH2: fnpic:
|
||||
# ORPH2-NEXT: 20050: 00 00 00 00 nop
|
||||
# ORPH2-NEXT: Disassembly of section .text:
|
||||
# ORPH2-NEXT: __LA25Thunk_foo1a:
|
||||
# ORPH2-NEXT: 20060: 3c 19 00 02 lui $25, 2
|
||||
# ORPH2-NEXT: 20064: 08 00 80 20 j 131200 <foo1a>
|
||||
# ORPH2-NEXT: 20068: 27 39 00 80 addiu $25, $25, 128
|
||||
# ORPH2-NEXT: 2006c: 00 00 00 00 nop
|
||||
# ORPH2: __LA25Thunk_foo1b:
|
||||
# ORPH2-NEXT: 20070: 3c 19 00 02 lui $25, 2
|
||||
# ORPH2-NEXT: 20074: 08 00 80 21 j 131204 <foo1b>
|
||||
# ORPH2-NEXT: 20078: 27 39 00 84 addiu $25, $25, 132
|
||||
# ORPH2-NEXT: 2007c: 00 00 00 00 nop
|
||||
# ORPH2: foo1a:
|
||||
# ORPH2-NEXT: 20080: 00 00 00 00 nop
|
||||
# ORPH2: foo1b:
|
||||
# ORPH2-NEXT: 20084: 00 00 00 00 nop
|
||||
# ORPH2: __LA25Thunk_foo2:
|
||||
# ORPH2-NEXT: 20088: 3c 19 00 02 lui $25, 2
|
||||
# ORPH2-NEXT: 2008c: 08 00 80 28 j 131232 <foo2>
|
||||
# ORPH2-NEXT: 20090: 27 39 00 a0 addiu $25, $25, 160
|
||||
# ORPH2-NEXT: 20094: 00 00 00 00 nop
|
||||
# ORPH2-NEXT: 20098: 00 00 00 00 nop
|
||||
# ORPH2-NEXT: 2009c: 00 00 00 00 nop
|
||||
# ORPH2: foo2:
|
||||
# ORPH2-NEXT: 200a0: 00 00 00 00 nop
|
||||
31
test/ELF/relocatable-comdat-multiple.s
Normal file
31
test/ELF/relocatable-comdat-multiple.s
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
# REQUIRES: x86
|
||||
# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
|
||||
# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %S/Inputs/relocatable-comdat-multiple.s -o %t2.o
|
||||
# RUN: ld.lld -r %t.o %t2.o -o %t
|
||||
# RUN: llvm-readobj -elf-section-groups %t | FileCheck %s
|
||||
|
||||
# CHECK: Groups {
|
||||
# CHECK-NEXT: Group {
|
||||
# CHECK-NEXT: Name: .group
|
||||
# CHECK-NEXT: Index: 2
|
||||
# CHECK-NEXT: Type: COMDAT
|
||||
# CHECK-NEXT: Signature: aaa
|
||||
# CHECK-NEXT: Section(s) in group [
|
||||
# CHECK-NEXT: .text.a
|
||||
# CHECK-NEXT: .text.b
|
||||
# CHECK-NEXT: ]
|
||||
# CHECK-NEXT: }
|
||||
# CHECK-NEXT: Group {
|
||||
# CHECK-NEXT: Name: .group
|
||||
# CHECK-NEXT: Index: 5
|
||||
# CHECK-NEXT: Type: COMDAT
|
||||
# CHECK-NEXT: Signature: bbb
|
||||
# CHECK-NEXT: Section(s) in group [
|
||||
# CHECK-NEXT: .text.c
|
||||
# CHECK-NEXT: .text.d
|
||||
# CHECK-NEXT: ]
|
||||
# CHECK-NEXT: }
|
||||
# CHECK-NEXT: }
|
||||
|
||||
.section .text.a,"axG",@progbits,aaa,comdat
|
||||
.section .text.b,"axG",@progbits,aaa,comdat
|
||||
45
test/ELF/relocatable-compressed-input.s
Normal file
45
test/ELF/relocatable-compressed-input.s
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
# REQUIRES: zlib
|
||||
|
||||
# RUN: llvm-mc -compress-debug-sections=zlib-gnu -filetype=obj -triple=x86_64-unknown-linux %s -o %t1
|
||||
# RUN: llvm-readobj -sections %t1 | FileCheck -check-prefix=GNU %s
|
||||
# GNU: Name: .zdebug_str
|
||||
|
||||
# RUN: ld.lld %t1 -o %t2 -r
|
||||
# RUN: llvm-readobj -sections -section-data %t2 | FileCheck %s
|
||||
|
||||
## Check we decompress section and remove ".z" prefix specific for zlib-gnu compression.
|
||||
# CHECK: Section {
|
||||
# CHECK: Index:
|
||||
# CHECK: Name: .debug_str
|
||||
# CHECK-NEXT: Type: SHT_PROGBITS
|
||||
# CHECK-NEXT: Flags [
|
||||
# CHECK-NEXT: SHF_MERGE
|
||||
# CHECK-NEXT: SHF_STRINGS
|
||||
# CHECK-NEXT: ]
|
||||
# CHECK-NEXT: Address:
|
||||
# CHECK-NEXT: Offset:
|
||||
# CHECK-NEXT: Size:
|
||||
# CHECK-NEXT: Link:
|
||||
# CHECK-NEXT: Info:
|
||||
# CHECK-NEXT: AddressAlignment: 1
|
||||
# CHECK-NEXT: EntrySize: 1
|
||||
# CHECK-NEXT: SectionData (
|
||||
# CHECK-NEXT: 0000: {{.*}} |short unsigned i|
|
||||
# CHECK-NEXT: 0010: {{.*}} |nt.unsigned int.|
|
||||
# CHECK-NEXT: 0020: {{.*}} |long unsigned in|
|
||||
# CHECK-NEXT: 0030: {{.*}} |t.char.unsigned |
|
||||
# CHECK-NEXT: 0040: {{.*}} |char.|
|
||||
# CHECK-NEXT: )
|
||||
# CHECK-NEXT: }
|
||||
|
||||
.section .debug_str,"MS",@progbits,1
|
||||
.LASF2:
|
||||
.string "short unsigned int"
|
||||
.LASF3:
|
||||
.string "unsigned int"
|
||||
.LASF0:
|
||||
.string "long unsigned int"
|
||||
.LASF8:
|
||||
.string "char"
|
||||
.LASF1:
|
||||
.string "unsigned char"
|
||||
10
test/ELF/relocatable-empty-archive.s
Normal file
10
test/ELF/relocatable-empty-archive.s
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
# REQUIRES: x86
|
||||
# RUN: rm -f %t.a
|
||||
# RUN: llvm-ar rc %t.a
|
||||
# RUN: ld.lld -m elf_x86_64 %t.a -o %t -r
|
||||
# RUN: llvm-readobj -file-headers %t | FileCheck %s
|
||||
|
||||
# CHECK: Format: ELF64-x86-64
|
||||
# CHECK: Arch: x86_64
|
||||
# CHECK: AddressSize: 64bit
|
||||
# CHECK: Type: Relocatable
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
#include "lld/Driver/Driver.h"
|
||||
#include "lld/ReaderWriter/MachOLinkingContext.h"
|
||||
#include "llvm/Support/MachO.h"
|
||||
#include "llvm/BinaryFormat/MachO.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -7,14 +7,14 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "../../lib/ReaderWriter/MachO/MachONormalizedFile.h"
|
||||
#include "lld/ReaderWriter/MachOLinkingContext.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/BinaryFormat/MachO.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include "llvm/Support/MachO.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
#include "llvm/Support/YAMLTraits.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
|
||||
|
|
|
|||
|
|
@ -7,11 +7,11 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "../../lib/ReaderWriter/MachO/MachONormalizedFile.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
#include "llvm/BinaryFormat/MachO.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
#include "llvm/Support/MachO.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
#include <system_error>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "../../lib/ReaderWriter/MachO/MachONormalizedFile.h"
|
||||
#include "lld/Core/Atom.h"
|
||||
#include "lld/Core/DefinedAtom.h"
|
||||
|
|
@ -15,9 +14,10 @@
|
|||
#include "lld/Core/UndefinedAtom.h"
|
||||
#include "lld/ReaderWriter/MachOLinkingContext.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/BinaryFormat/MachO.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include "llvm/Support/MachO.h"
|
||||
#include "llvm/Support/YAMLTraits.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
|
||||
|
|
|
|||
|
|
@ -7,18 +7,18 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "../../lib/ReaderWriter/MachO/MachONormalizedFile.h"
|
||||
#include "lld/ReaderWriter/MachOLinkingContext.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/BinaryFormat/MachO.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include "llvm/Support/MachO.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <system_error>
|
||||
#include <string>
|
||||
#include <system_error>
|
||||
|
||||
using llvm::StringRef;
|
||||
using llvm::MemoryBuffer;
|
||||
|
|
|
|||
Loading…
Reference in a new issue