Vendor import of lld trunk r257626:
https://llvm.org/svn/llvm-project/lld/trunk@257626
This commit is contained in:
parent
fba2c04f31
commit
b289257c7f
@ -1,4 +1,5 @@
|
||||
set(LLD_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
set(LLD_INCLUDE_DIR ${LLD_SOURCE_DIR}/include )
|
||||
set(LLD_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
# Compute the LLD version from the LLVM version.
|
||||
@ -86,6 +87,12 @@ if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY)
|
||||
)
|
||||
endif()
|
||||
|
||||
macro(add_lld_library name)
|
||||
add_llvm_library(${name} ${ARGN})
|
||||
set_target_properties(${name} PROPERTIES FOLDER "lld libraries")
|
||||
endmacro(add_lld_library)
|
||||
|
||||
|
||||
add_subdirectory(lib)
|
||||
add_subdirectory(tools)
|
||||
|
||||
|
@ -2,7 +2,7 @@ set(LLVM_TARGET_DEFINITIONS Options.td)
|
||||
tablegen(LLVM Options.inc -gen-opt-parser-defs)
|
||||
add_public_tablegen_target(COFFOptionsTableGen)
|
||||
|
||||
add_llvm_library(lldCOFF
|
||||
add_lld_library(lldCOFF
|
||||
Chunks.cpp
|
||||
DLL.cpp
|
||||
Driver.cpp
|
||||
|
@ -310,7 +310,7 @@ void SEHTableChunk::writeTo(uint8_t *Buf) const {
|
||||
BaserelChunk::BaserelChunk(uint32_t Page, Baserel *Begin, Baserel *End) {
|
||||
// Block header consists of 4 byte page RVA and 4 byte block size.
|
||||
// Each entry is 2 byte. Last entry may be padding.
|
||||
Data.resize(RoundUpToAlignment((End - Begin) * 2 + 8, 4));
|
||||
Data.resize(align((End - Begin) * 2 + 8, 4));
|
||||
uint8_t *P = Data.data();
|
||||
write32le(P, Page);
|
||||
write32le(P + 4, Data.size());
|
||||
|
@ -326,6 +326,10 @@ public:
|
||||
uint8_t Type;
|
||||
};
|
||||
|
||||
inline uint64_t align(uint64_t Value, uint64_t Align) {
|
||||
return llvm::RoundUpToAlignment(Value, Align);
|
||||
}
|
||||
|
||||
} // namespace coff
|
||||
} // namespace lld
|
||||
|
||||
|
@ -25,6 +25,7 @@ using llvm::COFF::WindowsSubsystem;
|
||||
using llvm::StringRef;
|
||||
class DefinedAbsolute;
|
||||
class DefinedRelative;
|
||||
class StringChunk;
|
||||
class Undefined;
|
||||
|
||||
// Short aliases.
|
||||
@ -42,6 +43,12 @@ struct Export {
|
||||
bool Data = false;
|
||||
bool Private = false;
|
||||
|
||||
// If an export is a form of /export:foo=dllname.bar, that means
|
||||
// that foo should be exported as an alias to bar in the DLL.
|
||||
// ForwardTo is set to "dllname.bar" part. Usually empty.
|
||||
StringRef ForwardTo;
|
||||
StringChunk *ForwardChunk = nullptr;
|
||||
|
||||
// True if this /export option was in .drectves section.
|
||||
bool Directives = false;
|
||||
StringRef SymbolName;
|
||||
|
21
COFF/DLL.cpp
21
COFF/DLL.cpp
@ -45,7 +45,7 @@ public:
|
||||
size_t getSize() const override {
|
||||
// Starts with 2 byte Hint field, followed by a null-terminated string,
|
||||
// ends with 0 or 1 byte padding.
|
||||
return RoundUpToAlignment(Name.size() + 3, 2);
|
||||
return align(Name.size() + 3, 2);
|
||||
}
|
||||
|
||||
void writeTo(uint8_t *Buf) const override {
|
||||
@ -320,8 +320,12 @@ public:
|
||||
|
||||
void writeTo(uint8_t *Buf) const override {
|
||||
for (Export &E : Config->Exports) {
|
||||
auto *D = cast<Defined>(E.Sym->repl());
|
||||
write32le(Buf + OutputSectionOff + E.Ordinal * 4, D->getRVA());
|
||||
uint8_t *P = Buf + OutputSectionOff + E.Ordinal * 4;
|
||||
if (E.ForwardChunk) {
|
||||
write32le(P, E.ForwardChunk->getRVA());
|
||||
} else {
|
||||
write32le(P, cast<Defined>(E.Sym->repl())->getRVA());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -539,6 +543,15 @@ EdataContents::EdataContents() {
|
||||
for (Export &E : Config->Exports)
|
||||
if (!E.Noname)
|
||||
Names.push_back(new StringChunk(E.ExportName));
|
||||
|
||||
std::vector<Chunk *> Forwards;
|
||||
for (Export &E : Config->Exports) {
|
||||
if (E.ForwardTo.empty())
|
||||
continue;
|
||||
E.ForwardChunk = new StringChunk(E.ForwardTo);
|
||||
Forwards.push_back(E.ForwardChunk);
|
||||
}
|
||||
|
||||
auto *NameTab = new NamePointersChunk(Names);
|
||||
auto *OrdinalTab = new ExportOrdinalChunk(Names.size());
|
||||
auto *Dir = new ExportDirectoryChunk(MaxOrdinal, Names.size(), DLLName,
|
||||
@ -550,6 +563,8 @@ EdataContents::EdataContents() {
|
||||
Chunks.push_back(std::unique_ptr<Chunk>(OrdinalTab));
|
||||
for (Chunk *C : Names)
|
||||
Chunks.push_back(std::unique_ptr<Chunk>(C));
|
||||
for (Chunk *C : Forwards)
|
||||
Chunks.push_back(std::unique_ptr<Chunk>(C));
|
||||
}
|
||||
|
||||
} // namespace coff
|
||||
|
@ -586,6 +586,8 @@ void LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
|
||||
|
||||
// Windows specific -- Make sure we resolve all dllexported symbols.
|
||||
for (Export &E : Config->Exports) {
|
||||
if (!E.ForwardTo.empty())
|
||||
continue;
|
||||
E.Sym = addUndefined(E.Name);
|
||||
if (!E.Directives)
|
||||
Symtab.mangleMaybe(E.Sym);
|
||||
|
@ -321,7 +321,8 @@ void createSideBySideManifest() {
|
||||
}
|
||||
|
||||
// Parse a string in the form of
|
||||
// "<name>[=<internalname>][,@ordinal[,NONAME]][,DATA][,PRIVATE]".
|
||||
// "<name>[=<internalname>][,@ordinal[,NONAME]][,DATA][,PRIVATE]"
|
||||
// or "<name>=<dllname>.<name>".
|
||||
// Used for parsing /export arguments.
|
||||
Export parseExport(StringRef Arg) {
|
||||
Export E;
|
||||
@ -329,12 +330,25 @@ Export parseExport(StringRef Arg) {
|
||||
std::tie(E.Name, Rest) = Arg.split(",");
|
||||
if (E.Name.empty())
|
||||
goto err;
|
||||
|
||||
if (E.Name.find('=') != StringRef::npos) {
|
||||
std::tie(E.ExtName, E.Name) = E.Name.split("=");
|
||||
StringRef X, Y;
|
||||
std::tie(X, Y) = E.Name.split("=");
|
||||
|
||||
// If "<name>=<dllname>.<name>".
|
||||
if (Y.find(".") != StringRef::npos) {
|
||||
E.Name = X;
|
||||
E.ForwardTo = Y;
|
||||
return E;
|
||||
}
|
||||
|
||||
E.ExtName = X;
|
||||
E.Name = Y;
|
||||
if (E.Name.empty())
|
||||
goto err;
|
||||
}
|
||||
|
||||
// If "<name>=<internalname>[,@ordinal[,NONAME]][,DATA][,PRIVATE]"
|
||||
while (!Rest.empty()) {
|
||||
StringRef Tok;
|
||||
std::tie(Tok, Rest) = Rest.split(",");
|
||||
@ -388,15 +402,22 @@ void fixupExports() {
|
||||
}
|
||||
|
||||
for (Export &E : Config->Exports) {
|
||||
if (Undefined *U = cast_or_null<Undefined>(E.Sym->WeakAlias)) {
|
||||
if (!E.ForwardTo.empty()) {
|
||||
E.SymbolName = E.Name;
|
||||
} else if (Undefined *U = cast_or_null<Undefined>(E.Sym->WeakAlias)) {
|
||||
E.SymbolName = U->getName();
|
||||
} else {
|
||||
E.SymbolName = E.Sym->getName();
|
||||
}
|
||||
}
|
||||
|
||||
for (Export &E : Config->Exports)
|
||||
for (Export &E : Config->Exports) {
|
||||
if (!E.ForwardTo.empty()) {
|
||||
E.ExportName = undecorate(E.Name);
|
||||
} else {
|
||||
E.ExportName = undecorate(E.ExtName.empty() ? E.Name : E.ExtName);
|
||||
}
|
||||
}
|
||||
|
||||
// Uniquefy by name.
|
||||
std::map<StringRef, Export *> Map;
|
||||
|
@ -23,7 +23,6 @@
|
||||
using namespace llvm::COFF;
|
||||
using namespace llvm::object;
|
||||
using namespace llvm::support::endian;
|
||||
using llvm::RoundUpToAlignment;
|
||||
using llvm::Triple;
|
||||
using llvm::support::ulittle32_t;
|
||||
using llvm::sys::fs::file_magic;
|
||||
|
@ -163,13 +163,13 @@ void OutputSection::addChunk(Chunk *C) {
|
||||
Chunks.push_back(C);
|
||||
C->setOutputSection(this);
|
||||
uint64_t Off = Header.VirtualSize;
|
||||
Off = RoundUpToAlignment(Off, C->getAlign());
|
||||
Off = align(Off, C->getAlign());
|
||||
C->setRVA(Off);
|
||||
C->setOutputSectionOff(Off);
|
||||
Off += C->getSize();
|
||||
Header.VirtualSize = Off;
|
||||
if (C->hasData())
|
||||
Header.SizeOfRawData = RoundUpToAlignment(Off, SectorSize);
|
||||
Header.SizeOfRawData = align(Off, SectorSize);
|
||||
}
|
||||
|
||||
void OutputSection::addPermissions(uint32_t C) {
|
||||
@ -448,15 +448,14 @@ void Writer::createSymbolAndStringTable() {
|
||||
OutputSection *LastSection = OutputSections.back();
|
||||
// We position the symbol table to be adjacent to the end of the last section.
|
||||
uint64_t FileOff =
|
||||
LastSection->getFileOff() +
|
||||
RoundUpToAlignment(LastSection->getRawSize(), SectorSize);
|
||||
LastSection->getFileOff() + align(LastSection->getRawSize(), SectorSize);
|
||||
if (!OutputSymtab.empty()) {
|
||||
PointerToSymbolTable = FileOff;
|
||||
FileOff += OutputSymtab.size() * sizeof(coff_symbol16);
|
||||
}
|
||||
if (!Strtab.empty())
|
||||
FileOff += Strtab.size() + 4;
|
||||
FileSize = RoundUpToAlignment(FileOff, SectorSize);
|
||||
FileSize = align(FileOff, SectorSize);
|
||||
}
|
||||
|
||||
// Visits all sections to assign incremental, non-overlapping RVAs and
|
||||
@ -467,7 +466,7 @@ void Writer::assignAddresses() {
|
||||
sizeof(coff_section) * OutputSections.size();
|
||||
SizeOfHeaders +=
|
||||
Config->is64() ? sizeof(pe32plus_header) : sizeof(pe32_header);
|
||||
SizeOfHeaders = RoundUpToAlignment(SizeOfHeaders, SectorSize);
|
||||
SizeOfHeaders = align(SizeOfHeaders, SectorSize);
|
||||
uint64_t RVA = 0x1000; // The first page is kept unmapped.
|
||||
FileSize = SizeOfHeaders;
|
||||
// Move DISCARDABLE (or non-memory-mapped) sections to the end of file because
|
||||
@ -481,10 +480,10 @@ void Writer::assignAddresses() {
|
||||
addBaserels(Sec);
|
||||
Sec->setRVA(RVA);
|
||||
Sec->setFileOffset(FileSize);
|
||||
RVA += RoundUpToAlignment(Sec->getVirtualSize(), PageSize);
|
||||
FileSize += RoundUpToAlignment(Sec->getRawSize(), SectorSize);
|
||||
RVA += align(Sec->getVirtualSize(), PageSize);
|
||||
FileSize += align(Sec->getRawSize(), SectorSize);
|
||||
}
|
||||
SizeOfImage = SizeOfHeaders + RoundUpToAlignment(RVA - 0x1000, PageSize);
|
||||
SizeOfImage = SizeOfHeaders + align(RVA - 0x1000, PageSize);
|
||||
}
|
||||
|
||||
template <typename PEHeaderTy> void Writer::writeHeader() {
|
||||
|
@ -2,7 +2,7 @@ set(LLVM_TARGET_DEFINITIONS Options.td)
|
||||
tablegen(LLVM Options.inc -gen-opt-parser-defs)
|
||||
add_public_tablegen_target(ELFOptionsTableGen)
|
||||
|
||||
add_llvm_library(lldELF2
|
||||
add_lld_library(lldELF2
|
||||
Driver.cpp
|
||||
DriverUtils.cpp
|
||||
Error.cpp
|
||||
|
@ -26,10 +26,10 @@ using namespace llvm::object;
|
||||
using namespace lld;
|
||||
using namespace lld::elf2;
|
||||
|
||||
Configuration *lld::elf2::Config;
|
||||
LinkerDriver *lld::elf2::Driver;
|
||||
Configuration *elf2::Config;
|
||||
LinkerDriver *elf2::Driver;
|
||||
|
||||
void lld::elf2::link(ArrayRef<const char *> Args) {
|
||||
void elf2::link(ArrayRef<const char *> Args) {
|
||||
Configuration C;
|
||||
LinkerDriver D;
|
||||
Config = &C;
|
||||
@ -42,9 +42,9 @@ static std::pair<ELFKind, uint16_t> parseEmulation(StringRef S) {
|
||||
return {ELF32BEKind, EM_MIPS};
|
||||
if (S == "elf32ltsmip")
|
||||
return {ELF32LEKind, EM_MIPS};
|
||||
if (S == "elf32ppc")
|
||||
if (S == "elf32ppc" || S == "elf32ppc_fbsd")
|
||||
return {ELF32BEKind, EM_PPC};
|
||||
if (S == "elf64ppc")
|
||||
if (S == "elf64ppc" || S == "elf64ppc_fbsd")
|
||||
return {ELF64BEKind, EM_PPC64};
|
||||
if (S == "elf_i386")
|
||||
return {ELF32LEKind, EM_386};
|
||||
@ -107,6 +107,24 @@ void LinkerDriver::addFile(StringRef Path) {
|
||||
}
|
||||
}
|
||||
|
||||
// Some command line options or some combinations of them are not allowed.
|
||||
// This function checks for such errors.
|
||||
static void checkOptions(opt::InputArgList &Args) {
|
||||
// Traditional linkers can generate re-linkable object files instead
|
||||
// of executables or DSOs. We don't support that since the feature
|
||||
// does not seem to provide more value than the static archiver.
|
||||
if (Args.hasArg(OPT_relocatable))
|
||||
error("-r option is not supported. Use 'ar' command instead.");
|
||||
|
||||
// The MIPS ABI as of 2016 does not support the GNU-style symbol lookup
|
||||
// table which is a relatively new feature.
|
||||
if (Config->EMachine == EM_MIPS && Config->GnuHash)
|
||||
error("The .gnu.hash section is not compatible with the MIPS target.");
|
||||
|
||||
if (Config->EMachine == EM_AMDGPU && !Config->Entry.empty())
|
||||
error("-e option is not valid for AMDGPU.");
|
||||
}
|
||||
|
||||
static StringRef
|
||||
getString(opt::InputArgList &Args, unsigned Key, StringRef Default = "") {
|
||||
if (auto *Arg = Args.getLastArg(Key))
|
||||
@ -125,13 +143,9 @@ void LinkerDriver::main(ArrayRef<const char *> ArgsArr) {
|
||||
initSymbols();
|
||||
|
||||
opt::InputArgList Args = parseArgs(&Alloc, ArgsArr);
|
||||
readConfigs(Args);
|
||||
createFiles(Args);
|
||||
|
||||
// Traditional linkers can generate re-linkable object files instead
|
||||
// of executables or DSOs. We don't support that since the feature
|
||||
// does not seem to provide more value than the static archiver.
|
||||
if (Args.hasArg(OPT_relocatable))
|
||||
error("-r option is not supported. Use 'ar' command instead.");
|
||||
checkOptions(Args);
|
||||
|
||||
switch (Config->EKind) {
|
||||
case ELF32LEKind:
|
||||
@ -151,7 +165,8 @@ void LinkerDriver::main(ArrayRef<const char *> ArgsArr) {
|
||||
}
|
||||
}
|
||||
|
||||
void LinkerDriver::createFiles(opt::InputArgList &Args) {
|
||||
// Initializes Config members by the command line options.
|
||||
void LinkerDriver::readConfigs(opt::InputArgList &Args) {
|
||||
for (auto *Arg : Args.filtered(OPT_L))
|
||||
Config->SearchPaths.push_back(Arg->getValue());
|
||||
|
||||
@ -162,10 +177,9 @@ void LinkerDriver::createFiles(opt::InputArgList &Args) {
|
||||
Config->RPath = llvm::join(RPaths.begin(), RPaths.end(), ":");
|
||||
|
||||
if (auto *Arg = Args.getLastArg(OPT_m)) {
|
||||
// Parse ELF{32,64}{LE,BE} and CPU type.
|
||||
StringRef S = Arg->getValue();
|
||||
std::pair<ELFKind, uint16_t> P = parseEmulation(S);
|
||||
Config->EKind = P.first;
|
||||
Config->EMachine = P.second;
|
||||
std::tie(Config->EKind, Config->EMachine) = parseEmulation(S);
|
||||
Config->Emulation = S;
|
||||
}
|
||||
|
||||
@ -217,7 +231,9 @@ void LinkerDriver::createFiles(opt::InputArgList &Args) {
|
||||
|
||||
for (auto *Arg : Args.filtered(OPT_undefined))
|
||||
Config->Undefined.push_back(Arg->getValue());
|
||||
}
|
||||
|
||||
void LinkerDriver::createFiles(opt::InputArgList &Args) {
|
||||
for (auto *Arg : Args) {
|
||||
switch (Arg->getOption().getID()) {
|
||||
case OPT_l:
|
||||
@ -250,9 +266,6 @@ void LinkerDriver::createFiles(opt::InputArgList &Args) {
|
||||
|
||||
if (Files.empty())
|
||||
error("no input files.");
|
||||
|
||||
if (Config->GnuHash && Config->EMachine == EM_MIPS)
|
||||
error("The .gnu.hash section is not compatible with the MIPS target.");
|
||||
}
|
||||
|
||||
template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
|
||||
@ -261,7 +274,10 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
|
||||
|
||||
if (!Config->Shared) {
|
||||
// Add entry symbol.
|
||||
if (Config->Entry.empty())
|
||||
//
|
||||
// There is no entry symbol for AMDGPU binaries, so skip adding one to avoid
|
||||
// having and undefined symbol.
|
||||
if (Config->Entry.empty() && Config->EMachine != EM_AMDGPU)
|
||||
Config->Entry = (Config->EMachine == EM_MIPS) ? "__start" : "_start";
|
||||
|
||||
// In the assembly for 32 bit x86 the _GLOBAL_OFFSET_TABLE_ symbol
|
||||
@ -288,8 +304,9 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
|
||||
|
||||
if (Config->EMachine == EM_MIPS) {
|
||||
// On MIPS O32 ABI, _gp_disp is a magic symbol designates offset between
|
||||
// start of function and gp pointer into GOT.
|
||||
Config->MipsGpDisp = Symtab.addIgnored("_gp_disp");
|
||||
// start of function and gp pointer into GOT. Use 'strong' variant of
|
||||
// the addIgnored to prevent '_gp_disp' substitution.
|
||||
Config->MipsGpDisp = Symtab.addIgnoredStrong("_gp_disp");
|
||||
|
||||
// Define _gp for MIPS. st_value of _gp symbol will be updated by Writer
|
||||
// so that it points to an absolute address which is relative to GOT.
|
||||
@ -304,6 +321,9 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
|
||||
for (StringRef S : Config->Undefined)
|
||||
Symtab.addUndefinedOpt(S);
|
||||
|
||||
for (auto *Arg : Args.filtered(OPT_wrap))
|
||||
Symtab.wrap(Arg->getValue());
|
||||
|
||||
if (Config->OutputFile.empty())
|
||||
Config->OutputFile = "a.out";
|
||||
|
||||
|
@ -26,14 +26,12 @@ void link(ArrayRef<const char *> Args);
|
||||
class LinkerDriver {
|
||||
public:
|
||||
void main(ArrayRef<const char *> Args);
|
||||
void createFiles(llvm::opt::InputArgList &Args);
|
||||
template <class ELFT> void link(llvm::opt::InputArgList &Args);
|
||||
|
||||
void addFile(StringRef Path);
|
||||
|
||||
private:
|
||||
template <template <class> class T>
|
||||
std::unique_ptr<InputFile> createELFInputFile(MemoryBufferRef MB);
|
||||
void readConfigs(llvm::opt::InputArgList &Args);
|
||||
void createFiles(llvm::opt::InputArgList &Args);
|
||||
template <class ELFT> void link(llvm::opt::InputArgList &Args);
|
||||
|
||||
llvm::BumpPtrAllocator Alloc;
|
||||
bool WholeArchive = false;
|
||||
|
@ -51,7 +51,7 @@ public:
|
||||
};
|
||||
|
||||
// Parses a given list of options.
|
||||
opt::InputArgList lld::elf2::parseArgs(llvm::BumpPtrAllocator *A,
|
||||
opt::InputArgList elf2::parseArgs(llvm::BumpPtrAllocator *A,
|
||||
ArrayRef<const char *> Argv) {
|
||||
// Make InputArgList from string vectors.
|
||||
ELFOptTable Table;
|
||||
@ -79,7 +79,7 @@ opt::InputArgList lld::elf2::parseArgs(llvm::BumpPtrAllocator *A,
|
||||
return Args;
|
||||
}
|
||||
|
||||
std::string lld::elf2::findFromSearchPaths(StringRef Path) {
|
||||
std::string elf2::findFromSearchPaths(StringRef Path) {
|
||||
for (StringRef Dir : Config->SearchPaths) {
|
||||
std::string FullPath = buildSysrootedPath(Dir, Path);
|
||||
if (sys::fs::exists(FullPath))
|
||||
@ -90,7 +90,7 @@ std::string lld::elf2::findFromSearchPaths(StringRef Path) {
|
||||
|
||||
// Searches a given library from input search paths, which are filled
|
||||
// from -L command line switches. Returns a path to an existent library file.
|
||||
std::string lld::elf2::searchLibrary(StringRef Path) {
|
||||
std::string elf2::searchLibrary(StringRef Path) {
|
||||
std::vector<std::string> Names;
|
||||
if (Path[0] == ':') {
|
||||
Names.push_back(Path.drop_front());
|
||||
@ -110,7 +110,7 @@ std::string lld::elf2::searchLibrary(StringRef Path) {
|
||||
// Makes a path by concatenating Dir and File.
|
||||
// If Dir starts with '=' the result will be preceded by Sysroot,
|
||||
// which can be set with --sysroot command line switch.
|
||||
std::string lld::elf2::buildSysrootedPath(StringRef Dir, StringRef File) {
|
||||
std::string elf2::buildSysrootedPath(StringRef Dir, StringRef File) {
|
||||
SmallString<128> Path;
|
||||
if (Dir.startswith("="))
|
||||
sys::path::append(Path, Config->Sysroot, Dir.substr(1), File);
|
||||
|
@ -92,7 +92,9 @@ typename ObjectFile<ELFT>::Elf_Sym_Range ObjectFile<ELFT>::getLocalSymbols() {
|
||||
}
|
||||
|
||||
template <class ELFT> uint32_t ObjectFile<ELFT>::getMipsGp0() const {
|
||||
return MipsReginfo ? MipsReginfo->getGp0() : 0;
|
||||
if (MipsReginfo)
|
||||
return MipsReginfo->Reginfo->ri_gp_value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
@ -132,13 +134,13 @@ StringRef ObjectFile<ELFT>::getShtGroupSignature(const Elf_Shdr &Sec) {
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
ArrayRef<typename ObjectFile<ELFT>::GroupEntryType>
|
||||
ArrayRef<typename ObjectFile<ELFT>::uint32_X>
|
||||
ObjectFile<ELFT>::getShtGroupEntries(const Elf_Shdr &Sec) {
|
||||
const ELFFile<ELFT> &Obj = this->ELFObj;
|
||||
ErrorOr<ArrayRef<GroupEntryType>> EntriesOrErr =
|
||||
Obj.template getSectionContentsAsArray<GroupEntryType>(&Sec);
|
||||
ErrorOr<ArrayRef<uint32_X>> EntriesOrErr =
|
||||
Obj.template getSectionContentsAsArray<uint32_X>(&Sec);
|
||||
error(EntriesOrErr);
|
||||
ArrayRef<GroupEntryType> Entries = *EntriesOrErr;
|
||||
ArrayRef<uint32_X> Entries = *EntriesOrErr;
|
||||
if (Entries.empty() || Entries[0] != GRP_COMDAT)
|
||||
error("Unsupported SHT_GROUP format");
|
||||
return Entries.slice(1);
|
||||
@ -187,8 +189,7 @@ void ObjectFile<ELFT>::initializeSections(DenseSet<StringRef> &ComdatGroups) {
|
||||
Sections[I] = &InputSection<ELFT>::Discarded;
|
||||
if (ComdatGroups.insert(getShtGroupSignature(Sec)).second)
|
||||
continue;
|
||||
for (GroupEntryType E : getShtGroupEntries(Sec)) {
|
||||
uint32_t SecIndex = E;
|
||||
for (uint32_t SecIndex : getShtGroupEntries(Sec)) {
|
||||
if (SecIndex >= Size)
|
||||
error("Invalid section index in group");
|
||||
Sections[SecIndex] = &InputSection<ELFT>::Discarded;
|
||||
|
@ -91,10 +91,13 @@ template <class ELFT> class ObjectFile : public ELFFileBase<ELFT> {
|
||||
typedef typename llvm::object::ELFFile<ELFT>::Elf_Word Elf_Word;
|
||||
typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
|
||||
|
||||
// uint32 in ELFT's byte order
|
||||
typedef llvm::support::detail::packed_endian_specific_integral<
|
||||
uint32_t, ELFT::TargetEndianness, 2> GroupEntryType;
|
||||
uint32_t, ELFT::TargetEndianness, 2>
|
||||
uint32_X;
|
||||
|
||||
StringRef getShtGroupSignature(const Elf_Shdr &Sec);
|
||||
ArrayRef<GroupEntryType> getShtGroupEntries(const Elf_Shdr &Sec);
|
||||
ArrayRef<uint32_X> getShtGroupEntries(const Elf_Shdr &Sec);
|
||||
|
||||
public:
|
||||
static bool classof(const InputFile *F) {
|
||||
|
@ -52,7 +52,9 @@ InputSectionBase<ELFT>::getOffset(uintX_t Offset) {
|
||||
case Merge:
|
||||
return cast<MergeInputSection<ELFT>>(this)->getOffset(Offset);
|
||||
case MipsReginfo:
|
||||
return cast<MipsReginfoInputSection<ELFT>>(this)->getOffset(Offset);
|
||||
// MIPS .reginfo sections are consumed by the linker,
|
||||
// so it should never be copied to output.
|
||||
llvm_unreachable("MIPS .reginfo reached writeTo().");
|
||||
}
|
||||
llvm_unreachable("Invalid section kind");
|
||||
}
|
||||
@ -209,7 +211,6 @@ void InputSectionBase<ELFT>::relocate(uint8_t *Buf, uint8_t *BufEnd,
|
||||
uintX_t SymVA = getSymVA<ELFT>(*Body);
|
||||
if (Target->relocNeedsPlt(Type, *Body)) {
|
||||
SymVA = Out<ELFT>::Plt->getEntryAddr(*Body);
|
||||
Type = Target->getPltRefReloc(Type);
|
||||
} else if (Target->relocNeedsGot(Type, *Body)) {
|
||||
SymVA = Out<ELFT>::Got->getEntryAddr(*Body);
|
||||
if (Body->isTls())
|
||||
@ -217,8 +218,13 @@ void InputSectionBase<ELFT>::relocate(uint8_t *Buf, uint8_t *BufEnd,
|
||||
} else if (!Target->needsCopyRel(Type, *Body) &&
|
||||
isa<SharedSymbol<ELFT>>(*Body)) {
|
||||
continue;
|
||||
} else if (Target->isTlsDynReloc(Type, *Body) ||
|
||||
Target->isSizeDynReloc(Type, *Body)) {
|
||||
} else if (Target->isTlsDynReloc(Type, *Body)) {
|
||||
continue;
|
||||
} else if (Target->isSizeReloc(Type) && canBePreempted(Body, false)) {
|
||||
// A SIZE relocation is supposed to set a symbol size, but if a symbol
|
||||
// can be preempted, the size at runtime may be different than link time.
|
||||
// If that's the case, we leave the field alone rather than filling it
|
||||
// with a possibly incorrect value.
|
||||
continue;
|
||||
} else if (Config->EMachine == EM_MIPS) {
|
||||
if (Type == R_MIPS_HI16 && Body == Config->MipsGpDisp)
|
||||
@ -346,22 +352,13 @@ MergeInputSection<ELFT>::getOffset(uintX_t Offset) {
|
||||
|
||||
template <class ELFT>
|
||||
MipsReginfoInputSection<ELFT>::MipsReginfoInputSection(ObjectFile<ELFT> *F,
|
||||
const Elf_Shdr *Header)
|
||||
: InputSectionBase<ELFT>(F, Header, InputSectionBase<ELFT>::MipsReginfo) {}
|
||||
|
||||
template <class ELFT>
|
||||
uint32_t MipsReginfoInputSection<ELFT>::getGeneralMask() const {
|
||||
const Elf_Shdr *Hdr)
|
||||
: InputSectionBase<ELFT>(F, Hdr, InputSectionBase<ELFT>::MipsReginfo) {
|
||||
// Initialize this->Reginfo.
|
||||
ArrayRef<uint8_t> D = this->getSectionData();
|
||||
if (D.size() != sizeof(Elf_Mips_RegInfo))
|
||||
if (D.size() != sizeof(Elf_Mips_RegInfo<ELFT>))
|
||||
error("Invalid size of .reginfo section");
|
||||
return reinterpret_cast<const Elf_Mips_RegInfo *>(D.data())->ri_gprmask;
|
||||
}
|
||||
|
||||
template <class ELFT> uint32_t MipsReginfoInputSection<ELFT>::getGp0() const {
|
||||
ArrayRef<uint8_t> D = this->getSectionData();
|
||||
if (D.size() != sizeof(Elf_Mips_RegInfo))
|
||||
error("Invalid size of .reginfo section");
|
||||
return reinterpret_cast<const Elf_Mips_RegInfo *>(D.data())->ri_gp_value;
|
||||
Reginfo = reinterpret_cast<const Elf_Mips_RegInfo<ELFT> *>(D.data());
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
|
@ -177,16 +177,13 @@ public:
|
||||
// ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
|
||||
template <class ELFT>
|
||||
class MipsReginfoInputSection : public InputSectionBase<ELFT> {
|
||||
typedef llvm::object::Elf_Mips_RegInfo<ELFT> Elf_Mips_RegInfo;
|
||||
typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
|
||||
|
||||
public:
|
||||
MipsReginfoInputSection(ObjectFile<ELFT> *F, const Elf_Shdr *Header);
|
||||
|
||||
uint32_t getGeneralMask() const;
|
||||
uint32_t getGp0() const;
|
||||
|
||||
MipsReginfoInputSection(ObjectFile<ELFT> *F, const Elf_Shdr *Hdr);
|
||||
static bool classof(const InputSectionBase<ELFT> *S);
|
||||
|
||||
const llvm::object::Elf_Mips_RegInfo<ELFT> *Reginfo;
|
||||
};
|
||||
|
||||
} // namespace elf2
|
||||
|
@ -312,7 +312,7 @@ static bool isUnderSysroot(StringRef Path) {
|
||||
}
|
||||
|
||||
// Entry point. The other functions or classes are private to this file.
|
||||
void lld::elf2::readLinkerScript(BumpPtrAllocator *A, MemoryBufferRef MB) {
|
||||
void elf2::readLinkerScript(BumpPtrAllocator *A, MemoryBufferRef MB) {
|
||||
StringRef Path = MB.getBufferIdentifier();
|
||||
LinkerScript(A, MB.getBuffer(), isUnderSysroot(Path)).run();
|
||||
}
|
||||
|
@ -79,7 +79,7 @@ template <class ELFT> static bool isReserved(InputSectionBase<ELFT> *Sec) {
|
||||
// This is the main function of the garbage collector.
|
||||
// Starting from GC-root sections, this function visits all reachable
|
||||
// sections to set their "Live" bits.
|
||||
template <class ELFT> void lld::elf2::markLive(SymbolTable<ELFT> *Symtab) {
|
||||
template <class ELFT> void elf2::markLive(SymbolTable<ELFT> *Symtab) {
|
||||
SmallVector<InputSection<ELFT> *, 256> Q;
|
||||
|
||||
auto Enqueue = [&](InputSectionBase<ELFT> *Sec) {
|
||||
@ -116,8 +116,7 @@ template <class ELFT> void lld::elf2::markLive(SymbolTable<ELFT> *Symtab) {
|
||||
// Preserve special sections.
|
||||
for (const std::unique_ptr<ObjectFile<ELFT>> &F : Symtab->getObjectFiles())
|
||||
for (InputSectionBase<ELFT> *Sec : F->getSections())
|
||||
if (Sec && Sec != &InputSection<ELFT>::Discarded)
|
||||
if (isReserved(Sec))
|
||||
if (Sec && Sec != &InputSection<ELFT>::Discarded && isReserved(Sec))
|
||||
Enqueue(Sec);
|
||||
|
||||
// Mark all reachable sections.
|
||||
@ -125,7 +124,7 @@ template <class ELFT> void lld::elf2::markLive(SymbolTable<ELFT> *Symtab) {
|
||||
forEachSuccessor<ELFT>(Q.pop_back_val(), Enqueue);
|
||||
}
|
||||
|
||||
template void lld::elf2::markLive<ELF32LE>(SymbolTable<ELF32LE> *);
|
||||
template void lld::elf2::markLive<ELF32BE>(SymbolTable<ELF32BE> *);
|
||||
template void lld::elf2::markLive<ELF64LE>(SymbolTable<ELF64LE> *);
|
||||
template void lld::elf2::markLive<ELF64BE>(SymbolTable<ELF64BE> *);
|
||||
template void elf2::markLive<ELF32LE>(SymbolTable<ELF32LE> *);
|
||||
template void elf2::markLive<ELF32BE>(SymbolTable<ELF32BE> *);
|
||||
template void elf2::markLive<ELF64LE>(SymbolTable<ELF64LE> *);
|
||||
template void elf2::markLive<ELF64BE>(SymbolTable<ELF64BE> *);
|
||||
|
@ -109,6 +109,9 @@ def verbose : Flag<["--"], "verbose">;
|
||||
def whole_archive : Flag<["--", "-"], "whole-archive">,
|
||||
HelpText<"Force load of all members in a static library">;
|
||||
|
||||
def wrap : Separate<["--", "-"], "wrap">, MetaVarName<"<symbol>">,
|
||||
HelpText<"Use wrapper functions for symbol">;
|
||||
|
||||
def z : JoinedOrSeparate<["-"], "z">, MetaVarName<"<option>">,
|
||||
HelpText<"Linker option extensions">;
|
||||
|
||||
@ -136,6 +139,7 @@ def alias_soname_soname : Separate<["-"], "soname">, Alias<soname>;
|
||||
def alias_script_T : Separate<["-"], "T">, Alias<script>;
|
||||
def alias_strip_all: Flag<["-"], "s">, Alias<strip_all>;
|
||||
def alias_undefined_u : Separate<["-"], "u">, Alias<undefined>;
|
||||
def alias_wrap_wrap : Joined<["--", "-"], "wrap=">, Alias<wrap>;
|
||||
|
||||
// Our symbol resolution algorithm handles symbols in archive files differently
|
||||
// than traditional linkers, so we don't need --start-group and --end-group.
|
||||
|
@ -21,21 +21,20 @@ using namespace llvm::ELF;
|
||||
using namespace lld;
|
||||
using namespace lld::elf2;
|
||||
|
||||
bool lld::elf2::HasGotOffRel = false;
|
||||
bool elf2::HasGotOffRel = false;
|
||||
|
||||
template <class ELFT>
|
||||
OutputSectionBase<ELFT>::OutputSectionBase(StringRef Name, uint32_t sh_type,
|
||||
uintX_t sh_flags)
|
||||
OutputSectionBase<ELFT>::OutputSectionBase(StringRef Name, uint32_t Type,
|
||||
uintX_t Flags)
|
||||
: Name(Name) {
|
||||
memset(&Header, 0, sizeof(Elf_Shdr));
|
||||
Header.sh_type = sh_type;
|
||||
Header.sh_flags = sh_flags;
|
||||
Header.sh_type = Type;
|
||||
Header.sh_flags = Flags;
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
GotPltSection<ELFT>::GotPltSection()
|
||||
: OutputSectionBase<ELFT>(".got.plt", llvm::ELF::SHT_PROGBITS,
|
||||
llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE) {
|
||||
: OutputSectionBase<ELFT>(".got.plt", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE) {
|
||||
this->Header.sh_addralign = sizeof(uintX_t);
|
||||
}
|
||||
|
||||
@ -70,10 +69,9 @@ template <class ELFT> void GotPltSection<ELFT>::writeTo(uint8_t *Buf) {
|
||||
|
||||
template <class ELFT>
|
||||
GotSection<ELFT>::GotSection()
|
||||
: OutputSectionBase<ELFT>(".got", llvm::ELF::SHT_PROGBITS,
|
||||
llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE) {
|
||||
: OutputSectionBase<ELFT>(".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE) {
|
||||
if (Config->EMachine == EM_MIPS)
|
||||
this->Header.sh_flags |= llvm::ELF::SHF_MIPS_GPREL;
|
||||
this->Header.sh_flags |= SHF_MIPS_GPREL;
|
||||
this->Header.sh_addralign = sizeof(uintX_t);
|
||||
}
|
||||
|
||||
@ -120,7 +118,7 @@ const SymbolBody *GotSection<ELFT>::getMipsFirstGlobalEntry() const {
|
||||
|
||||
template <class ELFT>
|
||||
unsigned GotSection<ELFT>::getMipsLocalEntriesNum() const {
|
||||
// TODO: Update when the suppoort of GOT entries for local symbols is added.
|
||||
// TODO: Update when the support of GOT entries for local symbols is added.
|
||||
return Target->getGotHeaderEntriesNum();
|
||||
}
|
||||
|
||||
@ -151,8 +149,7 @@ template <class ELFT> void GotSection<ELFT>::writeTo(uint8_t *Buf) {
|
||||
|
||||
template <class ELFT>
|
||||
PltSection<ELFT>::PltSection()
|
||||
: OutputSectionBase<ELFT>(".plt", llvm::ELF::SHT_PROGBITS,
|
||||
llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR) {
|
||||
: OutputSectionBase<ELFT>(".plt", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR) {
|
||||
this->Header.sh_addralign = 16;
|
||||
}
|
||||
|
||||
@ -199,9 +196,7 @@ template <class ELFT> void PltSection<ELFT>::finalize() {
|
||||
|
||||
template <class ELFT>
|
||||
RelocationSection<ELFT>::RelocationSection(StringRef Name, bool IsRela)
|
||||
: OutputSectionBase<ELFT>(Name,
|
||||
IsRela ? llvm::ELF::SHT_RELA : llvm::ELF::SHT_REL,
|
||||
llvm::ELF::SHF_ALLOC),
|
||||
: OutputSectionBase<ELFT>(Name, IsRela ? SHT_RELA : SHT_REL, SHF_ALLOC),
|
||||
IsRela(IsRela) {
|
||||
this->Header.sh_entsize = IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel);
|
||||
this->Header.sh_addralign = ELFT::Is64Bits ? 8 : 4;
|
||||
@ -328,15 +323,14 @@ template <class ELFT> void RelocationSection<ELFT>::finalize() {
|
||||
|
||||
template <class ELFT>
|
||||
InterpSection<ELFT>::InterpSection()
|
||||
: OutputSectionBase<ELFT>(".interp", llvm::ELF::SHT_PROGBITS,
|
||||
llvm::ELF::SHF_ALLOC) {
|
||||
: OutputSectionBase<ELFT>(".interp", SHT_PROGBITS, SHF_ALLOC) {
|
||||
this->Header.sh_size = Config->DynamicLinker.size() + 1;
|
||||
this->Header.sh_addralign = 1;
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
void OutputSectionBase<ELFT>::writeHeaderTo(Elf_Shdr *SHdr) {
|
||||
Header.sh_name = Out<ELFT>::ShStrTab->getOffset(Name);
|
||||
Header.sh_name = Out<ELFT>::ShStrTab->addString(Name);
|
||||
*SHdr = Header;
|
||||
}
|
||||
|
||||
@ -346,8 +340,7 @@ template <class ELFT> void InterpSection<ELFT>::writeTo(uint8_t *Buf) {
|
||||
|
||||
template <class ELFT>
|
||||
HashTableSection<ELFT>::HashTableSection()
|
||||
: OutputSectionBase<ELFT>(".hash", llvm::ELF::SHT_HASH,
|
||||
llvm::ELF::SHF_ALLOC) {
|
||||
: OutputSectionBase<ELFT>(".hash", SHT_HASH, SHF_ALLOC) {
|
||||
this->Header.sh_entsize = sizeof(Elf_Word);
|
||||
this->Header.sh_addralign = sizeof(Elf_Word);
|
||||
}
|
||||
@ -404,8 +397,7 @@ static uint32_t hashGnu(StringRef Name) {
|
||||
|
||||
template <class ELFT>
|
||||
GnuHashTableSection<ELFT>::GnuHashTableSection()
|
||||
: OutputSectionBase<ELFT>(".gnu.hash", llvm::ELF::SHT_GNU_HASH,
|
||||
llvm::ELF::SHF_ALLOC) {
|
||||
: OutputSectionBase<ELFT>(".gnu.hash", SHT_GNU_HASH, SHF_ALLOC) {
|
||||
this->Header.sh_entsize = ELFT::Is64Bits ? 0 : 4;
|
||||
this->Header.sh_addralign = ELFT::Is64Bits ? 8 : 4;
|
||||
}
|
||||
@ -545,8 +537,7 @@ void GnuHashTableSection<ELFT>::addSymbols(std::vector<SymbolBody *> &Symbols) {
|
||||
|
||||
template <class ELFT>
|
||||
DynamicSection<ELFT>::DynamicSection(SymbolTable<ELFT> &SymTab)
|
||||
: OutputSectionBase<ELFT>(".dynamic", llvm::ELF::SHT_DYNAMIC,
|
||||
llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE),
|
||||
: OutputSectionBase<ELFT>(".dynamic", SHT_DYNAMIC, SHF_ALLOC | SHF_WRITE),
|
||||
SymTab(SymTab) {
|
||||
Elf_Shdr &Header = this->Header;
|
||||
Header.sh_addralign = ELFT::Is64Bits ? 8 : 4;
|
||||
@ -556,7 +547,7 @@ DynamicSection<ELFT>::DynamicSection(SymbolTable<ELFT> &SymTab)
|
||||
// See "Special Section" in Chapter 4 in the following document:
|
||||
// ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
|
||||
if (Config->EMachine == EM_MIPS)
|
||||
Header.sh_flags = llvm::ELF::SHF_ALLOC;
|
||||
Header.sh_flags = SHF_ALLOC;
|
||||
}
|
||||
|
||||
template <class ELFT> void DynamicSection<ELFT>::finalize() {
|
||||
@ -590,12 +581,12 @@ template <class ELFT> void DynamicSection<ELFT>::finalize() {
|
||||
|
||||
if (!Config->RPath.empty()) {
|
||||
++NumEntries; // DT_RUNPATH / DT_RPATH
|
||||
Out<ELFT>::DynStrTab->add(Config->RPath);
|
||||
Out<ELFT>::DynStrTab->reserve(Config->RPath);
|
||||
}
|
||||
|
||||
if (!Config->SoName.empty()) {
|
||||
++NumEntries; // DT_SONAME
|
||||
Out<ELFT>::DynStrTab->add(Config->SoName);
|
||||
Out<ELFT>::DynStrTab->reserve(Config->SoName);
|
||||
}
|
||||
|
||||
if (PreInitArraySec)
|
||||
@ -608,7 +599,7 @@ template <class ELFT> void DynamicSection<ELFT>::finalize() {
|
||||
for (const std::unique_ptr<SharedFile<ELFT>> &F : SymTab.getSharedFiles()) {
|
||||
if (!F->isNeeded())
|
||||
continue;
|
||||
Out<ELFT>::DynStrTab->add(F->getSoName());
|
||||
Out<ELFT>::DynStrTab->reserve(F->getSoName());
|
||||
++NumEntries;
|
||||
}
|
||||
|
||||
@ -696,7 +687,7 @@ template <class ELFT> void DynamicSection<ELFT>::writeTo(uint8_t *Buf) {
|
||||
WritePtr(DT_SYMTAB, Out<ELFT>::DynSymTab->getVA());
|
||||
WritePtr(DT_SYMENT, sizeof(Elf_Sym));
|
||||
WritePtr(DT_STRTAB, Out<ELFT>::DynStrTab->getVA());
|
||||
WriteVal(DT_STRSZ, Out<ELFT>::DynStrTab->data().size());
|
||||
WriteVal(DT_STRSZ, Out<ELFT>::DynStrTab->getSize());
|
||||
if (Out<ELFT>::GnuHashTab)
|
||||
WritePtr(DT_GNU_HASH, Out<ELFT>::GnuHashTab->getVA());
|
||||
if (Out<ELFT>::HashTab)
|
||||
@ -712,10 +703,10 @@ template <class ELFT> void DynamicSection<ELFT>::writeTo(uint8_t *Buf) {
|
||||
// DT_RPATH is used for indirect dependencies as well.
|
||||
if (!Config->RPath.empty())
|
||||
WriteVal(Config->EnableNewDtags ? DT_RUNPATH : DT_RPATH,
|
||||
Out<ELFT>::DynStrTab->getOffset(Config->RPath));
|
||||
Out<ELFT>::DynStrTab->addString(Config->RPath));
|
||||
|
||||
if (!Config->SoName.empty())
|
||||
WriteVal(DT_SONAME, Out<ELFT>::DynStrTab->getOffset(Config->SoName));
|
||||
WriteVal(DT_SONAME, Out<ELFT>::DynStrTab->addString(Config->SoName));
|
||||
|
||||
auto WriteArray = [&](int32_t T1, int32_t T2,
|
||||
const OutputSectionBase<ELFT> *Sec) {
|
||||
@ -730,7 +721,7 @@ template <class ELFT> void DynamicSection<ELFT>::writeTo(uint8_t *Buf) {
|
||||
|
||||
for (const std::unique_ptr<SharedFile<ELFT>> &F : SymTab.getSharedFiles())
|
||||
if (F->isNeeded())
|
||||
WriteVal(DT_NEEDED, Out<ELFT>::DynStrTab->getOffset(F->getSoName()));
|
||||
WriteVal(DT_NEEDED, Out<ELFT>::DynStrTab->addString(F->getSoName()));
|
||||
|
||||
if (InitSym)
|
||||
WritePtr(DT_INIT, getSymVA<ELFT>(*InitSym));
|
||||
@ -765,9 +756,9 @@ template <class ELFT> void DynamicSection<ELFT>::writeTo(uint8_t *Buf) {
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
OutputSection<ELFT>::OutputSection(StringRef Name, uint32_t sh_type,
|
||||
uintX_t sh_flags)
|
||||
: OutputSectionBase<ELFT>(Name, sh_type, sh_flags) {}
|
||||
OutputSection<ELFT>::OutputSection(StringRef Name, uint32_t Type,
|
||||
uintX_t Flags)
|
||||
: OutputSectionBase<ELFT>(Name, Type, Flags) {}
|
||||
|
||||
template <class ELFT>
|
||||
void OutputSection<ELFT>::addSection(InputSectionBase<ELFT> *C) {
|
||||
@ -779,14 +770,14 @@ void OutputSection<ELFT>::addSection(InputSectionBase<ELFT> *C) {
|
||||
this->Header.sh_addralign = Align;
|
||||
|
||||
uintX_t Off = this->Header.sh_size;
|
||||
Off = RoundUpToAlignment(Off, Align);
|
||||
Off = align(Off, Align);
|
||||
S->OutSecOff = Off;
|
||||
Off += S->getSize();
|
||||
this->Header.sh_size = Off;
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
typename ELFFile<ELFT>::uintX_t lld::elf2::getSymVA(const SymbolBody &S) {
|
||||
typename ELFFile<ELFT>::uintX_t elf2::getSymVA(const SymbolBody &S) {
|
||||
switch (S.kind()) {
|
||||
case SymbolBody::DefinedSyntheticKind: {
|
||||
auto &D = cast<DefinedSynthetic<ELFT>>(S);
|
||||
@ -797,6 +788,11 @@ typename ELFFile<ELFT>::uintX_t lld::elf2::getSymVA(const SymbolBody &S) {
|
||||
InputSectionBase<ELFT> *SC = DR.Section;
|
||||
if (!SC)
|
||||
return DR.Sym.st_value;
|
||||
|
||||
// Symbol offsets for AMDGPU need to be the offset in bytes of the symbol
|
||||
// from the beginning of the section.
|
||||
if (Config->EMachine == EM_AMDGPU)
|
||||
return SC->getOffset(DR.Sym);
|
||||
if (DR.Sym.getType() == STT_TLS)
|
||||
return SC->OutSec->getVA() + SC->getOffset(DR.Sym) -
|
||||
Out<ELFT>::TlsPhdr->p_vaddr;
|
||||
@ -824,7 +820,7 @@ typename ELFFile<ELFT>::uintX_t lld::elf2::getSymVA(const SymbolBody &S) {
|
||||
// For non-local symbols, use getSymVA instead.
|
||||
template <class ELFT, bool IsRela>
|
||||
typename ELFFile<ELFT>::uintX_t
|
||||
lld::elf2::getLocalRelTarget(const ObjectFile<ELFT> &File,
|
||||
elf2::getLocalRelTarget(const ObjectFile<ELFT> &File,
|
||||
const Elf_Rel_Impl<ELFT, IsRela> &RI,
|
||||
typename ELFFile<ELFT>::uintX_t Addend) {
|
||||
typedef typename ELFFile<ELFT>::Elf_Sym Elf_Sym;
|
||||
@ -868,7 +864,7 @@ lld::elf2::getLocalRelTarget(const ObjectFile<ELFT> &File,
|
||||
|
||||
// Returns true if a symbol can be replaced at load-time by a symbol
|
||||
// with the same name defined in other ELF executable or DSO.
|
||||
bool lld::elf2::canBePreempted(const SymbolBody *Body, bool NeedsGot) {
|
||||
bool elf2::canBePreempted(const SymbolBody *Body, bool NeedsGot) {
|
||||
if (!Body)
|
||||
return false; // Body is a local symbol.
|
||||
if (Body->isShared())
|
||||
@ -910,9 +906,9 @@ template <class ELFT> void OutputSection<ELFT>::writeTo(uint8_t *Buf) {
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
EHOutputSection<ELFT>::EHOutputSection(StringRef Name, uint32_t sh_type,
|
||||
uintX_t sh_flags)
|
||||
: OutputSectionBase<ELFT>(Name, sh_type, sh_flags) {}
|
||||
EHOutputSection<ELFT>::EHOutputSection(StringRef Name, uint32_t Type,
|
||||
uintX_t Flags)
|
||||
: OutputSectionBase<ELFT>(Name, Type, Flags) {}
|
||||
|
||||
template <class ELFT>
|
||||
EHRegion<ELFT>::EHRegion(EHInputSection<ELFT> *S, unsigned Index)
|
||||
@ -980,7 +976,7 @@ void EHOutputSection<ELFT>::addSectionAux(
|
||||
auto P = CieMap.insert(std::make_pair(CieInfo, Cies.size()));
|
||||
if (P.second) {
|
||||
Cies.push_back(C);
|
||||
this->Header.sh_size += RoundUpToAlignment(Length, sizeof(uintX_t));
|
||||
this->Header.sh_size += align(Length, sizeof(uintX_t));
|
||||
}
|
||||
OffsetToIndex[Offset] = P.first->second;
|
||||
} else {
|
||||
@ -993,7 +989,7 @@ void EHOutputSection<ELFT>::addSectionAux(
|
||||
if (I == OffsetToIndex.end())
|
||||
error("Invalid CIE reference");
|
||||
Cies[I->second].Fdes.push_back(EHRegion<ELFT>(S, Index));
|
||||
this->Header.sh_size += RoundUpToAlignment(Length, sizeof(uintX_t));
|
||||
this->Header.sh_size += align(Length, sizeof(uintX_t));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1046,7 +1042,7 @@ static typename ELFFile<ELFT>::uintX_t writeAlignedCieOrFde(StringRef Data,
|
||||
uint8_t *Buf) {
|
||||
typedef typename ELFFile<ELFT>::uintX_t uintX_t;
|
||||
const endianness E = ELFT::TargetEndianness;
|
||||
uint64_t Len = RoundUpToAlignment(Data.size(), sizeof(uintX_t));
|
||||
uint64_t Len = align(Data.size(), sizeof(uintX_t));
|
||||
write32<E>(Buf, Len - 4);
|
||||
memcpy(Buf + 4, Data.data() + 4, Data.size() - 4);
|
||||
return Len;
|
||||
@ -1083,9 +1079,9 @@ template <class ELFT> void EHOutputSection<ELFT>::writeTo(uint8_t *Buf) {
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
MergeOutputSection<ELFT>::MergeOutputSection(StringRef Name, uint32_t sh_type,
|
||||
uintX_t sh_flags)
|
||||
: OutputSectionBase<ELFT>(Name, sh_type, sh_flags) {}
|
||||
MergeOutputSection<ELFT>::MergeOutputSection(StringRef Name, uint32_t Type,
|
||||
uintX_t Flags)
|
||||
: OutputSectionBase<ELFT>(Name, Type, Flags) {}
|
||||
|
||||
template <class ELFT> void MergeOutputSection<ELFT>::writeTo(uint8_t *Buf) {
|
||||
if (shouldTailMerge()) {
|
||||
@ -1165,20 +1161,49 @@ template <class ELFT> void MergeOutputSection<ELFT>::finalize() {
|
||||
|
||||
template <class ELFT>
|
||||
StringTableSection<ELFT>::StringTableSection(StringRef Name, bool Dynamic)
|
||||
: OutputSectionBase<ELFT>(Name, llvm::ELF::SHT_STRTAB,
|
||||
Dynamic ? (uintX_t)llvm::ELF::SHF_ALLOC : 0),
|
||||
: OutputSectionBase<ELFT>(Name, SHT_STRTAB,
|
||||
Dynamic ? (uintX_t)SHF_ALLOC : 0),
|
||||
Dynamic(Dynamic) {
|
||||
this->Header.sh_addralign = 1;
|
||||
}
|
||||
|
||||
// String tables are created in two phases. First you call reserve()
|
||||
// to reserve room in the string table, and then call addString() to actually
|
||||
// add that string.
|
||||
//
|
||||
// Why two phases? We want to know the size of the string table as early as
|
||||
// possible to fix file layout. So we have separated finalize(), which
|
||||
// determines the size of the section, from writeTo(), which writes the section
|
||||
// contents to the output buffer. If we merge reserve() with addString(),
|
||||
// we need a plumbing work for finalize() and writeTo() so that offsets
|
||||
// we obtained in the former function can be written in the latter.
|
||||
// This design eliminated that need.
|
||||
template <class ELFT> void StringTableSection<ELFT>::reserve(StringRef S) {
|
||||
Reserved += S.size() + 1; // +1 for NUL
|
||||
}
|
||||
|
||||
// Adds a string to the string table. You must call reserve() with the
|
||||
// same string before calling addString().
|
||||
template <class ELFT> size_t StringTableSection<ELFT>::addString(StringRef S) {
|
||||
size_t Pos = Used;
|
||||
Strings.push_back(S);
|
||||
Used += S.size() + 1;
|
||||
Reserved -= S.size() + 1;
|
||||
assert((int64_t)Reserved >= 0);
|
||||
return Pos;
|
||||
}
|
||||
|
||||
template <class ELFT> void StringTableSection<ELFT>::writeTo(uint8_t *Buf) {
|
||||
StringRef Data = StrTabBuilder.data();
|
||||
memcpy(Buf, Data.data(), Data.size());
|
||||
// ELF string tables start with NUL byte, so advance the pointer by one.
|
||||
++Buf;
|
||||
for (StringRef S : Strings) {
|
||||
memcpy(Buf, S.data(), S.size());
|
||||
Buf += S.size() + 1;
|
||||
}
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
bool lld::elf2::shouldKeepInSymtab(const ObjectFile<ELFT> &File,
|
||||
StringRef SymName,
|
||||
bool elf2::shouldKeepInSymtab(const ObjectFile<ELFT> &File, StringRef SymName,
|
||||
const typename ELFFile<ELFT>::Elf_Sym &Sym) {
|
||||
if (Sym.getType() == STT_SECTION)
|
||||
return false;
|
||||
@ -1208,16 +1233,12 @@ bool lld::elf2::shouldKeepInSymtab(const ObjectFile<ELFT> &File,
|
||||
template <class ELFT>
|
||||
SymbolTableSection<ELFT>::SymbolTableSection(
|
||||
SymbolTable<ELFT> &Table, StringTableSection<ELFT> &StrTabSec)
|
||||
: OutputSectionBase<ELFT>(
|
||||
StrTabSec.isDynamic() ? ".dynsym" : ".symtab",
|
||||
StrTabSec.isDynamic() ? llvm::ELF::SHT_DYNSYM : llvm::ELF::SHT_SYMTAB,
|
||||
StrTabSec.isDynamic() ? (uintX_t)llvm::ELF::SHF_ALLOC : 0),
|
||||
: OutputSectionBase<ELFT>(StrTabSec.isDynamic() ? ".dynsym" : ".symtab",
|
||||
StrTabSec.isDynamic() ? SHT_DYNSYM : SHT_SYMTAB,
|
||||
StrTabSec.isDynamic() ? (uintX_t)SHF_ALLOC : 0),
|
||||
Table(Table), StrTabSec(StrTabSec) {
|
||||
typedef OutputSectionBase<ELFT> Base;
|
||||
typename Base::Elf_Shdr &Header = this->Header;
|
||||
|
||||
Header.sh_entsize = sizeof(Elf_Sym);
|
||||
Header.sh_addralign = ELFT::Is64Bits ? 8 : 4;
|
||||
this->Header.sh_entsize = sizeof(Elf_Sym);
|
||||
this->Header.sh_addralign = ELFT::Is64Bits ? 8 : 4;
|
||||
}
|
||||
|
||||
// Orders symbols according to their positions in the GOT,
|
||||
@ -1259,14 +1280,14 @@ template <class ELFT> void SymbolTableSection<ELFT>::finalize() {
|
||||
|
||||
template <class ELFT>
|
||||
void SymbolTableSection<ELFT>::addLocalSymbol(StringRef Name) {
|
||||
StrTabSec.add(Name);
|
||||
StrTabSec.reserve(Name);
|
||||
++NumVisible;
|
||||
++NumLocals;
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
void SymbolTableSection<ELFT>::addSymbol(SymbolBody *Body) {
|
||||
StrTabSec.add(Body->getName());
|
||||
StrTabSec.reserve(Body->getName());
|
||||
Symbols.push_back(Body);
|
||||
++NumVisible;
|
||||
}
|
||||
@ -1306,9 +1327,13 @@ void SymbolTableSection<ELFT>::writeLocalSymbols(uint8_t *&Buf) {
|
||||
continue;
|
||||
const OutputSectionBase<ELFT> *OutSec = Section->OutSec;
|
||||
ESym->st_shndx = OutSec->SectionIndex;
|
||||
VA += OutSec->getVA() + Section->getOffset(Sym);
|
||||
VA = Section->getOffset(Sym);
|
||||
// Symbol offsets for AMDGPU need to be the offset in bytes of the
|
||||
// symbol from the beginning of the section.
|
||||
if (Config->EMachine != EM_AMDGPU)
|
||||
VA += OutSec->getVA();
|
||||
}
|
||||
ESym->st_name = StrTabSec.getOffset(SymName);
|
||||
ESym->st_name = StrTabSec.addString(SymName);
|
||||
ESym->st_size = Sym.st_size;
|
||||
ESym->setBindingAndType(Sym.getBinding(), Sym.getType());
|
||||
ESym->st_value = VA;
|
||||
@ -1363,7 +1388,7 @@ void SymbolTableSection<ELFT>::writeGlobalSymbols(uint8_t *Buf) {
|
||||
}
|
||||
|
||||
StringRef Name = Body->getName();
|
||||
ESym->st_name = StrTabSec.getOffset(Name);
|
||||
ESym->st_name = StrTabSec.addString(Name);
|
||||
|
||||
unsigned char Type = STT_NOTYPE;
|
||||
uintX_t Size = 0;
|
||||
@ -1413,13 +1438,14 @@ template <class ELFT>
|
||||
void MipsReginfoOutputSection<ELFT>::writeTo(uint8_t *Buf) {
|
||||
auto *R = reinterpret_cast<Elf_Mips_RegInfo *>(Buf);
|
||||
R->ri_gp_value = getMipsGpAddr<ELFT>();
|
||||
R->ri_gprmask = GeneralMask;
|
||||
R->ri_gprmask = GprMask;
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
void MipsReginfoOutputSection<ELFT>::addSection(InputSectionBase<ELFT> *C) {
|
||||
// Copy input object file's .reginfo gprmask to output.
|
||||
auto *S = cast<MipsReginfoInputSection<ELFT>>(C);
|
||||
GeneralMask |= S->getGeneralMask();
|
||||
GprMask |= S->Reginfo->ri_gprmask;
|
||||
}
|
||||
|
||||
namespace lld {
|
||||
|
@ -329,21 +329,18 @@ class StringTableSection final : public OutputSectionBase<ELFT> {
|
||||
public:
|
||||
typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
|
||||
StringTableSection(StringRef Name, bool Dynamic);
|
||||
void add(StringRef S) { StrTabBuilder.add(S); }
|
||||
size_t getOffset(StringRef S) const { return StrTabBuilder.getOffset(S); }
|
||||
StringRef data() const { return StrTabBuilder.data(); }
|
||||
void reserve(StringRef S);
|
||||
size_t addString(StringRef S);
|
||||
void writeTo(uint8_t *Buf) override;
|
||||
|
||||
void finalize() override {
|
||||
StrTabBuilder.finalize();
|
||||
this->Header.sh_size = StrTabBuilder.data().size();
|
||||
}
|
||||
|
||||
size_t getSize() const { return Used + Reserved; }
|
||||
void finalize() override { this->Header.sh_size = getSize(); }
|
||||
bool isDynamic() const { return Dynamic; }
|
||||
|
||||
private:
|
||||
const bool Dynamic;
|
||||
llvm::StringTableBuilder StrTabBuilder{llvm::StringTableBuilder::ELF};
|
||||
std::vector<StringRef> Strings;
|
||||
size_t Used = 1; // ELF string tables start with a NUL byte, so 1.
|
||||
size_t Reserved = 0;
|
||||
};
|
||||
|
||||
template <class ELFT>
|
||||
@ -429,9 +426,13 @@ public:
|
||||
void addSection(InputSectionBase<ELFT> *S) override;
|
||||
|
||||
private:
|
||||
uint32_t GeneralMask = 0;
|
||||
uint32_t GprMask = 0;
|
||||
};
|
||||
|
||||
inline uint64_t align(uint64_t Value, uint64_t Align) {
|
||||
return llvm::RoundUpToAlignment(Value, Align);
|
||||
}
|
||||
|
||||
// All output sections that are hadnled by the linker specially are
|
||||
// globally accessible. Writer initializes them, so don't use them
|
||||
// until Writer is initialized.
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "Config.h"
|
||||
#include "Error.h"
|
||||
#include "Symbols.h"
|
||||
#include "llvm/Support/StringSaver.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::object;
|
||||
@ -26,8 +27,6 @@ using namespace llvm::ELF;
|
||||
using namespace lld;
|
||||
using namespace lld::elf2;
|
||||
|
||||
template <class ELFT> SymbolTable<ELFT>::SymbolTable() {}
|
||||
|
||||
// All input object files must be for the same architecture
|
||||
// (e.g. it does not make sense to link x86 object files with
|
||||
// MIPS object files.) This function checks for that error.
|
||||
@ -64,7 +63,7 @@ void SymbolTable<ELFT>::addFile(std::unique_ptr<InputFile> File) {
|
||||
if (auto *F = dyn_cast<SharedFile<ELFT>>(FileP)) {
|
||||
// DSOs are uniquified not by filename but by soname.
|
||||
F->parseSoName();
|
||||
if (!IncludedSoNames.insert(F->getSoName()).second)
|
||||
if (!SoNames.insert(F->getSoName()).second)
|
||||
return;
|
||||
|
||||
SharedFiles.emplace_back(cast<SharedFile<ELFT>>(File.release()));
|
||||
@ -100,17 +99,20 @@ SymbolBody *SymbolTable<ELFT>::addUndefinedOpt(StringRef Name) {
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
void SymbolTable<ELFT>::addAbsolute(StringRef Name,
|
||||
typename ELFFile<ELFT>::Elf_Sym &ESym) {
|
||||
resolve(new (Alloc) DefinedRegular<ELFT>(Name, ESym, nullptr));
|
||||
SymbolBody *SymbolTable<ELFT>::addAbsolute(StringRef Name, Elf_Sym &ESym) {
|
||||
// Pass nullptr because absolute symbols have no corresponding input sections.
|
||||
auto *Sym = new (Alloc) DefinedRegular<ELFT>(Name, ESym, nullptr);
|
||||
resolve(Sym);
|
||||
return Sym;
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
void SymbolTable<ELFT>::addSynthetic(StringRef Name,
|
||||
SymbolBody *SymbolTable<ELFT>::addSynthetic(StringRef Name,
|
||||
OutputSectionBase<ELFT> &Section,
|
||||
typename ELFFile<ELFT>::uintX_t Value) {
|
||||
uintX_t Value) {
|
||||
auto *Sym = new (Alloc) DefinedSynthetic<ELFT>(Name, Value, Section);
|
||||
resolve(Sym);
|
||||
return Sym;
|
||||
}
|
||||
|
||||
// Add Name as an "ignored" symbol. An ignored symbol is a regular
|
||||
@ -118,10 +120,27 @@ void SymbolTable<ELFT>::addSynthetic(StringRef Name,
|
||||
// file's symbol table. Such symbols are useful for some linker-defined symbols.
|
||||
template <class ELFT>
|
||||
SymbolBody *SymbolTable<ELFT>::addIgnored(StringRef Name) {
|
||||
auto *Sym = new (Alloc)
|
||||
DefinedRegular<ELFT>(Name, ElfSym<ELFT>::IgnoreUndef, nullptr);
|
||||
resolve(Sym);
|
||||
return Sym;
|
||||
return addAbsolute(Name, ElfSym<ELFT>::IgnoredWeak);
|
||||
}
|
||||
|
||||
// The 'strong' variant of the addIgnored. Adds symbol which has a global
|
||||
// binding and cannot be substituted.
|
||||
template <class ELFT>
|
||||
SymbolBody *SymbolTable<ELFT>::addIgnoredStrong(StringRef Name) {
|
||||
return addAbsolute(Name, ElfSym<ELFT>::Ignored);
|
||||
}
|
||||
|
||||
// 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) {
|
||||
if (Symtab.count(Name) == 0)
|
||||
return;
|
||||
StringSaver Saver(Alloc);
|
||||
Symbol *Sym = addUndefined(Name)->getSymbol();
|
||||
Symbol *Real = addUndefined(Saver.save("__real_" + Name))->getSymbol();
|
||||
Symbol *Wrap = addUndefined(Saver.save("__wrap_" + Name))->getSymbol();
|
||||
Real->Body = Sym->Body;
|
||||
Sym->Body = Wrap->Body;
|
||||
}
|
||||
|
||||
// Returns a file from which symbol B was created.
|
||||
@ -136,6 +155,8 @@ ELFFileBase<ELFT> *SymbolTable<ELFT>::findFile(SymbolBody *B) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Construct a string in the form of "Sym in File1 and File2".
|
||||
// Used to construct an error message.
|
||||
template <class ELFT>
|
||||
std::string SymbolTable<ELFT>::conflictMsg(SymbolBody *Old, SymbolBody *New) {
|
||||
ELFFileBase<ELFT> *OldFile = findFile(Old);
|
||||
@ -184,8 +205,8 @@ template <class ELFT> void SymbolTable<ELFT>::resolve(SymbolBody *New) {
|
||||
Sym->Body = New;
|
||||
}
|
||||
|
||||
// Find an existing symbol or create and insert a new one.
|
||||
template <class ELFT> Symbol *SymbolTable<ELFT>::insert(SymbolBody *New) {
|
||||
// Find an existing Symbol or create and insert a new one.
|
||||
StringRef Name = New->getName();
|
||||
Symbol *&Sym = Symtab[Name];
|
||||
if (!Sym)
|
||||
|
@ -31,9 +31,10 @@ class Undefined;
|
||||
// undefined, it'll read an archive member to read a real definition
|
||||
// to replace the lazy symbol. The logic is implemented in resolve().
|
||||
template <class ELFT> class SymbolTable {
|
||||
public:
|
||||
SymbolTable();
|
||||
typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
|
||||
typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
|
||||
|
||||
public:
|
||||
void addFile(std::unique_ptr<InputFile> File);
|
||||
|
||||
const llvm::MapVector<StringRef, Symbol *> &getSymbols() const {
|
||||
@ -50,13 +51,15 @@ public:
|
||||
|
||||
SymbolBody *addUndefined(StringRef Name);
|
||||
SymbolBody *addUndefinedOpt(StringRef Name);
|
||||
void addAbsolute(StringRef Name,
|
||||
typename llvm::object::ELFFile<ELFT>::Elf_Sym &ESym);
|
||||
void addSynthetic(StringRef Name, OutputSectionBase<ELFT> &Section,
|
||||
typename llvm::object::ELFFile<ELFT>::uintX_t Value);
|
||||
SymbolBody *addAbsolute(StringRef Name, Elf_Sym &ESym);
|
||||
SymbolBody *addSynthetic(StringRef Name, OutputSectionBase<ELFT> &Section,
|
||||
uintX_t Value);
|
||||
SymbolBody *addIgnored(StringRef Name);
|
||||
SymbolBody *addIgnoredStrong(StringRef Name);
|
||||
|
||||
void scanShlibUndefined();
|
||||
SymbolBody *find(StringRef Name);
|
||||
void wrap(StringRef Name);
|
||||
ELFFileBase<ELFT> *findFile(SymbolBody *B);
|
||||
|
||||
private:
|
||||
@ -66,8 +69,6 @@ private:
|
||||
void resolve(SymbolBody *Body);
|
||||
std::string conflictMsg(SymbolBody *Old, SymbolBody *New);
|
||||
|
||||
std::vector<std::unique_ptr<ArchiveFile>> ArchiveFiles;
|
||||
|
||||
// The order the global symbols are in is not defined. We can use an arbitrary
|
||||
// order, but it has to be reproducible. That is true even when cross linking.
|
||||
// The default hashing of StringRef produces different results on 32 and 64
|
||||
@ -78,13 +79,18 @@ private:
|
||||
llvm::MapVector<StringRef, Symbol *> Symtab;
|
||||
llvm::BumpPtrAllocator Alloc;
|
||||
|
||||
// Comdat groups define "link once" sections. If two comdat groups have the
|
||||
// same name, only one of them is linked, and the other is ignored. This set
|
||||
// is used to uniquify them.
|
||||
llvm::DenseSet<StringRef> ComdatGroups;
|
||||
|
||||
// The writer needs to infer the machine type from the object files.
|
||||
// The symbol table owns all file objects.
|
||||
std::vector<std::unique_ptr<ArchiveFile>> ArchiveFiles;
|
||||
std::vector<std::unique_ptr<ObjectFile<ELFT>>> ObjectFiles;
|
||||
|
||||
std::vector<std::unique_ptr<SharedFile<ELFT>>> SharedFiles;
|
||||
llvm::DenseSet<StringRef> IncludedSoNames;
|
||||
|
||||
// Set of .so files to not link the same shared object file more than once.
|
||||
llvm::DenseSet<StringRef> SoNames;
|
||||
};
|
||||
|
||||
} // namespace elf2
|
||||
|
@ -120,11 +120,13 @@ std::unique_ptr<InputFile> Lazy::getMember() {
|
||||
|
||||
template <class ELFT> static void doInitSymbols() {
|
||||
ElfSym<ELFT>::End.setBinding(STB_GLOBAL);
|
||||
ElfSym<ELFT>::IgnoreUndef.setBinding(STB_WEAK);
|
||||
ElfSym<ELFT>::IgnoreUndef.setVisibility(STV_HIDDEN);
|
||||
ElfSym<ELFT>::IgnoredWeak.setBinding(STB_WEAK);
|
||||
ElfSym<ELFT>::IgnoredWeak.setVisibility(STV_HIDDEN);
|
||||
ElfSym<ELFT>::Ignored.setBinding(STB_GLOBAL);
|
||||
ElfSym<ELFT>::Ignored.setVisibility(STV_HIDDEN);
|
||||
}
|
||||
|
||||
void lld::elf2::initSymbols() {
|
||||
void elf2::initSymbols() {
|
||||
doInitSymbols<ELF32LE>();
|
||||
doInitSymbols<ELF32BE>();
|
||||
doInitSymbols<ELF64LE>();
|
||||
@ -136,12 +138,12 @@ template int SymbolBody::compare<ELF32BE>(SymbolBody *Other);
|
||||
template int SymbolBody::compare<ELF64LE>(SymbolBody *Other);
|
||||
template int SymbolBody::compare<ELF64BE>(SymbolBody *Other);
|
||||
|
||||
template class lld::elf2::UndefinedElf<ELF32LE>;
|
||||
template class lld::elf2::UndefinedElf<ELF32BE>;
|
||||
template class lld::elf2::UndefinedElf<ELF64LE>;
|
||||
template class lld::elf2::UndefinedElf<ELF64BE>;
|
||||
template class elf2::UndefinedElf<ELF32LE>;
|
||||
template class elf2::UndefinedElf<ELF32BE>;
|
||||
template class elf2::UndefinedElf<ELF64LE>;
|
||||
template class elf2::UndefinedElf<ELF64BE>;
|
||||
|
||||
template class lld::elf2::DefinedSynthetic<ELF32LE>;
|
||||
template class lld::elf2::DefinedSynthetic<ELF32BE>;
|
||||
template class lld::elf2::DefinedSynthetic<ELF64LE>;
|
||||
template class lld::elf2::DefinedSynthetic<ELF64BE>;
|
||||
template class elf2::DefinedSynthetic<ELF32LE>;
|
||||
template class elf2::DefinedSynthetic<ELF32BE>;
|
||||
template class elf2::DefinedSynthetic<ELF64LE>;
|
||||
template class elf2::DefinedSynthetic<ELF64BE>;
|
||||
|
@ -105,6 +105,7 @@ public:
|
||||
// you can access P->Backref->Body to get the resolver's result.
|
||||
void setBackref(Symbol *P) { Backref = P; }
|
||||
SymbolBody *repl() { return Backref ? Backref->Body : this; }
|
||||
Symbol *getSymbol() { return Backref; }
|
||||
|
||||
// Decides which symbol should "win" in the symbol table, this or
|
||||
// the Other. Returns 1 if this wins, -1 if the Other wins, or 0 if
|
||||
@ -299,8 +300,11 @@ template <class ELFT> struct ElfSym {
|
||||
typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
|
||||
|
||||
// Used to represent an undefined symbol which we don't want
|
||||
// to add to the output file's symbol table.
|
||||
static Elf_Sym IgnoreUndef;
|
||||
// to add to the output file's symbol table. The `IgnoredWeak`
|
||||
// has weak binding and can be substituted. The `Ignore` has
|
||||
// global binding and gets priority over symbols from shared libs.
|
||||
static Elf_Sym IgnoredWeak;
|
||||
static Elf_Sym Ignored;
|
||||
|
||||
// The content for _end and end symbols.
|
||||
static Elf_Sym End;
|
||||
@ -314,7 +318,8 @@ template <class ELFT> struct ElfSym {
|
||||
static Elf_Sym RelaIpltEnd;
|
||||
};
|
||||
|
||||
template <class ELFT> typename ElfSym<ELFT>::Elf_Sym ElfSym<ELFT>::IgnoreUndef;
|
||||
template <class ELFT> typename ElfSym<ELFT>::Elf_Sym ElfSym<ELFT>::IgnoredWeak;
|
||||
template <class ELFT> typename ElfSym<ELFT>::Elf_Sym ElfSym<ELFT>::Ignored;
|
||||
template <class ELFT> typename ElfSym<ELFT>::Elf_Sym ElfSym<ELFT>::End;
|
||||
template <class ELFT> typename ElfSym<ELFT>::Elf_Sym ElfSym<ELFT>::MipsGp;
|
||||
template <class ELFT>
|
||||
|
178
ELF/Target.cpp
178
ELF/Target.cpp
@ -122,7 +122,6 @@ private:
|
||||
class X86_64TargetInfo final : public TargetInfo {
|
||||
public:
|
||||
X86_64TargetInfo();
|
||||
unsigned getPltRefReloc(unsigned Type) const override;
|
||||
bool isTlsDynReloc(unsigned Type, const SymbolBody &S) const override;
|
||||
void writeGotPltHeaderEntries(uint8_t *Buf) const override;
|
||||
void writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const override;
|
||||
@ -139,7 +138,7 @@ public:
|
||||
uint8_t *PairedLoc = nullptr) const override;
|
||||
bool isRelRelative(uint32_t Type) const override;
|
||||
bool isTlsOptimized(unsigned Type, const SymbolBody *S) const override;
|
||||
bool isSizeDynReloc(uint32_t Type, const SymbolBody &S) const override;
|
||||
bool isSizeReloc(uint32_t Type) const override;
|
||||
unsigned relocateTlsOptimize(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
|
||||
uint64_t P, uint64_t SA,
|
||||
const SymbolBody &S) const override;
|
||||
@ -155,6 +154,23 @@ private:
|
||||
uint64_t SA) const;
|
||||
};
|
||||
|
||||
class PPCTargetInfo final : public TargetInfo {
|
||||
public:
|
||||
PPCTargetInfo();
|
||||
void writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const override;
|
||||
void writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
|
||||
uint64_t PltEntryAddr) const override;
|
||||
void writePltEntry(uint8_t *Buf, uint64_t GotAddr, uint64_t GotEntryAddr,
|
||||
uint64_t PltEntryAddr, int32_t Index,
|
||||
unsigned RelOff) const override;
|
||||
bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
|
||||
bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
|
||||
void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P,
|
||||
uint64_t SA, uint64_t ZA = 0,
|
||||
uint8_t *PairedLoc = nullptr) const override;
|
||||
bool isRelRelative(uint32_t Type) const override;
|
||||
};
|
||||
|
||||
class PPC64TargetInfo final : public TargetInfo {
|
||||
public:
|
||||
PPC64TargetInfo();
|
||||
@ -176,13 +192,14 @@ class AArch64TargetInfo final : public TargetInfo {
|
||||
public:
|
||||
AArch64TargetInfo();
|
||||
unsigned getDynReloc(unsigned Type) const override;
|
||||
unsigned getPltRefReloc(unsigned Type) const override;
|
||||
void writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const override;
|
||||
void writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
|
||||
uint64_t PltEntryAddr) const override;
|
||||
void writePltEntry(uint8_t *Buf, uint64_t GotAddr, uint64_t GotEntryAddr,
|
||||
uint64_t PltEntryAddr, int32_t Index,
|
||||
unsigned RelOff) const override;
|
||||
unsigned getTlsGotReloc(unsigned Type = -1) const override;
|
||||
bool isTlsDynReloc(unsigned Type, const SymbolBody &S) const override;
|
||||
bool needsCopyRel(uint32_t Type, const SymbolBody &S) const override;
|
||||
bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
|
||||
bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
|
||||
@ -191,6 +208,22 @@ public:
|
||||
uint8_t *PairedLoc = nullptr) const override;
|
||||
};
|
||||
|
||||
class AMDGPUTargetInfo final : public TargetInfo {
|
||||
public:
|
||||
AMDGPUTargetInfo();
|
||||
void writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const override;
|
||||
void writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
|
||||
uint64_t PltEntryAddr) const override;
|
||||
void writePltEntry(uint8_t *Buf, uint64_t GotAddr, uint64_t GotEntryAddr,
|
||||
uint64_t PltEntryAddr, int32_t Index,
|
||||
unsigned RelOff) const override;
|
||||
bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
|
||||
bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
|
||||
void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P,
|
||||
uint64_t SA, uint64_t ZA = 0,
|
||||
uint8_t *PairedLoc = nullptr) const override;
|
||||
};
|
||||
|
||||
template <class ELFT> class MipsTargetInfo final : public TargetInfo {
|
||||
public:
|
||||
MipsTargetInfo();
|
||||
@ -216,6 +249,8 @@ TargetInfo *createTarget() {
|
||||
return new X86TargetInfo();
|
||||
case EM_AARCH64:
|
||||
return new AArch64TargetInfo();
|
||||
case EM_AMDGPU:
|
||||
return new AMDGPUTargetInfo();
|
||||
case EM_MIPS:
|
||||
switch (Config->EKind) {
|
||||
case ELF32LEKind:
|
||||
@ -225,6 +260,8 @@ TargetInfo *createTarget() {
|
||||
default:
|
||||
error("Unsupported MIPS target");
|
||||
}
|
||||
case EM_PPC:
|
||||
return new PPCTargetInfo();
|
||||
case EM_PPC64:
|
||||
return new PPC64TargetInfo();
|
||||
case EM_X86_64:
|
||||
@ -247,13 +284,9 @@ bool TargetInfo::needsCopyRel(uint32_t Type, const SymbolBody &S) const {
|
||||
|
||||
bool TargetInfo::isGotRelative(uint32_t Type) const { return false; }
|
||||
|
||||
unsigned TargetInfo::getPltRefReloc(unsigned Type) const { return PCRelReloc; }
|
||||
|
||||
bool TargetInfo::isRelRelative(uint32_t Type) const { return true; }
|
||||
|
||||
bool TargetInfo::isSizeDynReloc(uint32_t Type, const SymbolBody &S) const {
|
||||
return false;
|
||||
}
|
||||
bool TargetInfo::isSizeReloc(uint32_t Type) const { return false; }
|
||||
|
||||
unsigned TargetInfo::relocateTlsOptimize(uint8_t *Loc, uint8_t *BufEnd,
|
||||
uint32_t Type, uint64_t P, uint64_t SA,
|
||||
@ -639,12 +672,6 @@ bool X86_64TargetInfo::isTlsDynReloc(unsigned Type, const SymbolBody &S) const {
|
||||
return Type == R_X86_64_GOTTPOFF || Type == R_X86_64_TLSGD;
|
||||
}
|
||||
|
||||
unsigned X86_64TargetInfo::getPltRefReloc(unsigned Type) const {
|
||||
if (Type == R_X86_64_PLT32)
|
||||
return R_X86_64_PC32;
|
||||
return Type;
|
||||
}
|
||||
|
||||
bool X86_64TargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody &S) const {
|
||||
if (needsCopyRel(Type, S))
|
||||
return false;
|
||||
@ -698,16 +725,12 @@ bool X86_64TargetInfo::isRelRelative(uint32_t Type) const {
|
||||
case R_X86_64_PC32:
|
||||
case R_X86_64_PC64:
|
||||
case R_X86_64_PLT32:
|
||||
case R_X86_64_SIZE32:
|
||||
case R_X86_64_SIZE64:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool X86_64TargetInfo::isSizeDynReloc(uint32_t Type,
|
||||
const SymbolBody &S) const {
|
||||
return (Type == R_X86_64_SIZE32 || Type == R_X86_64_SIZE64) &&
|
||||
canBePreempted(&S, false);
|
||||
bool X86_64TargetInfo::isSizeReloc(uint32_t Type) const {
|
||||
return Type == R_X86_64_SIZE32 || Type == R_X86_64_SIZE64;
|
||||
}
|
||||
|
||||
bool X86_64TargetInfo::isTlsOptimized(unsigned Type,
|
||||
@ -909,6 +932,37 @@ static uint16_t applyPPCHighera(uint64_t V) { return (V + 0x8000) >> 32; }
|
||||
static uint16_t applyPPCHighest(uint64_t V) { return V >> 48; }
|
||||
static uint16_t applyPPCHighesta(uint64_t V) { return (V + 0x8000) >> 48; }
|
||||
|
||||
PPCTargetInfo::PPCTargetInfo() {}
|
||||
void PPCTargetInfo::writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const {}
|
||||
void PPCTargetInfo::writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
|
||||
uint64_t PltEntryAddr) const {}
|
||||
void PPCTargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotAddr,
|
||||
uint64_t GotEntryAddr,
|
||||
uint64_t PltEntryAddr, int32_t Index,
|
||||
unsigned RelOff) const {}
|
||||
bool PPCTargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody &S) const {
|
||||
return false;
|
||||
}
|
||||
bool PPCTargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody &S) const {
|
||||
return false;
|
||||
}
|
||||
bool PPCTargetInfo::isRelRelative(uint32_t Type) const { return false; }
|
||||
|
||||
void PPCTargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
|
||||
uint64_t P, uint64_t SA, uint64_t ZA,
|
||||
uint8_t *PairedLoc) const {
|
||||
switch (Type) {
|
||||
case R_PPC_ADDR16_HA:
|
||||
write16be(Loc, applyPPCHa(SA));
|
||||
break;
|
||||
case R_PPC_ADDR16_LO:
|
||||
write16be(Loc, applyPPCLo(SA));
|
||||
break;
|
||||
default:
|
||||
error("unrecognized reloc " + Twine(Type));
|
||||
}
|
||||
}
|
||||
|
||||
PPC64TargetInfo::PPC64TargetInfo() {
|
||||
PCRelReloc = R_PPC64_REL24;
|
||||
GotReloc = R_PPC64_GLOB_DAT;
|
||||
@ -1124,8 +1178,10 @@ void PPC64TargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
|
||||
|
||||
AArch64TargetInfo::AArch64TargetInfo() {
|
||||
CopyReloc = R_AARCH64_COPY;
|
||||
IRelativeReloc = R_AARCH64_IRELATIVE;
|
||||
GotReloc = R_AARCH64_GLOB_DAT;
|
||||
PltReloc = R_AARCH64_JUMP_SLOT;
|
||||
TlsGotReloc = R_AARCH64_TLS_TPREL64;
|
||||
LazyRelocations = true;
|
||||
PltEntrySize = 16;
|
||||
PltZeroEntrySize = 32;
|
||||
@ -1139,8 +1195,6 @@ unsigned AArch64TargetInfo::getDynReloc(unsigned Type) const {
|
||||
"recompile with -fPIC.");
|
||||
}
|
||||
|
||||
unsigned AArch64TargetInfo::getPltRefReloc(unsigned Type) const { return Type; }
|
||||
|
||||
void AArch64TargetInfo::writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const {
|
||||
write64le(Buf, Out<ELF64LE>::Plt->getVA());
|
||||
}
|
||||
@ -1187,6 +1241,19 @@ void AArch64TargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotAddr,
|
||||
GotEntryAddr);
|
||||
}
|
||||
|
||||
unsigned AArch64TargetInfo::getTlsGotReloc(unsigned Type) const {
|
||||
if (Type == R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 ||
|
||||
Type == R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC)
|
||||
return Type;
|
||||
return TlsGotReloc;
|
||||
}
|
||||
|
||||
bool AArch64TargetInfo::isTlsDynReloc(unsigned Type,
|
||||
const SymbolBody &S) const {
|
||||
return Type == R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 ||
|
||||
Type == R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC;
|
||||
}
|
||||
|
||||
bool AArch64TargetInfo::needsCopyRel(uint32_t Type, const SymbolBody &S) const {
|
||||
if (Config->Shared)
|
||||
return false;
|
||||
@ -1210,17 +1277,28 @@ bool AArch64TargetInfo::needsCopyRel(uint32_t Type, const SymbolBody &S) const {
|
||||
|
||||
bool AArch64TargetInfo::relocNeedsGot(uint32_t Type,
|
||||
const SymbolBody &S) const {
|
||||
return Type == R_AARCH64_ADR_GOT_PAGE || Type == R_AARCH64_LD64_GOT_LO12_NC ||
|
||||
relocNeedsPlt(Type, S);
|
||||
switch (Type) {
|
||||
case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
|
||||
case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
|
||||
case R_AARCH64_ADR_GOT_PAGE:
|
||||
case R_AARCH64_LD64_GOT_LO12_NC:
|
||||
return true;
|
||||
default:
|
||||
return relocNeedsPlt(Type, S);
|
||||
}
|
||||
}
|
||||
|
||||
bool AArch64TargetInfo::relocNeedsPlt(uint32_t Type,
|
||||
const SymbolBody &S) const {
|
||||
if (isGnuIFunc<ELF64LE>(S))
|
||||
return true;
|
||||
switch (Type) {
|
||||
default:
|
||||
return false;
|
||||
case R_AARCH64_CALL26:
|
||||
case R_AARCH64_CONDBR19:
|
||||
case R_AARCH64_JUMP26:
|
||||
case R_AARCH64_TSTBR14:
|
||||
return canBePreempted(&S, true);
|
||||
}
|
||||
}
|
||||
@ -1273,7 +1351,8 @@ void AArch64TargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd,
|
||||
updateAArch64Adr(Loc, X & 0x1FFFFF);
|
||||
break;
|
||||
}
|
||||
case R_AARCH64_ADR_PREL_PG_HI21: {
|
||||
case R_AARCH64_ADR_PREL_PG_HI21:
|
||||
case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: {
|
||||
uint64_t X = getAArch64Page(SA) - getAArch64Page(P);
|
||||
checkInt<33>(X, Type);
|
||||
updateAArch64Adr(Loc, (X >> 12) & 0x1FFFFF); // X[32:12]
|
||||
@ -1286,7 +1365,14 @@ void AArch64TargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd,
|
||||
or32le(Loc, (X & 0x0FFFFFFC) >> 2);
|
||||
break;
|
||||
}
|
||||
case R_AARCH64_CONDBR19: {
|
||||
uint64_t X = SA - P;
|
||||
checkInt<21>(X, Type);
|
||||
or32le(Loc, (X & 0x1FFFFC) << 3);
|
||||
break;
|
||||
}
|
||||
case R_AARCH64_LD64_GOT_LO12_NC:
|
||||
case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
|
||||
checkAlignment<8>(SA, Type);
|
||||
or32le(Loc, (SA & 0xFF8) << 7);
|
||||
break;
|
||||
@ -1310,11 +1396,53 @@ void AArch64TargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd,
|
||||
case R_AARCH64_PREL64:
|
||||
write64le(Loc, SA - P);
|
||||
break;
|
||||
case R_AARCH64_TSTBR14: {
|
||||
uint64_t X = SA - P;
|
||||
checkInt<16>(X, Type);
|
||||
or32le(Loc, (X & 0xFFFC) << 3);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
error("unrecognized reloc " + Twine(Type));
|
||||
}
|
||||
}
|
||||
|
||||
AMDGPUTargetInfo::AMDGPUTargetInfo() {}
|
||||
|
||||
void AMDGPUTargetInfo::writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const {
|
||||
llvm_unreachable("not implemented");
|
||||
}
|
||||
|
||||
void AMDGPUTargetInfo::writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
|
||||
uint64_t PltEntryAddr) const {
|
||||
llvm_unreachable("not implemented");
|
||||
}
|
||||
|
||||
void AMDGPUTargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotAddr,
|
||||
uint64_t GotEntryAddr,
|
||||
uint64_t PltEntryAddr, int32_t Index,
|
||||
unsigned RelOff) const {
|
||||
llvm_unreachable("not implemented");
|
||||
}
|
||||
|
||||
bool AMDGPUTargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody &S) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AMDGPUTargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody &S) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Implementing relocations for AMDGPU is low priority since most
|
||||
// programs don't use relocations now. Thus, this function is not
|
||||
// actually called (relocateOne is called for each relocation).
|
||||
// That's why the AMDGPU port works without implementing this function.
|
||||
void AMDGPUTargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
|
||||
uint64_t P, uint64_t SA, uint64_t ZA,
|
||||
uint8_t *PairedLoc) const {
|
||||
llvm_unreachable("not implemented");
|
||||
}
|
||||
|
||||
template <class ELFT> MipsTargetInfo<ELFT>::MipsTargetInfo() {
|
||||
PageSize = 65536;
|
||||
GotHeaderEntriesNum = 2;
|
||||
|
10
ELF/Target.h
10
ELF/Target.h
@ -45,7 +45,6 @@ public:
|
||||
virtual bool isTlsDynReloc(unsigned Type, const SymbolBody &S) const {
|
||||
return false;
|
||||
}
|
||||
virtual unsigned getPltRefReloc(unsigned Type) const;
|
||||
virtual unsigned getTlsGotReloc(unsigned Type = -1) const {
|
||||
return TlsGotReloc;
|
||||
}
|
||||
@ -57,8 +56,15 @@ public:
|
||||
virtual void writePltEntry(uint8_t *Buf, uint64_t GotAddr,
|
||||
uint64_t GotEntryAddr, uint64_t PltEntryAddr,
|
||||
int32_t Index, unsigned RelOff) const = 0;
|
||||
|
||||
// Returns true if a relocation is relative to the place being relocated,
|
||||
// such as relocations used for PC-relative instructions. Such relocations
|
||||
// need not be fixed up if an image is loaded to a different address than
|
||||
// the link-time address. So we don't have to emit a relocation for the
|
||||
// dynamic linker if isRelRelative returns true.
|
||||
virtual bool isRelRelative(uint32_t Type) const;
|
||||
virtual bool isSizeDynReloc(uint32_t Type, const SymbolBody &S) const;
|
||||
|
||||
virtual bool isSizeReloc(uint32_t Type) const;
|
||||
virtual bool relocNeedsDynRelative(unsigned Type) const { return false; }
|
||||
virtual bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const = 0;
|
||||
virtual bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const = 0;
|
||||
|
112
ELF/Writer.cpp
112
ELF/Writer.cpp
@ -98,12 +98,9 @@ private:
|
||||
};
|
||||
} // anonymous namespace
|
||||
|
||||
template <class ELFT> static bool shouldUseRela() {
|
||||
ELFKind K = cast<ELFFileBase<ELFT>>(Config->FirstElf)->getELFKind();
|
||||
return K == ELF64LEKind || K == ELF64BEKind;
|
||||
}
|
||||
template <class ELFT> static bool shouldUseRela() { return ELFT::Is64Bits; }
|
||||
|
||||
template <class ELFT> void lld::elf2::writeResult(SymbolTable<ELFT> *Symtab) {
|
||||
template <class ELFT> void elf2::writeResult(SymbolTable<ELFT> *Symtab) {
|
||||
// Initialize output sections that are handled by Writer specially.
|
||||
// Don't reorder because the order of initialization matters.
|
||||
InterpSection<ELFT> Interp;
|
||||
@ -290,7 +287,8 @@ void Writer<ELFT>::scanRelocs(
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Config->EMachine == EM_MIPS && NeedsGot) {
|
||||
if (Config->EMachine == EM_MIPS) {
|
||||
if (NeedsGot) {
|
||||
// MIPS ABI has special rules to process GOT entries
|
||||
// and doesn't require relocation entries for them.
|
||||
// See "Global Offset Table" in Chapter 5 in the following document
|
||||
@ -299,9 +297,21 @@ void Writer<ELFT>::scanRelocs(
|
||||
Body->setUsedInDynamicReloc();
|
||||
continue;
|
||||
}
|
||||
bool CBP = canBePreempted(Body, NeedsGot);
|
||||
if (!CBP && (!Config->Shared || Target->isRelRelative(Type)))
|
||||
if (Body == Config->MipsGpDisp)
|
||||
// MIPS _gp_disp designates offset between start of function and gp
|
||||
// pointer into GOT therefore any relocations against it do not require
|
||||
// dynamic relocation.
|
||||
continue;
|
||||
}
|
||||
|
||||
// Here we are creating a relocation for the dynamic linker based on
|
||||
// a relocation from an object file, but some relocations need no
|
||||
// load-time fixup. Skip such relocation.
|
||||
bool CBP = canBePreempted(Body, NeedsGot);
|
||||
bool NoDynrel = Target->isRelRelative(Type) || Target->isSizeReloc(Type);
|
||||
if (!CBP && (NoDynrel || !Config->Shared))
|
||||
continue;
|
||||
|
||||
if (CBP)
|
||||
Body->setUsedInDynamicReloc();
|
||||
if (NeedsPlt && Target->supportsLazyRelocations())
|
||||
@ -490,8 +500,7 @@ void Writer<ELFT>::addCommonSymbols(std::vector<DefinedCommon *> &Syms) {
|
||||
|
||||
uintX_t Off = getBss()->getSize();
|
||||
for (DefinedCommon *C : Syms) {
|
||||
uintX_t Align = C->MaxAlignment;
|
||||
Off = RoundUpToAlignment(Off, Align);
|
||||
Off = align(Off, C->MaxAlignment);
|
||||
C->OffsetInBss = Off;
|
||||
Off += C->Size;
|
||||
}
|
||||
@ -514,7 +523,7 @@ void Writer<ELFT>::addCopyRelSymbols(std::vector<SharedSymbol<ELFT> *> &Syms) {
|
||||
countTrailingZeros((uintX_t)Sym.st_value));
|
||||
uintX_t Align = 1 << TrailingZeros;
|
||||
Out<ELFT>::Bss->updateAlign(Align);
|
||||
Off = RoundUpToAlignment(Off, Align);
|
||||
Off = align(Off, Align);
|
||||
C->OffsetInBss = Off;
|
||||
Off += Sym.st_size;
|
||||
}
|
||||
@ -597,7 +606,8 @@ template <class ELFT> static bool includeInSymtab(const SymbolBody &B) {
|
||||
|
||||
// Don't include synthetic symbols like __init_array_start in every output.
|
||||
if (auto *U = dyn_cast<DefinedRegular<ELFT>>(&B))
|
||||
if (&U->Sym == &ElfSym<ELFT>::IgnoreUndef)
|
||||
if (&U->Sym == &ElfSym<ELFT>::IgnoredWeak ||
|
||||
&U->Sym == &ElfSym<ELFT>::Ignored)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@ -630,8 +640,6 @@ public:
|
||||
private:
|
||||
SectionKey<ELFT::Is64Bits> createKey(InputSectionBase<ELFT> *C,
|
||||
StringRef OutsecName);
|
||||
OutputSectionBase<ELFT> *createAux(InputSectionBase<ELFT> *C,
|
||||
const SectionKey<ELFT::Is64Bits> &Key);
|
||||
|
||||
SmallDenseMap<SectionKey<ELFT::Is64Bits>, OutputSectionBase<ELFT> *> Map;
|
||||
};
|
||||
@ -645,25 +653,22 @@ OutputSectionFactory<ELFT>::create(InputSectionBase<ELFT> *C,
|
||||
OutputSectionBase<ELFT> *&Sec = Map[Key];
|
||||
if (Sec)
|
||||
return {Sec, false};
|
||||
Sec = createAux(C, Key);
|
||||
return {Sec, true};
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
OutputSectionBase<ELFT> *
|
||||
OutputSectionFactory<ELFT>::createAux(InputSectionBase<ELFT> *C,
|
||||
const SectionKey<ELFT::Is64Bits> &Key) {
|
||||
switch (C->SectionKind) {
|
||||
case InputSectionBase<ELFT>::Regular:
|
||||
return new OutputSection<ELFT>(Key.Name, Key.Type, Key.Flags);
|
||||
Sec = new OutputSection<ELFT>(Key.Name, Key.Type, Key.Flags);
|
||||
break;
|
||||
case InputSectionBase<ELFT>::EHFrame:
|
||||
return new EHOutputSection<ELFT>(Key.Name, Key.Type, Key.Flags);
|
||||
Sec = new EHOutputSection<ELFT>(Key.Name, Key.Type, Key.Flags);
|
||||
break;
|
||||
case InputSectionBase<ELFT>::Merge:
|
||||
return new MergeOutputSection<ELFT>(Key.Name, Key.Type, Key.Flags);
|
||||
Sec = new MergeOutputSection<ELFT>(Key.Name, Key.Type, Key.Flags);
|
||||
break;
|
||||
case InputSectionBase<ELFT>::MipsReginfo:
|
||||
return new MipsReginfoOutputSection<ELFT>();
|
||||
Sec = new MipsReginfoOutputSection<ELFT>();
|
||||
break;
|
||||
}
|
||||
llvm_unreachable("Unknown output section type");
|
||||
return {Sec, true};
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
@ -832,7 +837,7 @@ template <class ELFT> void Writer<ELFT>::createSections() {
|
||||
}
|
||||
|
||||
for (OutputSectionBase<ELFT> *Sec : OutputSections)
|
||||
Out<ELFT>::ShStrTab->add(Sec->getName());
|
||||
Out<ELFT>::ShStrTab->reserve(Sec->getName());
|
||||
|
||||
// Finalizers fix each section's size.
|
||||
// .dynamic section's finalizer may add strings to .dynstr,
|
||||
@ -976,6 +981,18 @@ static uint32_t toPhdrFlags(uint64_t Flags) {
|
||||
return Ret;
|
||||
}
|
||||
|
||||
/// For AMDGPU we need to use custom segment kinds in order to specify which
|
||||
/// address space data should be loaded into.
|
||||
template <class ELFT>
|
||||
static uint32_t getAmdgpuPhdr(OutputSectionBase<ELFT> *Sec) {
|
||||
uint32_t Flags = Sec->getFlags();
|
||||
if (Flags & SHF_AMDGPU_HSA_CODE)
|
||||
return PT_AMDGPU_HSA_LOAD_CODE_AGENT;
|
||||
if ((Flags & SHF_AMDGPU_HSA_GLOBAL) && !(Flags & SHF_AMDGPU_HSA_AGENT))
|
||||
return PT_AMDGPU_HSA_LOAD_GLOBAL_PROGRAM;
|
||||
return PT_LOAD;
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
void Writer<ELFT>::updateRelro(Elf_Phdr *Cur, Elf_Phdr *GnuRelroPhdr,
|
||||
uintX_t VA) {
|
||||
@ -1024,8 +1041,8 @@ template <class ELFT> void Writer<ELFT>::assignAddresses() {
|
||||
bool InRelRo = Config->ZRelro && (Flags & PF_W) && isRelroSection(Sec);
|
||||
bool FirstNonRelRo = GnuRelroPhdr.p_type && !InRelRo && !RelroAligned;
|
||||
if (FirstNonRelRo || PH->p_flags != Flags) {
|
||||
VA = RoundUpToAlignment(VA, Target->getPageSize());
|
||||
FileOff = RoundUpToAlignment(FileOff, Target->getPageSize());
|
||||
VA = align(VA, Target->getPageSize());
|
||||
FileOff = align(FileOff, Target->getPageSize());
|
||||
if (FirstNonRelRo)
|
||||
RelroAligned = true;
|
||||
}
|
||||
@ -1033,15 +1050,17 @@ template <class ELFT> void Writer<ELFT>::assignAddresses() {
|
||||
if (PH->p_flags != Flags) {
|
||||
// Flags changed. Create a new PT_LOAD.
|
||||
PH = &Phdrs[++PhdrIdx];
|
||||
setPhdr(PH, PT_LOAD, Flags, FileOff, VA, 0, Target->getPageSize());
|
||||
uint32_t PTType = (Config->EMachine != EM_AMDGPU) ? (uint32_t)PT_LOAD
|
||||
: getAmdgpuPhdr(Sec);
|
||||
setPhdr(PH, PTType, Flags, FileOff, VA, 0, Target->getPageSize());
|
||||
}
|
||||
|
||||
if (Sec->getFlags() & SHF_TLS) {
|
||||
if (!TlsPhdr.p_vaddr)
|
||||
setPhdr(&TlsPhdr, PT_TLS, PF_R, FileOff, VA, 0, Sec->getAlign());
|
||||
if (Sec->getType() != SHT_NOBITS)
|
||||
VA = RoundUpToAlignment(VA, Sec->getAlign());
|
||||
uintX_t TVA = RoundUpToAlignment(VA + ThreadBssOffset, Sec->getAlign());
|
||||
VA = align(VA, Sec->getAlign());
|
||||
uintX_t TVA = align(VA + ThreadBssOffset, Sec->getAlign());
|
||||
Sec->setVA(TVA);
|
||||
TlsPhdr.p_memsz += Sec->getSize();
|
||||
if (Sec->getType() == SHT_NOBITS) {
|
||||
@ -1052,7 +1071,7 @@ template <class ELFT> void Writer<ELFT>::assignAddresses() {
|
||||
}
|
||||
TlsPhdr.p_align = std::max<uintX_t>(TlsPhdr.p_align, Sec->getAlign());
|
||||
} else {
|
||||
VA = RoundUpToAlignment(VA, Sec->getAlign());
|
||||
VA = align(VA, Sec->getAlign());
|
||||
Sec->setVA(VA);
|
||||
VA += Sec->getSize();
|
||||
if (InRelRo)
|
||||
@ -1060,7 +1079,7 @@ template <class ELFT> void Writer<ELFT>::assignAddresses() {
|
||||
}
|
||||
}
|
||||
|
||||
FileOff = RoundUpToAlignment(FileOff, Sec->getAlign());
|
||||
FileOff = align(FileOff, Sec->getAlign());
|
||||
Sec->setFileOffset(FileOff);
|
||||
if (Sec->getType() != SHT_NOBITS)
|
||||
FileOff += Sec->getSize();
|
||||
@ -1073,7 +1092,7 @@ template <class ELFT> void Writer<ELFT>::assignAddresses() {
|
||||
if (TlsPhdr.p_vaddr) {
|
||||
// The TLS pointer goes after PT_TLS. At least glibc will align it,
|
||||
// so round up the size to make sure the offsets are correct.
|
||||
TlsPhdr.p_memsz = RoundUpToAlignment(TlsPhdr.p_memsz, TlsPhdr.p_align);
|
||||
TlsPhdr.p_memsz = align(TlsPhdr.p_memsz, TlsPhdr.p_align);
|
||||
Phdrs[++PhdrIdx] = TlsPhdr;
|
||||
Out<ELFT>::TlsPhdr = &Phdrs[PhdrIdx];
|
||||
}
|
||||
@ -1105,7 +1124,7 @@ template <class ELFT> void Writer<ELFT>::assignAddresses() {
|
||||
}
|
||||
|
||||
// Add space for section headers.
|
||||
SectionHeaderOff = RoundUpToAlignment(FileOff, ELFT::Is64Bits ? 8 : 4);
|
||||
SectionHeaderOff = align(FileOff, ELFT::Is64Bits ? 8 : 4);
|
||||
FileSize = SectionHeaderOff + getNumSections() * sizeof(Elf_Shdr);
|
||||
|
||||
// Update "_end" and "end" symbols so that they
|
||||
@ -1146,7 +1165,7 @@ static uint32_t getELFFlags() {
|
||||
if (Config->EMachine != EM_MIPS)
|
||||
return 0;
|
||||
// FIXME: In fact ELF flags depends on ELF flags of input object files
|
||||
// and selected emulation. For now just use hadr coded values.
|
||||
// and selected emulation. For now just use hard coded values.
|
||||
uint32_t V = EF_MIPS_ABI_O32 | EF_MIPS_CPIC | EF_MIPS_ARCH_32R2;
|
||||
if (Config->Shared)
|
||||
V |= EF_MIPS_PIC;
|
||||
@ -1238,8 +1257,17 @@ template <class ELFT> void Writer<ELFT>::writeSections() {
|
||||
Sec->writeTo(Buf + Sec->getFileOff());
|
||||
}
|
||||
|
||||
// Write all sections but string table sections. We know the sizes of the
|
||||
// string tables already, but they may not have actual strings yet (only
|
||||
// room may be reserved), because writeTo() is allowed to add actual
|
||||
// strings to the string tables.
|
||||
for (OutputSectionBase<ELFT> *Sec : OutputSections)
|
||||
if (Sec != Out<ELFT>::Opd)
|
||||
if (Sec != Out<ELFT>::Opd && Sec->getType() != SHT_STRTAB)
|
||||
Sec->writeTo(Buf + Sec->getFileOff());
|
||||
|
||||
// Write string table sections.
|
||||
for (OutputSectionBase<ELFT> *Sec : OutputSections)
|
||||
if (Sec != Out<ELFT>::Opd && Sec->getType() == SHT_STRTAB)
|
||||
Sec->writeTo(Buf + Sec->getFileOff());
|
||||
}
|
||||
|
||||
@ -1275,7 +1303,7 @@ template <class ELFT> void Writer<ELFT>::buildSectionMap() {
|
||||
InputToOutputSection[Name] = OutSec.first;
|
||||
}
|
||||
|
||||
template void lld::elf2::writeResult<ELF32LE>(SymbolTable<ELF32LE> *Symtab);
|
||||
template void lld::elf2::writeResult<ELF32BE>(SymbolTable<ELF32BE> *Symtab);
|
||||
template void lld::elf2::writeResult<ELF64LE>(SymbolTable<ELF64LE> *Symtab);
|
||||
template void lld::elf2::writeResult<ELF64BE>(SymbolTable<ELF64BE> *Symtab);
|
||||
template void elf2::writeResult<ELF32LE>(SymbolTable<ELF32LE> *Symtab);
|
||||
template void elf2::writeResult<ELF32BE>(SymbolTable<ELF32BE> *Symtab);
|
||||
template void elf2::writeResult<ELF64LE>(SymbolTable<ELF64LE> *Symtab);
|
||||
template void elf2::writeResult<ELF64BE>(SymbolTable<ELF64BE> *Symtab);
|
||||
|
@ -1,5 +1,9 @@
|
||||
add_llvm_library(lldConfig
|
||||
add_lld_library(lldConfig
|
||||
Version.cpp
|
||||
|
||||
ADDITIONAL_HEADER_DIRS
|
||||
${LLD_INCLUDE_DIR}/lld/Config
|
||||
|
||||
LINK_LIBS
|
||||
LLVMSupport
|
||||
)
|
||||
|
@ -1,4 +1,4 @@
|
||||
add_llvm_library(lldCore
|
||||
add_lld_library(lldCore
|
||||
DefinedAtom.cpp
|
||||
Error.cpp
|
||||
File.cpp
|
||||
@ -7,6 +7,10 @@ add_llvm_library(lldCore
|
||||
Resolver.cpp
|
||||
SymbolTable.cpp
|
||||
Writer.cpp
|
||||
|
||||
ADDITIONAL_HEADER_DIRS
|
||||
${LLD_INCLUDE_DIR}/lld/Core
|
||||
|
||||
LINK_LIBS
|
||||
LLVMSupport
|
||||
)
|
||||
|
@ -8,12 +8,16 @@ set(LLVM_TARGET_DEFINITIONS DarwinLdOptions.td)
|
||||
tablegen(LLVM DarwinLdOptions.inc -gen-opt-parser-defs)
|
||||
add_public_tablegen_target(DriverOptionsTableGen)
|
||||
|
||||
add_llvm_library(lldDriver
|
||||
add_lld_library(lldDriver
|
||||
CoreDriver.cpp
|
||||
DarwinLdDriver.cpp
|
||||
Driver.cpp
|
||||
GnuLdDriver.cpp
|
||||
UniversalDriver.cpp
|
||||
|
||||
ADDITIONAL_HEADER_DIRS
|
||||
${LLD_INCLUDE_DIR}/lld/Driver
|
||||
|
||||
LINK_LIBS
|
||||
lldConfig
|
||||
lldMachO
|
||||
@ -21,7 +25,6 @@ add_llvm_library(lldDriver
|
||||
lldELF
|
||||
lldELF2
|
||||
lldAArch64ELFTarget
|
||||
lldAMDGPUELFTarget
|
||||
lldARMELFTarget
|
||||
lldHexagonELFTarget
|
||||
lldMipsELFTarget
|
||||
|
@ -325,7 +325,6 @@ std::unique_ptr<ELFLinkingContext>
|
||||
GnuLdDriver::createELFLinkingContext(llvm::Triple triple) {
|
||||
std::unique_ptr<ELFLinkingContext> p;
|
||||
if ((p = elf::createAArch64LinkingContext(triple))) return p;
|
||||
if ((p = elf::createAMDGPULinkingContext(triple))) return p;
|
||||
if ((p = elf::createARMLinkingContext(triple))) return p;
|
||||
if ((p = elf::createExampleLinkingContext(triple))) return p;
|
||||
if ((p = elf::createHexagonLinkingContext(triple))) return p;
|
||||
|
@ -6,10 +6,14 @@ if (MSVC)
|
||||
add_definitions(-wd4062) # Suppress 'warning C4062: Enumerator has no associated handler in a switch statement.'
|
||||
endif()
|
||||
|
||||
add_llvm_library(lldReaderWriter
|
||||
add_lld_library(lldReaderWriter
|
||||
CoreLinkingContext.cpp
|
||||
FileArchive.cpp
|
||||
LinkerScript.cpp
|
||||
|
||||
ADDITIONAL_HEADER_DIRS
|
||||
${LLD_INCLUDE_DIR}/lld/ReaderWriter
|
||||
|
||||
LINK_LIBS
|
||||
lldCore
|
||||
lldYAML
|
||||
|
@ -1,4 +1,4 @@
|
||||
add_llvm_library(lldAArch64ELFTarget
|
||||
add_lld_library(lldAArch64ELFTarget
|
||||
AArch64LinkingContext.cpp
|
||||
AArch64TargetHandler.cpp
|
||||
AArch64RelocationHandler.cpp
|
||||
|
@ -1,34 +0,0 @@
|
||||
//===- lib/ReaderWriter/ELF/AMDGPU/AMDGPUExecutableWriter.cpp -------------===//
|
||||
//
|
||||
// The LLVM Linker
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "AMDGPUExecutableWriter.h"
|
||||
|
||||
using namespace lld;
|
||||
using namespace lld::elf;
|
||||
|
||||
AMDGPUExecutableWriter::AMDGPUExecutableWriter(AMDGPULinkingContext &ctx,
|
||||
AMDGPUTargetLayout &layout)
|
||||
: ExecutableWriter(ctx, layout), _ctx(ctx) {}
|
||||
|
||||
void AMDGPUExecutableWriter::createImplicitFiles(
|
||||
std::vector<std::unique_ptr<File>> &Result) {
|
||||
// ExecutableWriter::createImplicitFiles() adds C runtime symbols that we
|
||||
// don't need, so we use the OutputELFWriter implementation instead.
|
||||
OutputELFWriter<ELF64LE>::createImplicitFiles(Result);
|
||||
}
|
||||
|
||||
void AMDGPUExecutableWriter::finalizeDefaultAtomValues() {
|
||||
|
||||
// ExecutableWriter::finalizeDefaultAtomValues() assumes the presence of
|
||||
// C runtime symbols. However, since we skip the call to
|
||||
// ExecutableWriter::createImplicitFiles(), these symbols are never added
|
||||
// and ExectuableWriter::finalizeDefaultAtomValues() will crash if we call
|
||||
// it.
|
||||
OutputELFWriter<ELF64LE>::finalizeDefaultAtomValues();
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
//===- lib/ReaderWriter/ELF/AMDGPU/AMDGPUExecutableWriter.h ---------------===//
|
||||
//
|
||||
// The LLVM Linker
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#ifndef AMDGPU_EXECUTABLE_WRITER_H
|
||||
#define AMDGPU_EXECUTABLE_WRITER_H
|
||||
|
||||
#include "ExecutableWriter.h"
|
||||
#include "AMDGPULinkingContext.h"
|
||||
#include "AMDGPUSymbolTable.h"
|
||||
#include "AMDGPUTargetHandler.h"
|
||||
|
||||
namespace lld {
|
||||
namespace elf {
|
||||
|
||||
class AMDGPUTargetLayout;
|
||||
|
||||
class AMDGPUExecutableWriter : public ExecutableWriter<ELF64LE> {
|
||||
public:
|
||||
AMDGPUExecutableWriter(AMDGPULinkingContext &ctx, AMDGPUTargetLayout &layout);
|
||||
|
||||
unique_bump_ptr<SymbolTable<ELF64LE>> createSymbolTable() override {
|
||||
return unique_bump_ptr<SymbolTable<ELF64LE>>(new (this->_alloc)
|
||||
AMDGPUSymbolTable(_ctx));
|
||||
}
|
||||
|
||||
void createImplicitFiles(std::vector<std::unique_ptr<File>> &Result) override;
|
||||
void finalizeDefaultAtomValues() override;
|
||||
|
||||
private:
|
||||
AMDGPULinkingContext &_ctx;
|
||||
};
|
||||
|
||||
} // namespace elf
|
||||
} // namespace lld
|
||||
|
||||
#endif // AMDGPU_EXECUTABLE_WRITER_H
|
@ -1,41 +0,0 @@
|
||||
//===- lib/ReaderWriter/ELF/AMDGPU/AMDGPULinkingContext.cpp ---------------===//
|
||||
//
|
||||
// The LLVM Linker
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===------------------------------------------------------------------------===//
|
||||
|
||||
#include "AMDGPULinkingContext.h"
|
||||
#include "AMDGPUTargetHandler.h"
|
||||
|
||||
namespace lld {
|
||||
namespace elf {
|
||||
|
||||
std::unique_ptr<ELFLinkingContext>
|
||||
createAMDGPULinkingContext(llvm::Triple triple) {
|
||||
if (triple.getArch() == llvm::Triple::amdgcn)
|
||||
return llvm::make_unique<AMDGPULinkingContext>(triple);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AMDGPULinkingContext::AMDGPULinkingContext(llvm::Triple triple)
|
||||
: ELFLinkingContext(triple, llvm::make_unique<AMDGPUTargetHandler>(*this)) {
|
||||
}
|
||||
|
||||
static const Registry::KindStrings kindStrings[] = {LLD_KIND_STRING_END};
|
||||
|
||||
void AMDGPULinkingContext::registerRelocationNames(Registry ®istry) {
|
||||
registry.addKindTable(Reference::KindNamespace::ELF,
|
||||
Reference::KindArch::AMDGPU, kindStrings);
|
||||
}
|
||||
|
||||
void setAMDGPUELFHeader(ELFHeader<ELF64LE> &elfHeader) {
|
||||
elfHeader.e_ident(llvm::ELF::EI_OSABI, ELFOSABI_AMDGPU_HSA);
|
||||
}
|
||||
|
||||
StringRef AMDGPULinkingContext::entrySymbolName() const { return ""; }
|
||||
|
||||
} // namespace elf
|
||||
} // namespace lld
|
@ -1,36 +0,0 @@
|
||||
//===- lib/ReaderWriter/ELF/AMDGPU/AMDGPULinkingContext.h ---------------===//
|
||||
//
|
||||
// The LLVM Linker
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLD_READER_WRITER_ELF_AMDGPU_AMDGPU_LINKING_CONTEXT_H
|
||||
#define LLD_READER_WRITER_ELF_AMDGPU_AMDGPU_LINKING_CONTEXT_H
|
||||
|
||||
#include "OutputELFWriter.h"
|
||||
#include "lld/ReaderWriter/ELFLinkingContext.h"
|
||||
#include "llvm/Object/ELF.h"
|
||||
#include "llvm/Support/ELF.h"
|
||||
|
||||
namespace lld {
|
||||
namespace elf {
|
||||
|
||||
class AMDGPULinkingContext final : public ELFLinkingContext {
|
||||
public:
|
||||
AMDGPULinkingContext(llvm::Triple triple);
|
||||
int getMachineType() const override { return llvm::ELF::EM_AMDGPU; }
|
||||
|
||||
void registerRelocationNames(Registry &r) override;
|
||||
|
||||
StringRef entrySymbolName() const override;
|
||||
};
|
||||
|
||||
void setAMDGPUELFHeader(ELFHeader<ELF64LE> &elfHeader);
|
||||
|
||||
} // elf
|
||||
} // lld
|
||||
|
||||
#endif // LLD_READER_WRITER_ELF_AMDGPU_AMDGPU_LINKING_CONTEXT_H
|
@ -1,19 +0,0 @@
|
||||
//===- lib/ReaderWriter/ELF/AMDGPU/AMDGPURelocationHandler.cpp -----------===//
|
||||
//
|
||||
// The LLVM Linker
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "AMDGPURelocationHandler.h"
|
||||
|
||||
using namespace lld;
|
||||
using namespace lld::elf;
|
||||
|
||||
std::error_code AMDGPUTargetRelocationHandler::applyRelocation(
|
||||
ELFWriter &writer, llvm::FileOutputBuffer &buf, const AtomLayout &atom,
|
||||
const Reference &ref) const {
|
||||
return std::error_code();
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
//===- lld/ReaderWriter/ELF/AMDGPU/AMDGPURelocationHandler.h --------------===//
|
||||
//
|
||||
// The LLVM Linker
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#ifndef LLD_READER_WRITER_ELF_AMDGPU_AMDGPU_RELOCATION_HANDLER_H
|
||||
#define LLD_READER_WRITER_ELF_AMDGPU_AMDGPU_RELOCATION_HANDLER_H
|
||||
|
||||
#include "lld/ReaderWriter/ELFLinkingContext.h"
|
||||
#include <system_error>
|
||||
|
||||
namespace lld {
|
||||
namespace elf {
|
||||
class AMDGPUTargetHandler;
|
||||
class AMDGPUTargetLayout;
|
||||
|
||||
class AMDGPUTargetRelocationHandler final : public TargetRelocationHandler {
|
||||
public:
|
||||
AMDGPUTargetRelocationHandler(AMDGPUTargetLayout &layout) { }
|
||||
|
||||
std::error_code applyRelocation(ELFWriter &, llvm::FileOutputBuffer &,
|
||||
const AtomLayout &,
|
||||
const Reference &) const override;
|
||||
|
||||
};
|
||||
} // elf
|
||||
} // lld
|
||||
#endif
|
@ -1,32 +0,0 @@
|
||||
//===--------- lib/ReaderWriter/ELF/AMDGPU/AMDGPUSymbolTable.cpp ----------===//
|
||||
//
|
||||
// The LLVM Linker
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "AMDGPUSymbolTable.h"
|
||||
#include "ELFFile.h"
|
||||
#include "Atoms.h"
|
||||
#include "SectionChunks.h"
|
||||
|
||||
using namespace lld;
|
||||
using namespace lld::elf;
|
||||
|
||||
AMDGPUSymbolTable::AMDGPUSymbolTable(const ELFLinkingContext &ctx)
|
||||
: SymbolTable(ctx, ".symtab", TargetLayout<ELF64LE>::ORDER_SYMBOL_TABLE) {}
|
||||
|
||||
void AMDGPUSymbolTable::addDefinedAtom(Elf_Sym &sym, const DefinedAtom *da,
|
||||
int64_t addr) {
|
||||
SymbolTable::addDefinedAtom(sym, da, addr);
|
||||
|
||||
// FIXME: Only do this for kernel functions.
|
||||
sym.setType(STT_AMDGPU_HSA_KERNEL);
|
||||
|
||||
// Make st_value section relative.
|
||||
// FIXME: This is hack to give kernel symbols a section relative offset.
|
||||
// Because of this hack only on kernel can be included in a binary file.
|
||||
sym.st_value = 0;
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
//===--------- lib/ReaderWriter/ELF/AMDGPU/AMDGPUSymbolTable.h ------------===//
|
||||
//
|
||||
// The LLVM Linker
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLD_READER_WRITER_ELF_AMDGPU_AMDGPU_SYMBOL_TABLE_H
|
||||
#define LLD_READER_WRITER_ELF_AMDGPU_AMDGPU_SYMBOL_TABLE_H
|
||||
|
||||
#include "TargetLayout.h"
|
||||
|
||||
namespace lld {
|
||||
namespace elf {
|
||||
|
||||
/// \brief The SymbolTable class represents the symbol table in a ELF file
|
||||
class AMDGPUSymbolTable : public SymbolTable<ELF64LE> {
|
||||
public:
|
||||
typedef llvm::object::Elf_Sym_Impl<ELF64LE> Elf_Sym;
|
||||
|
||||
AMDGPUSymbolTable(const ELFLinkingContext &ctx);
|
||||
|
||||
void addDefinedAtom(Elf_Sym &sym, const DefinedAtom *da,
|
||||
int64_t addr) override;
|
||||
};
|
||||
|
||||
} // elf
|
||||
} // lld
|
||||
|
||||
#endif
|
@ -1,65 +0,0 @@
|
||||
//===- lib/ReaderWriter/ELF/AMDGPU/AMDGPUTargetHandler.cpp -------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Linker
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "TargetLayout.h"
|
||||
#include "AMDGPUExecutableWriter.h"
|
||||
#include "AMDGPULinkingContext.h"
|
||||
#include "AMDGPUTargetHandler.h"
|
||||
#include "llvm/Support/ELF.h"
|
||||
|
||||
namespace lld {
|
||||
namespace elf {
|
||||
|
||||
AMDGPUTargetHandler::AMDGPUTargetHandler(AMDGPULinkingContext &ctx)
|
||||
: _ctx(ctx), _targetLayout(new AMDGPUTargetLayout(ctx)),
|
||||
_relocationHandler(new AMDGPUTargetRelocationHandler(*_targetLayout)) {}
|
||||
|
||||
std::unique_ptr<Writer> AMDGPUTargetHandler::getWriter() {
|
||||
switch (_ctx.getOutputELFType()) {
|
||||
case llvm::ELF::ET_EXEC:
|
||||
return llvm::make_unique<AMDGPUExecutableWriter>(_ctx, *_targetLayout);
|
||||
case llvm::ELF::ET_DYN:
|
||||
llvm_unreachable("TODO: support dynamic libraries");
|
||||
case llvm::ELF::ET_REL:
|
||||
llvm_unreachable("TODO: support -r mode");
|
||||
default:
|
||||
llvm_unreachable("unsupported output type");
|
||||
}
|
||||
}
|
||||
|
||||
HSATextSection::HSATextSection(const ELFLinkingContext &ctx)
|
||||
: AtomSection(ctx, ".hsatext", DefinedAtom::typeCode, 0, 0) {
|
||||
_type = SHT_PROGBITS;
|
||||
_flags = SHF_ALLOC | SHF_WRITE | SHF_EXECINSTR | SHF_AMDGPU_HSA_AGENT |
|
||||
SHF_AMDGPU_HSA_CODE;
|
||||
|
||||
// FIXME: What alignment should we use here?
|
||||
_alignment = 4096;
|
||||
}
|
||||
|
||||
void AMDGPUTargetLayout::assignSectionsToSegments() {
|
||||
|
||||
TargetLayout::assignSectionsToSegments();
|
||||
for (OutputSection<ELF64LE> *osi : _outputSections) {
|
||||
for (Section<ELF64LE> *section : osi->sections()) {
|
||||
StringRef InputSectionName = section->inputSectionName();
|
||||
if (InputSectionName != ".hsatext")
|
||||
continue;
|
||||
|
||||
auto *segment = new (_allocator) Segment<ELF64LE>(
|
||||
_ctx, "PT_AMDGPU_HSA_LOAD_CODE_AGENT", PT_AMDGPU_HSA_LOAD_CODE_AGENT);
|
||||
_segments.push_back(segment);
|
||||
assert(segment);
|
||||
segment->append(section);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace elf
|
||||
} // namespace lld
|
@ -1,80 +0,0 @@
|
||||
//===- lib/ReaderWriter/ELF/AMDGPU/AMDGPUTargetHandler.h ------------------===//
|
||||
//
|
||||
// The LLVM Linker
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef AMDGPU_TARGET_HANDLER_H
|
||||
#define AMDGPU_TARGET_HANDLER_H
|
||||
|
||||
#include "ELFFile.h"
|
||||
#include "ELFReader.h"
|
||||
#include "AMDGPURelocationHandler.h"
|
||||
#include "TargetLayout.h"
|
||||
|
||||
namespace lld {
|
||||
namespace elf {
|
||||
class AMDGPULinkingContext;
|
||||
|
||||
class HSATextSection : public AtomSection<ELF64LE> {
|
||||
public:
|
||||
HSATextSection(const ELFLinkingContext &ctx);
|
||||
};
|
||||
|
||||
/// \brief TargetLayout for AMDGPU
|
||||
class AMDGPUTargetLayout final : public TargetLayout<ELF64LE> {
|
||||
public:
|
||||
AMDGPUTargetLayout(AMDGPULinkingContext &ctx) : TargetLayout(ctx) {}
|
||||
|
||||
void assignSectionsToSegments() override;
|
||||
|
||||
/// \brief Gets or creates a section.
|
||||
AtomSection<ELF64LE> *
|
||||
createSection(StringRef name, int32_t contentType,
|
||||
DefinedAtom::ContentPermissions contentPermissions,
|
||||
TargetLayout::SectionOrder sectionOrder) override {
|
||||
if (name == ".hsatext")
|
||||
return new (_allocator) HSATextSection(_ctx);
|
||||
|
||||
if (name == ".note")
|
||||
contentType = DefinedAtom::typeRONote;
|
||||
|
||||
return TargetLayout::createSection(name, contentType, contentPermissions,
|
||||
sectionOrder);
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief TargetHandler for AMDGPU
|
||||
class AMDGPUTargetHandler final : public TargetHandler {
|
||||
public:
|
||||
AMDGPUTargetHandler(AMDGPULinkingContext &targetInfo);
|
||||
|
||||
const TargetRelocationHandler &getRelocationHandler() const override {
|
||||
return *_relocationHandler;
|
||||
}
|
||||
|
||||
std::unique_ptr<Reader> getObjReader() override {
|
||||
return llvm::make_unique<ELFReader<ELFFile<ELF64LE>>>(_ctx);
|
||||
}
|
||||
|
||||
std::unique_ptr<Reader> getDSOReader() override {
|
||||
return llvm::make_unique<ELFReader<DynamicFile<ELF64LE>>>(_ctx);
|
||||
}
|
||||
|
||||
std::unique_ptr<Writer> getWriter() override;
|
||||
|
||||
private:
|
||||
AMDGPULinkingContext &_ctx;
|
||||
std::unique_ptr<AMDGPUTargetLayout> _targetLayout;
|
||||
std::unique_ptr<AMDGPUTargetRelocationHandler> _relocationHandler;
|
||||
};
|
||||
|
||||
void finalizeAMDGPURuntimeAtomValues(AMDGPUTargetLayout &layout);
|
||||
|
||||
} // end namespace elf
|
||||
} // end namespace lld
|
||||
|
||||
#endif
|
@ -1,13 +0,0 @@
|
||||
add_llvm_library(lldAMDGPUELFTarget
|
||||
AMDGPUExecutableWriter.cpp
|
||||
AMDGPULinkingContext.cpp
|
||||
AMDGPURelocationHandler.cpp
|
||||
AMDGPUSymbolTable.cpp
|
||||
AMDGPUTargetHandler.cpp
|
||||
LINK_LIBS
|
||||
lldELF
|
||||
lldReaderWriter
|
||||
lldCore
|
||||
LLVMObject
|
||||
LLVMSupport
|
||||
)
|
@ -1,4 +1,4 @@
|
||||
add_llvm_library(lldARMELFTarget
|
||||
add_lld_library(lldARMELFTarget
|
||||
ARMLinkingContext.cpp
|
||||
ARMTargetHandler.cpp
|
||||
ARMRelocationHandler.cpp
|
||||
|
@ -1,4 +1,4 @@
|
||||
add_llvm_library(lldELF
|
||||
add_lld_library(lldELF
|
||||
Atoms.cpp
|
||||
DynamicFile.cpp
|
||||
ELFFile.cpp
|
||||
@ -27,4 +27,3 @@ add_subdirectory(Mips)
|
||||
add_subdirectory(Hexagon)
|
||||
add_subdirectory(AArch64)
|
||||
add_subdirectory(ARM)
|
||||
add_subdirectory(AMDGPU)
|
||||
|
@ -61,8 +61,6 @@ uint16_t ELFLinkingContext::getOutputMachine() const {
|
||||
return llvm::ELF::EM_AARCH64;
|
||||
case llvm::Triple::arm:
|
||||
return llvm::ELF::EM_ARM;
|
||||
case llvm::Triple::amdgcn:
|
||||
return llvm::ELF::EM_AMDGPU;
|
||||
default:
|
||||
llvm_unreachable("Unhandled arch");
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
add_llvm_library(lldHexagonELFTarget
|
||||
add_lld_library(lldHexagonELFTarget
|
||||
HexagonLinkingContext.cpp
|
||||
HexagonRelocationHandler.cpp
|
||||
HexagonTargetHandler.cpp
|
||||
|
@ -1,4 +1,4 @@
|
||||
add_llvm_library(lldMipsELFTarget
|
||||
add_lld_library(lldMipsELFTarget
|
||||
MipsAbiInfoHandler.cpp
|
||||
MipsCtorsOrderPass.cpp
|
||||
MipsELFFile.cpp
|
||||
|
@ -1,4 +1,4 @@
|
||||
add_llvm_library(lldX86ELFTarget
|
||||
add_lld_library(lldX86ELFTarget
|
||||
X86LinkingContext.cpp
|
||||
X86TargetHandler.cpp
|
||||
X86RelocationHandler.cpp
|
||||
|
@ -1,4 +1,4 @@
|
||||
add_llvm_library(lldX86_64ELFTarget
|
||||
add_lld_library(lldX86_64ELFTarget
|
||||
X86_64LinkingContext.cpp
|
||||
X86_64TargetHandler.cpp
|
||||
X86_64RelocationHandler.cpp
|
||||
|
@ -1,4 +1,4 @@
|
||||
add_llvm_library(lldExampleSubTarget
|
||||
add_lld_library(lldExampleSubTarget
|
||||
ExampleLinkingContext.cpp
|
||||
ExampleTargetHandler.cpp
|
||||
LINK_LIBS
|
||||
|
@ -687,17 +687,28 @@ void ArchHandler_arm64::applyFixupRelocatable(const Reference &ref,
|
||||
case delta64:
|
||||
*loc64 = ref.addend() + inAtomAddress - fixupAddress;
|
||||
return;
|
||||
case unwindFDEToFunction:
|
||||
// We don't emit unwindFDEToFunction in -r mode as they are implicitly
|
||||
// generated from the data in the __eh_frame section. So here we need
|
||||
// to use the targetAddress so that we can generate the full relocation
|
||||
// when we parse again later.
|
||||
*loc64 = targetAddress - fixupAddress;
|
||||
return;
|
||||
case delta32:
|
||||
*loc32 = ref.addend() + inAtomAddress - fixupAddress;
|
||||
return;
|
||||
case negDelta32:
|
||||
// We don't emit negDelta32 in -r mode as they are implicitly
|
||||
// generated from the data in the __eh_frame section. So here we need
|
||||
// to use the targetAddress so that we can generate the full relocation
|
||||
// when we parse again later.
|
||||
*loc32 = fixupAddress - targetAddress + ref.addend();
|
||||
return;
|
||||
case pointer64ToGOT:
|
||||
*loc64 = 0;
|
||||
return;
|
||||
case delta32ToGOT:
|
||||
*loc32 = -fixupAddress;
|
||||
*loc32 = inAtomAddress - fixupAddress;
|
||||
return;
|
||||
case addOffset12:
|
||||
llvm_unreachable("lazy reference kind implies GOT pass was run");
|
||||
@ -709,9 +720,6 @@ void ArchHandler_arm64::applyFixupRelocatable(const Reference &ref,
|
||||
case unwindInfoToEhFrame:
|
||||
llvm_unreachable("fixup implies __unwind_info");
|
||||
return;
|
||||
case unwindFDEToFunction:
|
||||
// Do nothing for now
|
||||
return;
|
||||
case invalid:
|
||||
// Fall into llvm_unreachable().
|
||||
break;
|
||||
|
@ -1,4 +1,4 @@
|
||||
add_llvm_library(lldMachO
|
||||
add_lld_library(lldMachO
|
||||
ArchHandler.cpp
|
||||
ArchHandler_arm.cpp
|
||||
ArchHandler_arm64.cpp
|
||||
|
@ -168,7 +168,8 @@ void relocatableSectionInfoForContentType(DefinedAtom::ContentType atomType,
|
||||
StringRef &segmentName,
|
||||
StringRef §ionName,
|
||||
SectionType §ionType,
|
||||
SectionAttr §ionAttrs);
|
||||
SectionAttr §ionAttrs,
|
||||
bool &relocsToDefinedCanBeImplicit);
|
||||
|
||||
} // namespace normalized
|
||||
} // namespace mach_o
|
||||
|
@ -50,7 +50,8 @@ struct AtomInfo {
|
||||
|
||||
struct SectionInfo {
|
||||
SectionInfo(StringRef seg, StringRef sect, SectionType type,
|
||||
const MachOLinkingContext &ctxt, uint32_t attr=0);
|
||||
const MachOLinkingContext &ctxt, uint32_t attr,
|
||||
bool relocsToDefinedCanBeImplicit);
|
||||
|
||||
StringRef segmentName;
|
||||
StringRef sectionName;
|
||||
@ -59,15 +60,25 @@ struct SectionInfo {
|
||||
uint64_t address;
|
||||
uint64_t size;
|
||||
uint16_t alignment;
|
||||
|
||||
/// If this is set, the any relocs in this section which point to defined
|
||||
/// addresses can be implicitly generated. This is the case for the
|
||||
/// __eh_frame section where references to the function can be implicit if the
|
||||
/// function is defined.
|
||||
bool relocsToDefinedCanBeImplicit;
|
||||
|
||||
|
||||
std::vector<AtomInfo> atomsAndOffsets;
|
||||
uint32_t normalizedSectionIndex;
|
||||
uint32_t finalSectionIndex;
|
||||
};
|
||||
|
||||
SectionInfo::SectionInfo(StringRef sg, StringRef sct, SectionType t,
|
||||
const MachOLinkingContext &ctxt, uint32_t attrs)
|
||||
const MachOLinkingContext &ctxt, uint32_t attrs,
|
||||
bool relocsToDefinedCanBeImplicit)
|
||||
: segmentName(sg), sectionName(sct), type(t), attributes(attrs),
|
||||
address(0), size(0), alignment(1),
|
||||
relocsToDefinedCanBeImplicit(relocsToDefinedCanBeImplicit),
|
||||
normalizedSectionIndex(0), finalSectionIndex(0) {
|
||||
uint16_t align = 1;
|
||||
if (ctxt.sectionAligned(segmentName, sectionName, align)) {
|
||||
@ -193,10 +204,12 @@ SectionInfo *Util::getRelocatableSection(DefinedAtom::ContentType type) {
|
||||
StringRef sectionName;
|
||||
SectionType sectionType;
|
||||
SectionAttr sectionAttrs;
|
||||
bool relocsToDefinedCanBeImplicit;
|
||||
|
||||
// Use same table used by when parsing .o files.
|
||||
relocatableSectionInfoForContentType(type, segmentName, sectionName,
|
||||
sectionType, sectionAttrs);
|
||||
sectionType, sectionAttrs,
|
||||
relocsToDefinedCanBeImplicit);
|
||||
// If we already have a SectionInfo with this name, re-use it.
|
||||
// This can happen if two ContentType map to the same mach-o section.
|
||||
for (auto sect : _sectionMap) {
|
||||
@ -207,7 +220,8 @@ SectionInfo *Util::getRelocatableSection(DefinedAtom::ContentType type) {
|
||||
}
|
||||
// Otherwise allocate new SectionInfo object.
|
||||
auto *sect = new (_allocator)
|
||||
SectionInfo(segmentName, sectionName, sectionType, _ctx, sectionAttrs);
|
||||
SectionInfo(segmentName, sectionName, sectionType, _ctx, sectionAttrs,
|
||||
relocsToDefinedCanBeImplicit);
|
||||
_sectionInfos.push_back(sect);
|
||||
_sectionMap[type] = sect;
|
||||
return sect;
|
||||
@ -287,7 +301,8 @@ SectionInfo *Util::getFinalSection(DefinedAtom::ContentType atomType) {
|
||||
}
|
||||
// Otherwise allocate new SectionInfo object.
|
||||
auto *sect = new (_allocator) SectionInfo(
|
||||
p.segmentName, p.sectionName, p.sectionType, _ctx, sectionAttrs);
|
||||
p.segmentName, p.sectionName, p.sectionType, _ctx, sectionAttrs,
|
||||
/* relocsToDefinedCanBeImplicit */ false);
|
||||
_sectionInfos.push_back(sect);
|
||||
_sectionMap[atomType] = sect;
|
||||
return sect;
|
||||
@ -320,7 +335,8 @@ SectionInfo *Util::sectionForAtom(const DefinedAtom *atom) {
|
||||
StringRef segName = customName.slice(0, seperatorIndex);
|
||||
StringRef sectName = customName.drop_front(seperatorIndex + 1);
|
||||
auto *sect =
|
||||
new (_allocator) SectionInfo(segName, sectName, S_REGULAR, _ctx);
|
||||
new (_allocator) SectionInfo(segName, sectName, S_REGULAR, _ctx,
|
||||
0, /* relocsToDefinedCanBeImplicit */ false);
|
||||
_customSections.push_back(sect);
|
||||
_sectionInfos.push_back(sect);
|
||||
return sect;
|
||||
@ -1024,6 +1040,11 @@ void Util::addSectionRelocs(const lld::File &, NormalizedFile &file) {
|
||||
for (const AtomInfo &info : si->atomsAndOffsets) {
|
||||
const DefinedAtom *atom = info.atom;
|
||||
for (const Reference *ref : *atom) {
|
||||
// Skip emitting relocs for sections which are always able to be
|
||||
// implicitly regenerated and where the relocation targets an address
|
||||
// which is defined.
|
||||
if (si->relocsToDefinedCanBeImplicit && isa<DefinedAtom>(ref->target()))
|
||||
continue;
|
||||
_archHandler.appendSectionRelocations(*atom, info.offsetInSection, *ref,
|
||||
symIndexForAtom,
|
||||
sectIndexForAtom,
|
||||
|
@ -1034,7 +1034,8 @@ void relocatableSectionInfoForContentType(DefinedAtom::ContentType atomType,
|
||||
StringRef &segmentName,
|
||||
StringRef §ionName,
|
||||
SectionType §ionType,
|
||||
SectionAttr §ionAttrs) {
|
||||
SectionAttr §ionAttrs,
|
||||
bool &relocsToDefinedCanBeImplicit) {
|
||||
|
||||
for (const MachORelocatableSectionToAtomType *p = sectsToAtomType ;
|
||||
p->atomType != DefinedAtom::typeUnknown; ++p) {
|
||||
@ -1047,8 +1048,11 @@ void relocatableSectionInfoForContentType(DefinedAtom::ContentType atomType,
|
||||
sectionName = p->sectionName;
|
||||
sectionType = p->sectionType;
|
||||
sectionAttrs = 0;
|
||||
relocsToDefinedCanBeImplicit = false;
|
||||
if (atomType == DefinedAtom::typeCode)
|
||||
sectionAttrs = S_ATTR_PURE_INSTRUCTIONS;
|
||||
if (atomType == DefinedAtom::typeCFI)
|
||||
relocsToDefinedCanBeImplicit = true;
|
||||
return;
|
||||
}
|
||||
llvm_unreachable("content type not yet supported");
|
||||
|
@ -1,4 +1,4 @@
|
||||
add_llvm_library(lldYAML
|
||||
add_lld_library(lldYAML
|
||||
ReaderWriterYAML.cpp
|
||||
LINK_LIBS
|
||||
lldCore
|
||||
|
@ -80,3 +80,14 @@ SYMTAB: __imp_exportfn2 in export.test.tmp.DLL
|
||||
SYMTAB: exportfn2 in export.test.tmp.DLL
|
||||
SYMTAB: __imp_exportfn3 in export.test.tmp.DLL
|
||||
SYMTAB: exportfn3 in export.test.tmp.DLL
|
||||
|
||||
# RUN: lld-link /out:%t.dll /dll %t.obj /export:foo=kernel32.foobar
|
||||
# RUN: llvm-objdump -p %t.dll | FileCheck -check-prefix=FORWARDER %s
|
||||
|
||||
FORWARDER: Export Table:
|
||||
FORWARDER: DLL name: export.test.tmp.dll
|
||||
FORWARDER: Ordinal base: 0
|
||||
FORWARDER: Ordinal RVA Name
|
||||
FORWARDER: 0 0
|
||||
FORWARDER: 1 0x1010 exportfn
|
||||
FORWARDER: 2 foo (forwarded to kernel32.foobar)
|
||||
|
17
test/ELF/Inputs/aarch64-condb-reloc.s
Normal file
17
test/ELF/Inputs/aarch64-condb-reloc.s
Normal file
@ -0,0 +1,17 @@
|
||||
.globl _foo
|
||||
_foo:
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
.globl _bar
|
||||
_bar:
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
.globl _dah
|
||||
_dah:
|
||||
nop
|
||||
nop
|
19
test/ELF/Inputs/aarch64-tls-ie.s
Normal file
19
test/ELF/Inputs/aarch64-tls-ie.s
Normal file
@ -0,0 +1,19 @@
|
||||
.text
|
||||
.global foo
|
||||
.section .tdata,"awT",%progbits
|
||||
.align 2
|
||||
.type foo, %object
|
||||
.size foo, 4
|
||||
foo:
|
||||
.word 5
|
||||
.text
|
||||
|
||||
.text
|
||||
.global bar
|
||||
.section .tdata,"awT",%progbits
|
||||
.align 2
|
||||
.type bar, %object
|
||||
.size bar, 4
|
||||
bar:
|
||||
.word 5
|
||||
.text
|
12
test/ELF/Inputs/aarch64-tstbr14-reloc.s
Normal file
12
test/ELF/Inputs/aarch64-tstbr14-reloc.s
Normal file
@ -0,0 +1,12 @@
|
||||
.globl _foo
|
||||
_foo:
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
.globl _bar
|
||||
_bar:
|
||||
nop
|
||||
nop
|
||||
nop
|
BIN
test/ELF/Inputs/mips-gp-disp.so
Normal file
BIN
test/ELF/Inputs/mips-gp-disp.so
Normal file
Binary file not shown.
4
test/ELF/Inputs/wrap.s
Normal file
4
test/ELF/Inputs/wrap.s
Normal file
@ -0,0 +1,4 @@
|
||||
.globl foo, __wrap_foo, __real_foo
|
||||
foo = 0x11000
|
||||
__wrap_foo = 0x11010
|
||||
__real_foo = 0x11020
|
99
test/ELF/aarch64-condb-reloc.s
Normal file
99
test/ELF/aarch64-condb-reloc.s
Normal file
@ -0,0 +1,99 @@
|
||||
# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-freebsd %p/Inputs/aarch64-condb-reloc.s -o %t1
|
||||
# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-freebsd %s -o %t2
|
||||
# RUN: ld.lld %t1 %t2 -o %t
|
||||
# RUN: llvm-objdump -d %t | FileCheck %s
|
||||
# RUN: ld.lld -shared %t1 %t2 -o %t3
|
||||
# RUN: llvm-objdump -d %t3 | FileCheck -check-prefix=DSO %s
|
||||
# RUN: llvm-readobj -s -r %t3 | FileCheck -check-prefix=DSOREL %s
|
||||
# REQUIRES: aarch64
|
||||
|
||||
# 0x11024 - 36 = 0x11000
|
||||
# 0x11028 - 24 = 0x11010
|
||||
# 0x1102c - 16 = 0x1101c
|
||||
# CHECK: Disassembly of section .text:
|
||||
# CHECK-NEXT: _foo:
|
||||
# CHECK-NEXT: 11000: {{.*}} nop
|
||||
# CHECK-NEXT: 11004: {{.*}} nop
|
||||
# CHECK-NEXT: 11008: {{.*}} nop
|
||||
# CHECK-NEXT: 1100c: {{.*}} nop
|
||||
# CHECK: _bar:
|
||||
# CHECK-NEXT: 11010: {{.*}} nop
|
||||
# CHECK-NEXT: 11014: {{.*}} nop
|
||||
# CHECK-NEXT: 11018: {{.*}} nop
|
||||
# CHECK: _dah:
|
||||
# CHECK-NEXT: 1101c: {{.*}} nop
|
||||
# CHECK-NEXT: 11020: {{.*}} nop
|
||||
# CHECK: _start:
|
||||
# CHECK-NEXT: 11024: {{.*}} b.eq #-36
|
||||
# CHECK-NEXT: 11028: {{.*}} b.eq #-24
|
||||
# CHECK-NEXT: 1102c: {{.*}} b.eq #-16
|
||||
|
||||
#DSOREL: Section {
|
||||
#DSOREL: Index:
|
||||
#DSOREL: Name: .got.plt
|
||||
#DSOREL-NEXT: Type: SHT_PROGBITS
|
||||
#DSOREL-NEXT: Flags [
|
||||
#DSOREL-NEXT: SHF_ALLOC
|
||||
#DSOREL-NEXT: SHF_WRITE
|
||||
#DSOREL-NEXT: ]
|
||||
#DSOREL-NEXT: Address: 0x3000
|
||||
#DSOREL-NEXT: Offset: 0x3000
|
||||
#DSOREL-NEXT: Size: 48
|
||||
#DSOREL-NEXT: Link: 0
|
||||
#DSOREL-NEXT: Info: 0
|
||||
#DSOREL-NEXT: AddressAlignment: 8
|
||||
#DSOREL-NEXT: EntrySize: 0
|
||||
#DSOREL-NEXT: }
|
||||
#DSOREL: Relocations [
|
||||
#DSOREL-NEXT: Section ({{.*}}) .rela.plt {
|
||||
#DSOREL-NEXT: 0x3018 R_AARCH64_JUMP_SLOT _foo
|
||||
#DSOREL-NEXT: 0x3020 R_AARCH64_JUMP_SLOT _bar
|
||||
#DSOREL-NEXT: 0x3028 R_AARCH64_JUMP_SLOT _dah
|
||||
#DSOREL-NEXT: }
|
||||
#DSOREL-NEXT:]
|
||||
|
||||
#DSO: Disassembly of section .text:
|
||||
#DSO-NEXT: _foo:
|
||||
#DSO-NEXT: 1000: {{.*}} nop
|
||||
#DSO-NEXT: 1004: {{.*}} nop
|
||||
#DSO-NEXT: 1008: {{.*}} nop
|
||||
#DSO-NEXT: 100c: {{.*}} nop
|
||||
#DSO: _bar:
|
||||
#DSO-NEXT: 1010: {{.*}} nop
|
||||
#DSO-NEXT: 1014: {{.*}} nop
|
||||
#DSO-NEXT: 1018: {{.*}} nop
|
||||
#DSO: _dah:
|
||||
#DSO-NEXT: 101c: {{.*}} nop
|
||||
#DSO-NEXT: 1020: {{.*}} nop
|
||||
#DSO: _start:
|
||||
#DSO-NEXT: 1024: {{.*}} b.eq #44
|
||||
#DSO-NEXT: 1028: {{.*}} b.eq #56
|
||||
#DSO-NEXT: 102c: {{.*}} b.eq #68
|
||||
#DSO-NEXT: Disassembly of section .plt:
|
||||
#DSO-NEXT: .plt:
|
||||
#DSO-NEXT: 1030: {{.*}} stp x16, x30, [sp, #-16]!
|
||||
#DSO-NEXT: 1034: {{.*}} adrp x16, #8192
|
||||
#DSO-NEXT: 1038: {{.*}} ldr x17, [x16, #16]
|
||||
#DSO-NEXT: 103c: {{.*}} add x16, x16, #16
|
||||
#DSO-NEXT: 1040: {{.*}} br x17
|
||||
#DSO-NEXT: 1044: {{.*}} nop
|
||||
#DSO-NEXT: 1048: {{.*}} nop
|
||||
#DSO-NEXT: 104c: {{.*}} nop
|
||||
#DSO-NEXT: 1050: {{.*}} adrp x16, #8192
|
||||
#DSO-NEXT: 1054: {{.*}} ldr x17, [x16, #24]
|
||||
#DSO-NEXT: 1058: {{.*}} add x16, x16, #24
|
||||
#DSO-NEXT: 105c: {{.*}} br x17
|
||||
#DSO-NEXT: 1060: {{.*}} adrp x16, #8192
|
||||
#DSO-NEXT: 1064: {{.*}} ldr x17, [x16, #32]
|
||||
#DSO-NEXT: 1068: {{.*}} add x16, x16, #32
|
||||
#DSO-NEXT: 106c: {{.*}} br x17
|
||||
#DSO-NEXT: 1070: {{.*}} adrp x16, #8192
|
||||
#DSO-NEXT: 1074: {{.*}} ldr x17, [x16, #40]
|
||||
#DSO-NEXT: 1078: {{.*}} add x16, x16, #40
|
||||
#DSO-NEXT: 107c: {{.*}} br x17
|
||||
|
||||
.globl _start
|
||||
_start:
|
||||
b.eq _foo
|
||||
b.eq _bar
|
||||
b.eq _dah
|
29
test/ELF/aarch64-gnu-ifunc-nosym.s
Normal file
29
test/ELF/aarch64-gnu-ifunc-nosym.s
Normal file
@ -0,0 +1,29 @@
|
||||
// RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux-gnu %s -o %t.o
|
||||
// RUN: ld.lld -static %t.o -o %tout
|
||||
// RUN: llvm-readobj -symbols %tout | FileCheck %s
|
||||
// REQUIRES: aarch64
|
||||
|
||||
// Check that no __rela_iplt_end/__rela_iplt_start
|
||||
// appear in symtab if there is no references to them.
|
||||
// CHECK: Symbols [
|
||||
// CHECK-NEXT-NOT: __rela_iplt_end
|
||||
// CHECK-NEXT-NOT: __rela_iplt_start
|
||||
// CHECK: ]
|
||||
|
||||
.text
|
||||
.type foo STT_GNU_IFUNC
|
||||
.globl foo
|
||||
.type foo, @function
|
||||
foo:
|
||||
ret
|
||||
|
||||
.type bar STT_GNU_IFUNC
|
||||
.globl bar
|
||||
.type bar, @function
|
||||
bar:
|
||||
ret
|
||||
|
||||
.globl _start
|
||||
_start:
|
||||
bl foo
|
||||
bl bar
|
144
test/ELF/aarch64-gnu-ifunc.s
Normal file
144
test/ELF/aarch64-gnu-ifunc.s
Normal file
@ -0,0 +1,144 @@
|
||||
// RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux-gnu %s -o %t.o
|
||||
// RUN: ld.lld -static %t.o -o %tout
|
||||
// RUN: llvm-objdump -d %tout | FileCheck %s --check-prefix=DISASM
|
||||
// RUN: llvm-readobj -r -symbols -sections %tout | FileCheck %s --check-prefix=CHECK
|
||||
// REQUIRES: aarch64
|
||||
|
||||
// CHECK: Sections [
|
||||
// CHECK: Section {
|
||||
// CHECK: Index: 1
|
||||
// CHECK-NEXT: Name: .rela.plt
|
||||
// CHECK-NEXT: Type: SHT_RELA
|
||||
// CHECK-NEXT: Flags [
|
||||
// CHECK-NEXT: SHF_ALLOC
|
||||
// CHECK-NEXT: ]
|
||||
// CHECK-NEXT: Address: [[RELA:.*]]
|
||||
// CHECK-NEXT: Offset: 0x158
|
||||
// CHECK-NEXT: Size: 48
|
||||
// CHECK-NEXT: Link: 5
|
||||
// CHECK-NEXT: Info: 0
|
||||
// CHECK-NEXT: AddressAlignment: 8
|
||||
// CHECK-NEXT: EntrySize: 24
|
||||
// CHECK-NEXT: }
|
||||
// CHECK: Relocations [
|
||||
// CHECK-NEXT: Section ({{.*}}) .rela.plt {
|
||||
// CHECK-NEXT: 0x12018 R_AARCH64_IRELATIVE
|
||||
// CHECK-NEXT: 0x12020 R_AARCH64_IRELATIVE
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: ]
|
||||
// CHECK: Symbols [
|
||||
// CHECK-NEXT: Symbol {
|
||||
// CHECK-NEXT: Name:
|
||||
// CHECK-NEXT: Value: 0x0
|
||||
// CHECK-NEXT: Size: 0
|
||||
// CHECK-NEXT: Binding: Local
|
||||
// CHECK-NEXT: Type: None
|
||||
// CHECK-NEXT: Other: 0
|
||||
// CHECK-NEXT: Section: Undefined
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: Symbol {
|
||||
// CHECK-NEXT: Name: $x.0
|
||||
// CHECK-NEXT: Value: 0x11000
|
||||
// CHECK-NEXT: Size: 0
|
||||
// CHECK-NEXT: Binding: Local
|
||||
// CHECK-NEXT: Type: None
|
||||
// CHECK-NEXT: Other: 0
|
||||
// CHECK-NEXT: Section: .text
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: Symbol {
|
||||
// CHECK-NEXT: Name: __rela_iplt_end
|
||||
// CHECK-NEXT: Value: 0x10188
|
||||
// CHECK-NEXT: Size: 0
|
||||
// CHECK-NEXT: Binding: Local
|
||||
// CHECK-NEXT: Type: None
|
||||
// CHECK-NEXT: Other: 0
|
||||
// CHECK-NEXT: Section: Absolute
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: Symbol {
|
||||
// CHECK-NEXT: Name: __rela_iplt_start
|
||||
// CHECK-NEXT: Value: 0x10158
|
||||
// CHECK-NEXT: Size: 0
|
||||
// CHECK-NEXT: Binding: Local
|
||||
// CHECK-NEXT: Type: None
|
||||
// CHECK-NEXT: Other: 0
|
||||
// CHECK-NEXT: Section: Absolute
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: Symbol {
|
||||
// CHECK-NEXT: Name: _start
|
||||
// CHECK-NEXT: Value: 0x11008
|
||||
// CHECK-NEXT: Size: 0
|
||||
// CHECK-NEXT: Binding: Global
|
||||
// CHECK-NEXT: Type: None
|
||||
// CHECK-NEXT: Other: 0
|
||||
// CHECK-NEXT: Section: .text
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: Symbol {
|
||||
// CHECK-NEXT: Name: bar
|
||||
// CHECK-NEXT: Value: 0x11004
|
||||
// CHECK-NEXT: Size: 0
|
||||
// CHECK-NEXT: Binding: Global
|
||||
// CHECK-NEXT: Type: GNU_IFunc
|
||||
// CHECK-NEXT: Other: 0
|
||||
// CHECK-NEXT: Section: .text
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: Symbol {
|
||||
// CHECK-NEXT: Name: foo
|
||||
// CHECK-NEXT: Value: 0x11000
|
||||
// CHECK-NEXT: Size: 0
|
||||
// CHECK-NEXT: Binding: Global
|
||||
// CHECK-NEXT: Type: GNU_IFunc
|
||||
// CHECK-NEXT: Other: 0
|
||||
// CHECK-NEXT: Section: .text
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: ]
|
||||
|
||||
// 344 = 0x158
|
||||
// 392 = 0x188
|
||||
// DISASM: Disassembly of section .text:
|
||||
// DISASM-NEXT: foo:
|
||||
// DISASM-NEXT: 11000: c0 03 5f d6 ret
|
||||
// DISASM: bar:
|
||||
// DISASM-NEXT: 11004: c0 03 5f d6 ret
|
||||
// DISASM: _start:
|
||||
// DISASM-NEXT: 11008: 0e 00 00 94 bl #56
|
||||
// DISASM-NEXT: 1100c: 11 00 00 94 bl #68
|
||||
// DISASM-NEXT: 11010: 42 60 05 91 add x2, x2, #344
|
||||
// DISASM-NEXT: 11014: 42 20 06 91 add x2, x2, #392
|
||||
// DISASM-NEXT: Disassembly of section .plt:
|
||||
// DISASM-NEXT: .plt:
|
||||
// DISASM-NEXT: 11020: f0 7b bf a9 stp x16, x30, [sp, #-16]!
|
||||
// DISASM-NEXT: 11024: 10 00 00 b0 adrp x16, #4096
|
||||
// DISASM-NEXT: 11028: 11 0a 40 f9 ldr x17, [x16, #16]
|
||||
// DISASM-NEXT: 1102c: 10 42 00 91 add x16, x16, #16
|
||||
// DISASM-NEXT: 11030: 20 02 1f d6 br x17
|
||||
// DISASM-NEXT: 11034: 1f 20 03 d5 nop
|
||||
// DISASM-NEXT: 11038: 1f 20 03 d5 nop
|
||||
// DISASM-NEXT: 1103c: 1f 20 03 d5 nop
|
||||
// DISASM-NEXT: 11040: 10 00 00 b0 adrp x16, #4096
|
||||
// DISASM-NEXT: 11044: 11 0e 40 f9 ldr x17, [x16, #24]
|
||||
// DISASM-NEXT: 11048: 10 62 00 91 add x16, x16, #24
|
||||
// DISASM-NEXT: 1104c: 20 02 1f d6 br x17
|
||||
// DISASM-NEXT: 11050: 10 00 00 b0 adrp x16, #4096
|
||||
// DISASM-NEXT: 11054: 11 12 40 f9 ldr x17, [x16, #32]
|
||||
// DISASM-NEXT: 11058: 10 82 00 91 add x16, x16, #32
|
||||
// DISASM-NEXT: 1105c: 20 02 1f d6 br x17
|
||||
|
||||
.text
|
||||
.type foo STT_GNU_IFUNC
|
||||
.globl foo
|
||||
.type foo, @function
|
||||
foo:
|
||||
ret
|
||||
|
||||
.type bar STT_GNU_IFUNC
|
||||
.globl bar
|
||||
.type bar, @function
|
||||
bar:
|
||||
ret
|
||||
|
||||
.globl _start
|
||||
_start:
|
||||
bl foo
|
||||
bl bar
|
||||
add x2, x2, :lo12:__rela_iplt_start
|
||||
add x2, x2, :lo12:__rela_iplt_end
|
49
test/ELF/aarch64-tls-ie.s
Normal file
49
test/ELF/aarch64-tls-ie.s
Normal file
@ -0,0 +1,49 @@
|
||||
# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-freebsd %p/Inputs/aarch64-tls-ie.s -o %tdso.o
|
||||
# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-freebsd %s -o %tmain.o
|
||||
# RUN: ld.lld -shared %tdso.o -o %tdso.so
|
||||
# RUN: ld.lld %tmain.o %tdso.so -o %tout
|
||||
# RUN: llvm-objdump -d %tout | FileCheck %s
|
||||
# RUN: llvm-readobj -s -r %tout | FileCheck -check-prefix=RELOC %s
|
||||
# REQUIRES: aarch64
|
||||
|
||||
#RELOC: Section {
|
||||
#RELOC: Index:
|
||||
#RELOC: Name: .got
|
||||
#RELOC-NEXT: Type: SHT_PROGBITS
|
||||
#RELOC-NEXT: Flags [
|
||||
#RELOC-NEXT: SHF_ALLOC
|
||||
#RELOC-NEXT: SHF_WRITE
|
||||
#RELOC-NEXT: ]
|
||||
#RELOC-NEXT: Address: 0x120B0
|
||||
#RELOC-NEXT: Offset: 0x20B0
|
||||
#RELOC-NEXT: Size: 16
|
||||
#RELOC-NEXT: Link: 0
|
||||
#RELOC-NEXT: Info: 0
|
||||
#RELOC-NEXT: AddressAlignment: 8
|
||||
#RELOC-NEXT: EntrySize: 0
|
||||
#RELOC-NEXT: }
|
||||
#RELOC: Relocations [
|
||||
#RELOC-NEXT: Section ({{.*}}) .rela.dyn {
|
||||
#RELOC-NEXT: 0x120B0 R_AARCH64_TLS_TPREL64 foo 0x0
|
||||
#RELOC-NEXT: 0x120B8 R_AARCH64_TLS_TPREL64 bar 0x0
|
||||
#RELOC-NEXT: }
|
||||
#RELOC-NEXT:]
|
||||
|
||||
# Page(0x120B0) - Page(0x11000) = 0x1000 = 4096
|
||||
# 0x120B0 & 0xff8 = 0xB0 = 176
|
||||
# Page(0x120B8) - Page(0x11000) = 0x1000 = 4096
|
||||
# 0x120B8 & 0xff8 = 0xB8 = 184
|
||||
#CHECK: Disassembly of section .text:
|
||||
#CHECK: _start:
|
||||
#CHECK: 11000: 00 00 00 b0 adrp x0, #4096
|
||||
#CHECK: 11004: 00 58 40 f9 ldr x0, [x0, #176]
|
||||
#CHECK: 11008: 00 00 00 b0 adrp x0, #4096
|
||||
#CHECK: 1100c: 00 5c 40 f9 ldr x0, [x0, #184]
|
||||
|
||||
.globl _start
|
||||
_start:
|
||||
adrp x0, :gottprel:foo
|
||||
ldr x0, [x0, #:gottprel_lo12:foo]
|
||||
|
||||
adrp x0, :gottprel:bar
|
||||
ldr x0, [x0, #:gottprel_lo12:bar]
|
96
test/ELF/aarch64-tstbr14-reloc.s
Normal file
96
test/ELF/aarch64-tstbr14-reloc.s
Normal file
@ -0,0 +1,96 @@
|
||||
# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-freebsd %p/Inputs/aarch64-tstbr14-reloc.s -o %t1
|
||||
# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-freebsd %s -o %t2
|
||||
# RUN: ld.lld %t1 %t2 -o %t
|
||||
# RUN: llvm-objdump -d %t | FileCheck %s
|
||||
# RUN: ld.lld -shared %t1 %t2 -o %t3
|
||||
# RUN: llvm-objdump -d %t3 | FileCheck -check-prefix=DSO %s
|
||||
# RUN: llvm-readobj -s -r %t3 | FileCheck -check-prefix=DSOREL %s
|
||||
# REQUIRES: aarch64
|
||||
|
||||
# 0x1101c - 28 = 0x11000
|
||||
# 0x11020 - 16 = 0x11010
|
||||
# 0x11024 - 36 = 0x11000
|
||||
# 0x11028 - 24 = 0x11010
|
||||
# CHECK: Disassembly of section .text:
|
||||
# CHECK-NEXT: _foo:
|
||||
# CHECK-NEXT: 11000: {{.*}} nop
|
||||
# CHECK-NEXT: 11004: {{.*}} nop
|
||||
# CHECK-NEXT: 11008: {{.*}} nop
|
||||
# CHECK-NEXT: 1100c: {{.*}} nop
|
||||
# CHECK: _bar:
|
||||
# CHECK-NEXT: 11010: {{.*}} nop
|
||||
# CHECK-NEXT: 11014: {{.*}} nop
|
||||
# CHECK-NEXT: 11018: {{.*}} nop
|
||||
# CHECK: _start:
|
||||
# CHECK-NEXT: 1101c: {{.*}} tbnz w3, #15, #-28
|
||||
# CHECK-NEXT: 11020: {{.*}} tbnz w3, #15, #-16
|
||||
# CHECK-NEXT: 11024: {{.*}} tbz x6, #45, #-36
|
||||
# CHECK-NEXT: 11028: {{.*}} tbz x6, #45, #-24
|
||||
|
||||
#DSOREL: Section {
|
||||
#DSOREL: Index:
|
||||
#DSOREL: Name: .got.plt
|
||||
#DSOREL-NEXT: Type: SHT_PROGBITS
|
||||
#DSOREL-NEXT: Flags [
|
||||
#DSOREL-NEXT: SHF_ALLOC
|
||||
#DSOREL-NEXT: SHF_WRITE
|
||||
#DSOREL-NEXT: ]
|
||||
#DSOREL-NEXT: Address: 0x3000
|
||||
#DSOREL-NEXT: Offset: 0x3000
|
||||
#DSOREL-NEXT: Size: 40
|
||||
#DSOREL-NEXT: Link: 0
|
||||
#DSOREL-NEXT: Info: 0
|
||||
#DSOREL-NEXT: AddressAlignment: 8
|
||||
#DSOREL-NEXT: EntrySize: 0
|
||||
#DSOREL-NEXT: }
|
||||
#DSOREL: Relocations [
|
||||
#DSOREL-NEXT: Section ({{.*}}) .rela.plt {
|
||||
#DSOREL-NEXT: 0x3018 R_AARCH64_JUMP_SLOT _foo
|
||||
#DSOREL-NEXT: 0x3020 R_AARCH64_JUMP_SLOT _bar
|
||||
#DSOREL-NEXT: }
|
||||
#DSOREL-NEXT:]
|
||||
|
||||
#DSO: Disassembly of section .text:
|
||||
#DSO-NEXT: _foo:
|
||||
#DSO-NEXT: 1000: {{.*}} nop
|
||||
#DSO-NEXT: 1004: {{.*}} nop
|
||||
#DSO-NEXT: 1008: {{.*}} nop
|
||||
#DSO-NEXT: 100c: {{.*}} nop
|
||||
#DSO: _bar:
|
||||
#DSO-NEXT: 1010: {{.*}} nop
|
||||
#DSO-NEXT: 1014: {{.*}} nop
|
||||
#DSO-NEXT: 1018: {{.*}} nop
|
||||
#DSO: _start:
|
||||
# 0x101c + 52 = 0x1050 = PLT[1]
|
||||
# 0x1020 + 64 = 0x1060 = PLT[2]
|
||||
# 0x1024 + 44 = 0x1050 = PLT[1]
|
||||
# 0x1028 + 56 = 0x1060 = PLT[2]
|
||||
#DSO-NEXT: 101c: {{.*}} tbnz w3, #15, #52
|
||||
#DSO-NEXT: 1020: {{.*}} tbnz w3, #15, #64
|
||||
#DSO-NEXT: 1024: {{.*}} tbz x6, #45, #44
|
||||
#DSO-NEXT: 1028: {{.*}} tbz x6, #45, #56
|
||||
#DSO-NEXT: Disassembly of section .plt:
|
||||
#DSO-NEXT: .plt:
|
||||
#DSO-NEXT: 1030: {{.*}} stp x16, x30, [sp, #-16]!
|
||||
#DSO-NEXT: 1034: {{.*}} adrp x16, #8192
|
||||
#DSO-NEXT: 1038: {{.*}} ldr x17, [x16, #16]
|
||||
#DSO-NEXT: 103c: {{.*}} add x16, x16, #16
|
||||
#DSO-NEXT: 1040: {{.*}} br x17
|
||||
#DSO-NEXT: 1044: {{.*}} nop
|
||||
#DSO-NEXT: 1048: {{.*}} nop
|
||||
#DSO-NEXT: 104c: {{.*}} nop
|
||||
#DSO-NEXT: 1050: {{.*}} adrp x16, #8192
|
||||
#DSO-NEXT: 1054: {{.*}} ldr x17, [x16, #24]
|
||||
#DSO-NEXT: 1058: {{.*}} add x16, x16, #24
|
||||
#DSO-NEXT: 105c: {{.*}} br x17
|
||||
#DSO-NEXT: 1060: {{.*}} adrp x16, #8192
|
||||
#DSO-NEXT: 1064: {{.*}} ldr x17, [x16, #32]
|
||||
#DSO-NEXT: 1068: {{.*}} add x16, x16, #32
|
||||
#DSO-NEXT: 106c: {{.*}} br x17
|
||||
|
||||
.globl _start
|
||||
_start:
|
||||
tbnz w3, #15, _foo
|
||||
tbnz w3, #15, _bar
|
||||
tbz x6, #45, _foo
|
||||
tbz x6, #45, _bar
|
16
test/ELF/amdgpu-entry.s
Normal file
16
test/ELF/amdgpu-entry.s
Normal file
@ -0,0 +1,16 @@
|
||||
# RUN: llvm-mc -filetype=obj -triple amdgcn--amdhsa -mcpu=kaveri %s -o %t.o
|
||||
# RUN: not lld -e kernel0 -flavor gnu %t.o -o %t
|
||||
|
||||
# REQUIRES: amdgpu
|
||||
|
||||
.hsa_code_object_version 1,0
|
||||
.hsa_code_object_isa 7,0,0,"AMD","AMDGPU"
|
||||
|
||||
.hsatext
|
||||
.globl kernel0
|
||||
.align 256
|
||||
.amdgpu_hsa_kernel kernel0
|
||||
kernel0:
|
||||
s_endpgm
|
||||
.Lfunc_end0:
|
||||
.size kernel0, .Lfunc_end0-kernel0
|
138
test/ELF/amdgpu-globals.s
Normal file
138
test/ELF/amdgpu-globals.s
Normal file
@ -0,0 +1,138 @@
|
||||
# RUN: llvm-mc -filetype=obj -triple amdgcn--amdhsa -mcpu=kaveri %s -o %t.o
|
||||
# RUN: lld -flavor gnu %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
|
||||
|
||||
.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
|
||||
|
||||
# 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: }
|
||||
|
||||
# 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: }
|
||||
|
||||
# CHECK: Symbol {
|
||||
# CHECK: Name: module_global_agent
|
||||
# CHECK: Value: 0x0
|
||||
# CHECK: Size: 4
|
||||
# CHECK: Binding: Local
|
||||
# CHECK: Section: .hsadata_global_agent
|
||||
# CHECK: }
|
||||
|
||||
# CHECK: Symbol {
|
||||
# CHECK: Name: module_global_program
|
||||
# CHECK: Value: 0x0
|
||||
# CHECK: Size: 4
|
||||
# CHECK: Binding: Local
|
||||
# CHECK: Section: .hsadata_global_program
|
||||
# CHECK: }
|
||||
|
||||
# CHECK: Symbol {
|
||||
# CHECK: Name: module_global_readonly
|
||||
# CHECK: Value: 0x0
|
||||
# CHECK: Size: 4
|
||||
# CHECK: Binding: Local
|
||||
# CHECK: Type: Object
|
||||
# CHECK: Section: .hsatext
|
||||
# CHECK: }
|
||||
|
||||
# CHECK: Symbol {
|
||||
# CHECK: Name: program_global_agent
|
||||
# CHECK: Value: 0x4
|
||||
# CHECK: Size: 4
|
||||
# CHECK: Binding: Global
|
||||
# CHECK: Type: Object
|
||||
# CHECK: Section: .hsadata_global_agent
|
||||
# CHECK: }
|
||||
|
||||
# CHECK: Symbol {
|
||||
# CHECK: Name: program_global_program
|
||||
# CHECK: Value: 0x4
|
||||
# CHECK: Size: 4
|
||||
# CHECK: Binding: Global
|
||||
# CHECK: Type: Object
|
||||
# CHECK: Section: .hsadata_global_program
|
||||
# CHECK: }
|
||||
|
||||
# CHECK: Symbol {
|
||||
# CHECK: Name: program_global_readonly
|
||||
# CHECK: Value: 0x4
|
||||
# CHECK: Size: 4
|
||||
# CHECK: Binding: Global
|
||||
# CHECK: Type: Object
|
||||
# CHECK: Section: .hsatext
|
||||
# CHECK: }
|
||||
|
||||
# CHECK: ProgramHeader {
|
||||
# CHECK: Type: PT_AMDGPU_HSA_LOAD_GLOBAL_PROGRAM
|
||||
# CHECK: VirtualAddress: [[HSADATA_GLOBAL_PROGRAM_ADDR]]
|
||||
# CHECK: }
|
||||
|
||||
# CHECK: ProgramHeader {
|
||||
# CHECK: Type: PT_AMDGPU_HSA_LOAD_CODE_AGENT
|
||||
# CHECK: VirtualAddress: [[HSATEXT_ADDR]]
|
||||
# CHECK: }
|
63
test/ELF/amdgpu-kernels.s
Normal file
63
test/ELF/amdgpu-kernels.s
Normal file
@ -0,0 +1,63 @@
|
||||
# RUN: llvm-mc -filetype=obj -triple amdgcn--amdhsa -mcpu=kaveri %s -o %t.o
|
||||
# RUN: lld -flavor gnu %t.o -o %t
|
||||
# RUN: llvm-readobj -sections -symbols -program-headers %t | FileCheck %s
|
||||
|
||||
# REQUIRES: amdgpu
|
||||
|
||||
.hsa_code_object_version 1,0
|
||||
.hsa_code_object_isa 7,0,0,"AMD","AMDGPU"
|
||||
|
||||
.hsatext
|
||||
.globl kernel0
|
||||
.align 256
|
||||
.amdgpu_hsa_kernel kernel0
|
||||
kernel0:
|
||||
s_endpgm
|
||||
.Lfunc_end0:
|
||||
.size kernel0, .Lfunc_end0-kernel0
|
||||
|
||||
.globl kernel1
|
||||
.align 256
|
||||
.amdgpu_hsa_kernel kernel1
|
||||
kernel1:
|
||||
s_endpgm
|
||||
s_endpgm
|
||||
.Lfunc_end1:
|
||||
.size kernel1, .Lfunc_end1-kernel1
|
||||
|
||||
|
||||
# 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: }
|
||||
|
||||
# CHECK: Symbol {
|
||||
# CHECK: Name: kernel0
|
||||
# CHECK: Value: 0x0
|
||||
# CHECK: Size: 4
|
||||
# CHECK: Binding: Global
|
||||
# CHECK: Type: AMDGPU_HSA_KERNEL
|
||||
# CHECK: Section: .hsatext
|
||||
# CHECK: }
|
||||
|
||||
# CHECK: Symbol {
|
||||
# CHECK: Name: kernel1
|
||||
# CHECK: Value: 0x100
|
||||
# CHECK: Size: 8
|
||||
# CHECK: Binding: Global
|
||||
# CHECK: Type: AMDGPU_HSA_KERNEL
|
||||
# CHECK: Section: .hsatext
|
||||
# CHECK: }
|
||||
|
||||
# CHECK: ProgramHeader {
|
||||
# CHECK: Type: PT_AMDGPU_HSA_LOAD_CODE_AGENT
|
||||
# CHECK: VirtualAddress: [[HSATEXT_ADDR]]
|
||||
# CHECK: }
|
@ -97,7 +97,7 @@ _start:
|
||||
# CHECK-NEXT: }
|
||||
# CHECK-NEXT: Section {
|
||||
# CHECK-NEXT: Index: 4
|
||||
# CHECK-NEXT: Name: .strtab (17)
|
||||
# CHECK-NEXT: Name: .strtab (25)
|
||||
# CHECK-NEXT: Type: SHT_STRTAB (0x3)
|
||||
# CHECK-NEXT: Flags [ (0x0)
|
||||
# CHECK-NEXT: ]
|
||||
|
@ -87,7 +87,7 @@ __start:
|
||||
# CHECK-NEXT: }
|
||||
# CHECK-NEXT: Section {
|
||||
# CHECK-NEXT: Index: 3
|
||||
# CHECK-NEXT: Name: .text (1)
|
||||
# CHECK-NEXT: Name: .text (25)
|
||||
# CHECK-NEXT: Type: SHT_PROGBITS (0x1)
|
||||
# CHECK-NEXT: Flags [ (0x6)
|
||||
# CHECK-NEXT: SHF_ALLOC (0x2)
|
||||
@ -119,7 +119,7 @@ __start:
|
||||
# CHECK-NEXT: }
|
||||
# CHECK-NEXT: Section {
|
||||
# CHECK-NEXT: Index: 5
|
||||
# CHECK-NEXT: Name: .bss (7)
|
||||
# CHECK-NEXT: Name: .bss (37)
|
||||
# CHECK-NEXT: Type: SHT_NOBITS (0x8)
|
||||
# CHECK-NEXT: Flags [ (0x3)
|
||||
# CHECK-NEXT: SHF_ALLOC (0x2)
|
||||
@ -163,7 +163,7 @@ __start:
|
||||
# CHECK-NEXT: }
|
||||
# CHECK-NEXT: Section {
|
||||
# CHECK-NEXT: Index: 8
|
||||
# CHECK-NEXT: Name: .strtab (46)
|
||||
# CHECK-NEXT: Name: .strtab (60)
|
||||
# CHECK-NEXT: Type: SHT_STRTAB (0x3)
|
||||
# CHECK-NEXT: Flags [ (0x0)
|
||||
# CHECK-NEXT: ]
|
||||
|
296
test/ELF/basic-ppc.s
Normal file
296
test/ELF/basic-ppc.s
Normal file
@ -0,0 +1,296 @@
|
||||
# RUN: llvm-mc -filetype=obj -triple=powerpc-unknown-freebsd %s -o %t
|
||||
# RUN: ld.lld -discard-all -shared %t -o %t2
|
||||
# RUN: llvm-readobj -file-headers -sections -section-data -program-headers %t2 | FileCheck %s
|
||||
# REQUIRES: ppc
|
||||
|
||||
# exits with return code 42 on FreeBSD
|
||||
.text
|
||||
li 0,1
|
||||
li 3,1
|
||||
sc
|
||||
|
||||
// CHECK: Format: ELF32-ppc
|
||||
// CHECK-NEXT: Arch: powerpc
|
||||
// CHECK-NEXT: AddressSize: 32bit
|
||||
// CHECK-NEXT: LoadName:
|
||||
// CHECK-NEXT: ElfHeader {
|
||||
// CHECK-NEXT: Ident {
|
||||
// CHECK-NEXT: Magic: (7F 45 4C 46)
|
||||
// CHECK-NEXT: Class: 32-bit (0x1)
|
||||
// CHECK-NEXT: DataEncoding: BigEndian (0x2)
|
||||
// CHECK-NEXT: FileVersion: 1
|
||||
// CHECK-NEXT: OS/ABI: FreeBSD (0x9)
|
||||
// CHECK-NEXT: ABIVersion: 0
|
||||
// CHECK-NEXT: Unused: (00 00 00 00 00 00 00)
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: Type: SharedObject (0x3)
|
||||
// CHECK-NEXT: Machine: EM_PPC (0x14)
|
||||
// CHECK-NEXT: Version: 1
|
||||
// CHECK-NEXT: Entry: 0x0
|
||||
// CHECK-NEXT: ProgramHeaderOffset: 0x34
|
||||
// CHECK-NEXT: SectionHeaderOffset: 0x2084
|
||||
// CHECK-NEXT: Flags [ (0x0)
|
||||
// CHECK-NEXT: ]
|
||||
// CHECK-NEXT: HeaderSize: 52
|
||||
// CHECK-NEXT: ProgramHeaderEntrySize: 32
|
||||
// CHECK-NEXT: ProgramHeaderCount: 7
|
||||
// CHECK-NEXT: SectionHeaderEntrySize: 40
|
||||
// CHECK-NEXT: SectionHeaderCount: 9
|
||||
// CHECK-NEXT: StringTableSectionIndex: 7
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: Sections [
|
||||
// CHECK-NEXT: Section {
|
||||
// CHECK-NEXT: Index: 0
|
||||
// CHECK-NEXT: Name: (0)
|
||||
// CHECK-NEXT: Type: SHT_NULL (0x0)
|
||||
// CHECK-NEXT: Flags [ (0x0)
|
||||
// CHECK-NEXT: ]
|
||||
// CHECK-NEXT: Address: 0x0
|
||||
// CHECK-NEXT: Offset: 0x0
|
||||
// CHECK-NEXT: Size: 0
|
||||
// CHECK-NEXT: Link: 0
|
||||
// CHECK-NEXT: Info: 0
|
||||
// CHECK-NEXT: AddressAlignment: 0
|
||||
// CHECK-NEXT: EntrySize: 0
|
||||
// CHECK-NEXT: SectionData (
|
||||
// CHECK-NEXT: )
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: Section {
|
||||
// CHECK-NEXT: Index: 1
|
||||
// CHECK-NEXT: Name: .dynsym (1)
|
||||
// CHECK-NEXT: Type: SHT_DYNSYM (0xB)
|
||||
// CHECK-NEXT: Flags [ (0x2)
|
||||
// CHECK-NEXT: SHF_ALLOC (0x2)
|
||||
// CHECK-NEXT: ]
|
||||
// CHECK-NEXT: Address: 0x114
|
||||
// CHECK-NEXT: Offset: 0x114
|
||||
// CHECK-NEXT: Size: 16
|
||||
// CHECK-NEXT: Link: 3
|
||||
// CHECK-NEXT: Info: 1
|
||||
// CHECK-NEXT: AddressAlignment: 4
|
||||
// CHECK-NEXT: EntrySize: 16
|
||||
// CHECK-NEXT: SectionData (
|
||||
// CHECK-NEXT: 0000: 00000000 00000000 00000000 00000000 |................|
|
||||
// CHECK-NEXT: )
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: Section {
|
||||
// CHECK-NEXT: Index: 2
|
||||
// CHECK-NEXT: Name: .hash (9)
|
||||
// CHECK-NEXT: Type: SHT_HASH (0x5)
|
||||
// CHECK-NEXT: Flags [ (0x2)
|
||||
// CHECK-NEXT: SHF_ALLOC (0x2)
|
||||
// CHECK-NEXT: ]
|
||||
// CHECK-NEXT: Address: 0x124
|
||||
// CHECK-NEXT: Offset: 0x124
|
||||
// CHECK-NEXT: Size: 16
|
||||
// CHECK-NEXT: Link: 1
|
||||
// CHECK-NEXT: Info: 0
|
||||
// CHECK-NEXT: AddressAlignment: 4
|
||||
// CHECK-NEXT: EntrySize: 4
|
||||
// CHECK-NEXT: SectionData (
|
||||
// CHECK-NEXT: 0000: 00000001 00000001 00000000 00000000 |................|
|
||||
// CHECK-NEXT: )
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: Section {
|
||||
// CHECK-NEXT: Index: 3
|
||||
// CHECK-NEXT: Name: .dynstr (15)
|
||||
// CHECK-NEXT: Type: SHT_STRTAB (0x3)
|
||||
// CHECK-NEXT: Flags [ (0x2)
|
||||
// CHECK-NEXT: SHF_ALLOC (0x2)
|
||||
// CHECK-NEXT: ]
|
||||
// CHECK-NEXT: Address: 0x134
|
||||
// CHECK-NEXT: Offset: 0x134
|
||||
// CHECK-NEXT: Size: 1
|
||||
// CHECK-NEXT: Link: 0
|
||||
// CHECK-NEXT: Info: 0
|
||||
// CHECK-NEXT: AddressAlignment: 1
|
||||
// CHECK-NEXT: EntrySize: 0
|
||||
// CHECK-NEXT: SectionData (
|
||||
// CHECK-NEXT: 0000: 00 |.|
|
||||
// CHECK-NEXT: )
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: Section {
|
||||
// CHECK-NEXT: Index: 4
|
||||
// CHECK-NEXT: Name: .text (23)
|
||||
// CHECK-NEXT: Type: SHT_PROGBITS (0x1)
|
||||
// CHECK-NEXT: Flags [ (0x6)
|
||||
// CHECK-NEXT: SHF_ALLOC (0x2)
|
||||
// CHECK-NEXT: SHF_EXECINSTR (0x4)
|
||||
// CHECK-NEXT: ]
|
||||
// CHECK-NEXT: Address: 0x1000
|
||||
// CHECK-NEXT: Offset: 0x1000
|
||||
// CHECK-NEXT: Size: 12
|
||||
// CHECK-NEXT: Link: 0
|
||||
// CHECK-NEXT: Info: 0
|
||||
// CHECK-NEXT: AddressAlignment: 4
|
||||
// CHECK-NEXT: EntrySize: 0
|
||||
// CHECK-NEXT: SectionData (
|
||||
// CHECK-NEXT: 0000: 38000001 38600001 44000002 |8...8`..D...|
|
||||
// CHECK-NEXT: )
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: Section {
|
||||
// CHECK-NEXT: Index: 5
|
||||
// CHECK-NEXT: Name: .dynamic (29)
|
||||
// CHECK-NEXT: Type: SHT_DYNAMIC (0x6)
|
||||
// CHECK-NEXT: Flags [ (0x3)
|
||||
// CHECK-NEXT: SHF_ALLOC (0x2)
|
||||
// CHECK-NEXT: SHF_WRITE (0x1)
|
||||
// CHECK-NEXT: ]
|
||||
// CHECK-NEXT: Address: 0x2000
|
||||
// CHECK-NEXT: Offset: 0x2000
|
||||
// CHECK-NEXT: Size: 48
|
||||
// CHECK-NEXT: Link: 3
|
||||
// CHECK-NEXT: Info: 0
|
||||
// CHECK-NEXT: AddressAlignment: 4
|
||||
// CHECK-NEXT: EntrySize: 8
|
||||
// CHECK-NEXT: SectionData (
|
||||
// CHECK-NEXT: 0000: 00000006 00000114 0000000B 00000010 |................|
|
||||
// CHECK-NEXT: 0010: 00000005 00000134 0000000A 00000001 |.......4........|
|
||||
// CHECK-NEXT: 0020: 00000004 00000124 00000000 00000000 |.......$........|
|
||||
// CHECK-NEXT: )
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: Section {
|
||||
// CHECK-NEXT: Index: 6
|
||||
// CHECK-NEXT: Name: .symtab (38)
|
||||
// CHECK-NEXT: Type: SHT_SYMTAB (0x2)
|
||||
// CHECK-NEXT: Flags [ (0x0)
|
||||
// CHECK-NEXT: ]
|
||||
// CHECK-NEXT: Address: 0x0
|
||||
// CHECK-NEXT: Offset: 0x2030
|
||||
// CHECK-NEXT: Size: 16
|
||||
// CHECK-NEXT: Link: 8
|
||||
// CHECK-NEXT: Info: 1
|
||||
// CHECK-NEXT: AddressAlignment: 4
|
||||
// CHECK-NEXT: EntrySize: 16
|
||||
// CHECK-NEXT: SectionData (
|
||||
// CHECK-NEXT: 0000: 00000000 00000000 00000000 00000000 |................|
|
||||
// CHECK-NEXT: )
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: Section {
|
||||
// CHECK-NEXT: Index: 7
|
||||
// CHECK-NEXT: Name: .shstrtab (46)
|
||||
// CHECK-NEXT: Type: SHT_STRTAB (0x3)
|
||||
// CHECK-NEXT: Flags [ (0x0)
|
||||
// CHECK-NEXT: ]
|
||||
// CHECK-NEXT: Address: 0x0
|
||||
// CHECK-NEXT: Offset: 0x2040
|
||||
// CHECK-NEXT: Size: 64
|
||||
// CHECK-NEXT: Link: 0
|
||||
// CHECK-NEXT: Info: 0
|
||||
// CHECK-NEXT: AddressAlignment: 1
|
||||
// CHECK-NEXT: EntrySize: 0
|
||||
// CHECK-NEXT: SectionData (
|
||||
// CHECK-NEXT: 0000: 002E6479 6E73796D 002E6861 7368002E |..dynsym..hash..|
|
||||
// CHECK-NEXT: 0010: 64796E73 7472002E 74657874 002E6479 |dynstr..text..dy|
|
||||
// CHECK-NEXT: 0020: 6E616D69 63002E73 796D7461 62002E73 |namic..symtab..s|
|
||||
// CHECK-NEXT: 0030: 68737472 74616200 2E737472 74616200 |hstrtab..strtab.|
|
||||
// CHECK-NEXT: )
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: Section {
|
||||
// CHECK-NEXT: Index: 8
|
||||
// CHECK-NEXT: Name: .strtab (56)
|
||||
// CHECK-NEXT: Type: SHT_STRTAB (0x3)
|
||||
// CHECK-NEXT: Flags [ (0x0)
|
||||
// CHECK-NEXT: ]
|
||||
// CHECK-NEXT: Address: 0x0
|
||||
// CHECK-NEXT: Offset: 0x2080
|
||||
// CHECK-NEXT: Size: 1
|
||||
// CHECK-NEXT: Link: 0
|
||||
// CHECK-NEXT: Info: 0
|
||||
// CHECK-NEXT: AddressAlignment: 1
|
||||
// CHECK-NEXT: EntrySize: 0
|
||||
// CHECK-NEXT: SectionData (
|
||||
// CHECK-NEXT: 0000: 00 |.|
|
||||
// CHECK-NEXT: )
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: ]
|
||||
// CHECK-NEXT: ProgramHeaders [
|
||||
// CHECK-NEXT: ProgramHeader {
|
||||
// CHECK-NEXT: Type: PT_PHDR (0x6)
|
||||
// CHECK-NEXT: Offset: 0x34
|
||||
// CHECK-NEXT: VirtualAddress: 0x34
|
||||
// CHECK-NEXT: PhysicalAddress: 0x34
|
||||
// CHECK-NEXT: FileSize: 224
|
||||
// CHECK-NEXT: MemSize: 224
|
||||
// CHECK-NEXT: Flags [ (0x4)
|
||||
// CHECK-NEXT: PF_R (0x4)
|
||||
// CHECK-NEXT: ]
|
||||
// CHECK-NEXT: Alignment: 8
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: ProgramHeader {
|
||||
// CHECK-NEXT: Type: PT_LOAD (0x1)
|
||||
// CHECK-NEXT: Offset: 0x0
|
||||
// CHECK-NEXT: VirtualAddress: 0x0
|
||||
// CHECK-NEXT: PhysicalAddress: 0x0
|
||||
// CHECK-NEXT: FileSize: 309
|
||||
// CHECK-NEXT: MemSize: 309
|
||||
// CHECK-NEXT: Flags [ (0x4)
|
||||
// CHECK-NEXT: PF_R (0x4)
|
||||
// CHECK-NEXT: ]
|
||||
// CHECK-NEXT: Alignment: 4096
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: ProgramHeader {
|
||||
// CHECK-NEXT: Type: PT_LOAD (0x1)
|
||||
// CHECK-NEXT: Offset: 0x1000
|
||||
// CHECK-NEXT: VirtualAddress: 0x1000
|
||||
// CHECK-NEXT: PhysicalAddress: 0x1000
|
||||
// CHECK-NEXT: FileSize: 12
|
||||
// CHECK-NEXT: MemSize: 12
|
||||
// CHECK-NEXT: Flags [ (0x5)
|
||||
// CHECK-NEXT: PF_R (0x4)
|
||||
// CHECK-NEXT: PF_X (0x1)
|
||||
// CHECK-NEXT: ]
|
||||
// CHECK-NEXT: Alignment: 4096
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: ProgramHeader {
|
||||
// CHECK-NEXT: Type: PT_LOAD (0x1)
|
||||
// CHECK-NEXT: Offset: 0x2000
|
||||
// CHECK-NEXT: VirtualAddress: 0x2000
|
||||
// CHECK-NEXT: PhysicalAddress: 0x2000
|
||||
// CHECK-NEXT: FileSize: 48
|
||||
// CHECK-NEXT: MemSize: 48
|
||||
// CHECK-NEXT: Flags [ (0x6)
|
||||
// CHECK-NEXT: PF_R (0x4)
|
||||
// CHECK-NEXT: PF_W (0x2)
|
||||
// CHECK-NEXT: ]
|
||||
// CHECK-NEXT: Alignment: 4096
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: ProgramHeader {
|
||||
// CHECK-NEXT: Type: PT_DYNAMIC (0x2)
|
||||
// CHECK-NEXT: Offset: 0x2000
|
||||
// CHECK-NEXT: VirtualAddress: 0x2000
|
||||
// CHECK-NEXT: PhysicalAddress: 0x2000
|
||||
// CHECK-NEXT: FileSize: 48
|
||||
// CHECK-NEXT: MemSize: 48
|
||||
// CHECK-NEXT: Flags [ (0x6)
|
||||
// CHECK-NEXT: PF_R (0x4)
|
||||
// CHECK-NEXT: PF_W (0x2)
|
||||
// CHECK-NEXT: ]
|
||||
// CHECK-NEXT: Alignment: 4
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: ProgramHeader {
|
||||
// CHECK-NEXT: Type: PT_GNU_RELRO (0x6474E552)
|
||||
// CHECK-NEXT: Offset: 0x2000
|
||||
// CHECK-NEXT: VirtualAddress: 0x2000
|
||||
// CHECK-NEXT: PhysicalAddress: 0x2000
|
||||
// CHECK-NEXT: FileSize: 48
|
||||
// CHECK-NEXT: MemSize: 48
|
||||
// CHECK-NEXT: Flags [ (0x4)
|
||||
// CHECK-NEXT: PF_R (0x4)
|
||||
// CHECK-NEXT: ]
|
||||
// CHECK-NEXT: Alignment: 1
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: ProgramHeader {
|
||||
// CHECK-NEXT: Type: PT_GNU_STACK (0x6474E551)
|
||||
// CHECK-NEXT: Offset: 0x0
|
||||
// CHECK-NEXT: VirtualAddress: 0x0
|
||||
// CHECK-NEXT: PhysicalAddress: 0x0
|
||||
// CHECK-NEXT: FileSize: 0
|
||||
// CHECK-NEXT: MemSize: 0
|
||||
// CHECK-NEXT: Flags [ (0x6)
|
||||
// CHECK-NEXT: PF_R (0x4)
|
||||
// CHECK-NEXT: PF_W (0x2)
|
||||
// CHECK-NEXT: ]
|
||||
// CHECK-NEXT: Alignment: 0
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: ]
|
@ -98,7 +98,7 @@ _start:
|
||||
# CHECK-NEXT: }
|
||||
# CHECK-NEXT: Section {
|
||||
# CHECK-NEXT: Index: 4
|
||||
# CHECK-NEXT: Name: .strtab (17)
|
||||
# CHECK-NEXT: Name: .strtab (25)
|
||||
# CHECK-NEXT: Type: SHT_STRTAB (0x3)
|
||||
# CHECK-NEXT: Flags [ (0x0)
|
||||
# CHECK-NEXT: ]
|
||||
|
@ -96,7 +96,7 @@ _start:
|
||||
# CHECK-NEXT: }
|
||||
# CHECK-NEXT: Section {
|
||||
# CHECK-NEXT: Index: 4
|
||||
# CHECK-NEXT: Name: .strtab (17)
|
||||
# CHECK-NEXT: Name: .strtab (25)
|
||||
# CHECK-NEXT: Type: SHT_STRTAB (0x3)
|
||||
# CHECK-NEXT: Flags [ (0x0)
|
||||
# CHECK-NEXT: ]
|
||||
|
@ -177,7 +177,7 @@ _start:
|
||||
# CHECK-NEXT: }
|
||||
# CHECK-NEXT: Section {
|
||||
# CHECK-NEXT: Index: 7
|
||||
# CHECK-NEXT: Name: .strtab (27)
|
||||
# CHECK-NEXT: Name: .strtab (41)
|
||||
# CHECK-NEXT: Type: SHT_STRTAB (0x3)
|
||||
# CHECK-NEXT: Flags [ (0x0)
|
||||
# CHECK-NEXT: ]
|
||||
|
@ -20,8 +20,8 @@
|
||||
// CHECK-NEXT: AddressAlignment:
|
||||
// CHECK-NEXT: EntrySize:
|
||||
// CHECK-NEXT: SectionData (
|
||||
// CHECK-NEXT: 0000: 002E4C6D 79766172 002E4C6D 796F7468 |..Lmyvar..Lmyoth|
|
||||
// CHECK-NEXT: 0010: 65727661 7200 |ervar.|
|
||||
// CHECK-NEXT: 0000: 002E4C6D 796F7468 65727661 72002E4C |..Lmyothervar..L|
|
||||
// CHECK-NEXT: 0010: 6D797661 7200 |myvar.|
|
||||
// CHECK-NEXT: )
|
||||
// CHECK-NEXT: }
|
||||
|
||||
|
@ -22,7 +22,7 @@
|
||||
# SEC-DEFAULT: 4 .bss 00000002 {{[0-9a-f]*}} BSS
|
||||
# SEC-DEFAULT: 5 .shstrtab 00000002 {{[0-9a-f]*}}
|
||||
# SEC-DEFAULT: 6 .symtab 00000030 {{[0-9a-f]*}}
|
||||
# SEC-DEFAULT: 7 .shstrtab 00000032 {{[0-9a-f]*}}
|
||||
# SEC-DEFAULT: 7 .shstrtab 0000003c {{[0-9a-f]*}}
|
||||
# SEC-DEFAULT: 8 .strtab 00000008 {{[0-9a-f]*}}
|
||||
|
||||
# Sections are put in order specified in linker script.
|
||||
@ -42,7 +42,7 @@
|
||||
# SEC-ORDER: 1 .bss 00000002 {{[0-9a-f]*}} BSS
|
||||
# SEC-ORDER: 2 other 00000003 {{[0-9a-f]*}} DATA
|
||||
# SEC-ORDER: 3 .shstrtab 00000002 {{[0-9a-f]*}}
|
||||
# SEC-ORDER: 4 .shstrtab 00000032 {{[0-9a-f]*}}
|
||||
# SEC-ORDER: 4 .shstrtab 0000003c {{[0-9a-f]*}}
|
||||
# SEC-ORDER: 5 .symtab 00000030 {{[0-9a-f]*}}
|
||||
# SEC-ORDER: 6 .strtab 00000008 {{[0-9a-f]*}}
|
||||
# SEC-ORDER: 7 .data 00000020 {{[0-9a-f]*}} DATA
|
||||
@ -63,7 +63,7 @@
|
||||
# SEC-SWAP-NAMES: 4 .bss 00000002 {{[0-9a-f]*}} BSS
|
||||
# SEC-SWAP-NAMES: 5 .shstrtab 00000002 {{[0-9a-f]*}}
|
||||
# SEC-SWAP-NAMES: 6 .symtab 00000030 {{[0-9a-f]*}}
|
||||
# SEC-SWAP-NAMES: 7 .shstrtab 00000032 {{[0-9a-f]*}}
|
||||
# SEC-SWAP-NAMES: 7 .shstrtab 0000003c {{[0-9a-f]*}}
|
||||
# SEC-SWAP-NAMES: 8 .strtab 00000008 {{[0-9a-f]*}}
|
||||
|
||||
# .shstrtab from the input object file is discarded.
|
||||
@ -100,7 +100,7 @@
|
||||
# SEC-MULTI: 3 .bss 00000002 {{[0-9a-f]*}} BSS
|
||||
# SEC-MULTI: 4 .shstrtab 00000002 {{[0-9a-f]*}}
|
||||
# SEC-MULTI: 5 .symtab 00000030 {{[0-9a-f]*}}
|
||||
# SEC-MULTI: 6 .shstrtab 0000002c {{[0-9a-f]*}}
|
||||
# SEC-MULTI: 6 .shstrtab 00000036 {{[0-9a-f]*}}
|
||||
# SEC-MULTI: 7 .strtab 00000008 {{[0-9a-f]*}}
|
||||
|
||||
.globl _start;
|
||||
|
34
test/ELF/mips-gp-disp.s
Normal file
34
test/ELF/mips-gp-disp.s
Normal file
@ -0,0 +1,34 @@
|
||||
# Check that even if _gp_disp symbol is defined in the shared library
|
||||
# we use our own value.
|
||||
|
||||
# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o
|
||||
# RUN: ld.lld -shared -o %t.so %t.o %S/Inputs/mips-gp-disp.so
|
||||
# RUN: llvm-readobj -symbols %t.so | FileCheck -check-prefix=INT-SO %s
|
||||
# RUN: llvm-readobj -symbols %S/Inputs/mips-gp-disp.so \
|
||||
# RUN: | FileCheck -check-prefix=EXT-SO %s
|
||||
# RUN: llvm-objdump -d -t %t.so | FileCheck -check-prefix=DIS %s
|
||||
# RUN: llvm-readobj -relocations %t.so | FileCheck -check-prefix=REL %s
|
||||
|
||||
# REQUIRES: mips
|
||||
|
||||
# INT-SO-NOT: Name: _gp_disp
|
||||
|
||||
# EXT-SO: Name: _gp_disp
|
||||
# EXT-SO-NEXT: Value: 0x20010
|
||||
|
||||
# DIS: Disassembly of section .text:
|
||||
# DIS-NEXT: __start:
|
||||
# DIS-NEXT: 10000: 3c 08 00 01 lui $8, 1
|
||||
# DIS-NEXT: 10004: 21 08 7f f0 addi $8, $8, 32752
|
||||
# ^-- 0x37ff0 & 0xffff
|
||||
# DIS: 00027ff0 *ABS* 00000000 _gp
|
||||
|
||||
# REL: Relocations [
|
||||
# REL-NEXT: ]
|
||||
|
||||
.text
|
||||
.globl __start
|
||||
__start:
|
||||
lui $t0,%hi(_gp_disp)
|
||||
addi $t0,$t0,%lo(_gp_disp)
|
||||
lw $v0,%call16(_foo)($gp)
|
30
test/ELF/ppc-relocs.s
Normal file
30
test/ELF/ppc-relocs.s
Normal file
@ -0,0 +1,30 @@
|
||||
# RUN: llvm-mc -filetype=obj -triple=powerpc-unknown-freebsd %s -o %t
|
||||
# RUN: ld.lld %t -o %t2
|
||||
# RUN: llvm-objdump -d %t2 | FileCheck %s
|
||||
# REQUIRES: ppc
|
||||
|
||||
.section .R_PPC_ADDR16_HA,"ax",@progbits
|
||||
.globl _start
|
||||
_start:
|
||||
lis 4, msg@ha
|
||||
msg:
|
||||
.string "foo"
|
||||
len = . - msg
|
||||
|
||||
# CHECK: Disassembly of section .R_PPC_ADDR16_HA:
|
||||
# CHECK: _start:
|
||||
# CHECK: 11000: 3c 80 00 01 lis 4, 1
|
||||
# CHECK: msg:
|
||||
# CHECK: 11004: 66 6f 6f 00 oris 15, 19, 28416
|
||||
|
||||
.section .R_PPC_ADDR16_LO,"ax",@progbits
|
||||
addi 4, 4, msg@l
|
||||
mystr:
|
||||
.asciz "blah"
|
||||
len = . - mystr
|
||||
|
||||
# CHECK: Disassembly of section .R_PPC_ADDR16_LO:
|
||||
# CHECK: .R_PPC_ADDR16_LO:
|
||||
# CHECK: 11008: 38 84 10 04 addi 4, 4, 4100
|
||||
# CHECK: mystr:
|
||||
# CHECK: 1100c: 62 6c 61 68 ori 12, 19, 24936
|
@ -2,18 +2,19 @@
|
||||
// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
|
||||
// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/relocation-copy.s -o %t2.o
|
||||
// RUN: ld.lld -shared %t2.o -o %t.so
|
||||
// RUN: ld.lld -e main %t.o %t.so -o %t3
|
||||
// RUN: ld.lld %t.o %t.so -o %t3
|
||||
// RUN: llvm-readobj -s -r --expand-relocs %t3 | FileCheck %s
|
||||
// RUN: llvm-objdump -d %t3 | FileCheck -check-prefix=CODE %s
|
||||
|
||||
.text
|
||||
.globl main
|
||||
.align 16, 0x90
|
||||
.type main,@function
|
||||
main:
|
||||
.global _start
|
||||
_start:
|
||||
movl $5, x
|
||||
movl $7, y
|
||||
movl $9, z
|
||||
movl $x, %edx
|
||||
movl $y, %edx
|
||||
movl $z, %edx
|
||||
|
||||
// CHECK: Name: .bss
|
||||
// CHECK-NEXT: Type: SHT_NOBITS (0x8)
|
||||
@ -57,7 +58,10 @@ movl $9, z
|
||||
// 77840 = 0x13000 + 16
|
||||
// 77844 = 0x13000 + 16 + 4
|
||||
// CODE: Disassembly of section .text:
|
||||
// CODE-NEXT: main:
|
||||
// CODE-NEXT: _start:
|
||||
// CODE-NEXT: 11000: c7 04 25 00 30 01 00 05 00 00 00 movl $5, 77824
|
||||
// CODE-NEXT: 1100b: c7 04 25 10 30 01 00 07 00 00 00 movl $7, 77840
|
||||
// CODE-NEXT: 11016: c7 04 25 14 30 01 00 09 00 00 00 movl $9, 77844
|
||||
// CODE-NEXT: 11021: ba 00 30 01 00 movl $77824, %edx
|
||||
// CODE-NEXT: 11026: ba 10 30 01 00 movl $77840, %edx
|
||||
// CODE-NEXT: 1102b: ba 14 30 01 00 movl $77844, %edx
|
||||
|
@ -58,9 +58,10 @@ _start:
|
||||
// CHECK-NEXT: AddressAlignment: 1
|
||||
// CHECK-NEXT: EntrySize: 0
|
||||
// CHECK-NEXT: SectionData (
|
||||
// CHECK-NEXT: 0000: 002E7465 78740066 6F6F6261 72002E73 |..text.foobar..s|
|
||||
// CHECK-NEXT: 0010: 68737472 74616200 2E737472 74616200 |hstrtab..strtab.|
|
||||
// CHECK-NEXT: 0020: 2E73796D 74616200 |.symtab.|
|
||||
// CHECK-NEXT: 0000: 00626172 002E7465 78740066 6F6F6261 |.bar..text.fooba|
|
||||
// CHECK-NEXT: 0010: 7200666F 6F626172 00666F6F 62617200 |r.foobar.foobar.|
|
||||
// CHECK-NEXT: 0020: 2E73796D 74616200 2E736873 74727461 |.symtab..shstrta|
|
||||
// CHECK-NEXT: 0030: 62002E73 74727461 6200 |b..strtab.|
|
||||
// CHECK-NEXT: )
|
||||
// CHECK-NEXT:}
|
||||
// CHECK: Name: .strtab
|
||||
@ -75,6 +76,6 @@ _start:
|
||||
// CHECK-NEXT: AddressAlignment: 1
|
||||
// CHECK-NEXT: EntrySize: 0
|
||||
// CHECK-NEXT: SectionData (
|
||||
// CHECK-NEXT: 0000: 005F7374 61727400 666F6F62 617200 |._start.foobar.|
|
||||
// CHECK-NEXT: 0000: 00666F6F 62617200 5F737461 727400 |.foobar._start.|
|
||||
// CHECK-NEXT: )
|
||||
// CHECK-NEXT: }
|
||||
|
19
test/ELF/wrap.s
Normal file
19
test/ELF/wrap.s
Normal file
@ -0,0 +1,19 @@
|
||||
// REQUIRES: x86
|
||||
// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
|
||||
// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/wrap.s -o %t2
|
||||
|
||||
// RUN: ld.lld -o %t3 %t %t2 -wrap foo -wrap nosuchsym
|
||||
// RUN: llvm-objdump -d -print-imm-hex %t3 | FileCheck %s
|
||||
// RUN: ld.lld -o %t3 %t %t2 --wrap foo -wrap=nosuchsym
|
||||
// RUN: llvm-objdump -d -print-imm-hex %t3 | FileCheck %s
|
||||
|
||||
// CHECK: _start:
|
||||
// CHECK-NEXT: movl $0x11010, %edx
|
||||
// CHECK-NEXT: movl $0x11010, %edx
|
||||
// CHECK-NEXT: movl $0x11000, %edx
|
||||
|
||||
.global _start
|
||||
_start:
|
||||
movl $foo, %edx
|
||||
movl $__wrap_foo, %edx
|
||||
movl $__real_foo, %edx
|
@ -227,6 +227,8 @@ if re.search(r'X86', archs):
|
||||
config.available_features.add('x86')
|
||||
if re.search(r'PowerPC', archs):
|
||||
config.available_features.add('ppc')
|
||||
if re.search(r'AMDGPU', archs):
|
||||
config.available_features.add('amdgpu')
|
||||
llvm_config_cmd.wait()
|
||||
|
||||
# Check if Windows resource file compiler exists.
|
||||
|
@ -7,7 +7,7 @@
|
||||
# We don't emit these in to the binary as relocations, so we need to
|
||||
# make sure that the offset in the FDE to the CIE is the correct value.
|
||||
# CHECK: {{[0-9abcdef]*}} 10000000 00000000 017a5200 01781e01
|
||||
# CHECK: {{[0-9abcdef]*}} 100c1f00 20000000 18000000 e4ffffff
|
||||
# CHECK: {{[0-9abcdef]*}} 100c1f00 20000000 18000000 b8ffffff
|
||||
# Note, this one that matters ^~~~~~~~
|
||||
# It needs to be 0x18 as that is the offset back to 0 where the CIE is.
|
||||
# CHECK: {{[0-9abcdef]*}} ffffffff 20000000 00000000 00480e10
|
||||
@ -84,7 +84,7 @@ sections:
|
||||
content: [ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x01, 0x7A, 0x52, 0x00, 0x01, 0x78, 0x1E, 0x01,
|
||||
0x10, 0x0C, 0x1F, 0x00, 0x20, 0x00, 0x00, 0x00,
|
||||
0x18, 0x00, 0x00, 0x00, 0xE4, 0xFF, 0xFF, 0xFF,
|
||||
0x18, 0x00, 0x00, 0x00, 0x94, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x20, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x0E, 0x10,
|
||||
0x9E, 0x01, 0x9D, 0x02, 0x00, 0x00, 0x00, 0x00 ]
|
||||
|
208
test/mach-o/do-not-emit-unwind-fde-arm64.yaml
Normal file
208
test/mach-o/do-not-emit-unwind-fde-arm64.yaml
Normal file
@ -0,0 +1,208 @@
|
||||
# RUN: lld -flavor darwin -arch arm64 -r -print_atoms %s -o %t | FileCheck %s
|
||||
# RUN: lld -flavor darwin -arch arm64 -r -print_atoms %t -o %t2 | FileCheck %s
|
||||
# RUN: llvm-objdump -r -s -section="__eh_frame" -macho %t | FileCheck -check-prefix=CODE %s
|
||||
# RUN: llvm-objdump -r -s -section="__eh_frame" -macho %t2 | FileCheck -check-prefix=CODE %s
|
||||
|
||||
|
||||
--- !mach-o
|
||||
arch: arm64
|
||||
file-type: MH_OBJECT
|
||||
flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
|
||||
compat-version: 0.0
|
||||
current-version: 0.0
|
||||
has-UUID: false
|
||||
OS: unknown
|
||||
sections:
|
||||
- segment: __TEXT
|
||||
section: __text
|
||||
type: S_REGULAR
|
||||
attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
|
||||
alignment: 4
|
||||
address: 0x0000000000000000
|
||||
content: [ 0xFD, 0x7B, 0xBF, 0xA9, 0xFD, 0x03, 0x00, 0x91,
|
||||
0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x91,
|
||||
0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x80, 0x52,
|
||||
0xFD, 0x7B, 0xC1, 0xA8, 0xC0, 0x03, 0x5F, 0xD6 ]
|
||||
relocations:
|
||||
- offset: 0x00000010
|
||||
type: ARM64_RELOC_BRANCH26
|
||||
length: 2
|
||||
pc-rel: true
|
||||
extern: true
|
||||
symbol: 9
|
||||
- offset: 0x0000000C
|
||||
type: ARM64_RELOC_PAGEOFF12
|
||||
length: 2
|
||||
pc-rel: false
|
||||
extern: true
|
||||
symbol: 1
|
||||
- offset: 0x00000008
|
||||
type: ARM64_RELOC_PAGE21
|
||||
length: 2
|
||||
pc-rel: true
|
||||
extern: true
|
||||
symbol: 1
|
||||
- segment: __TEXT
|
||||
section: __cstring
|
||||
type: S_CSTRING_LITERALS
|
||||
attributes: [ ]
|
||||
address: 0x0000000000000020
|
||||
content: [ 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77, 0x6F,
|
||||
0x72, 0x6C, 0x64, 0x00 ]
|
||||
- segment: __LD
|
||||
section: __compact_unwind
|
||||
type: S_REGULAR
|
||||
attributes: [ ]
|
||||
alignment: 8
|
||||
address: 0x0000000000000030
|
||||
content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
|
||||
relocations:
|
||||
- offset: 0x00000000
|
||||
type: ARM64_RELOC_UNSIGNED
|
||||
length: 3
|
||||
pc-rel: false
|
||||
extern: false
|
||||
symbol: 1
|
||||
- segment: __TEXT
|
||||
section: __eh_frame
|
||||
type: S_COALESCED
|
||||
attributes: [ ]
|
||||
alignment: 8
|
||||
address: 0x0000000000000050
|
||||
content: [ 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x01, 0x7A, 0x50, 0x4C, 0x52, 0x00, 0x01, 0x78,
|
||||
0x1E, 0x0B, 0x00, 0xED, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x00, 0x10, 0x0C, 0x1F, 0x00,
|
||||
0x24, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
|
||||
0x88, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x08, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x48, 0x0E, 0x10, 0x9E, 0x01, 0x9D, 0x02 ]
|
||||
- segment: __TEXT
|
||||
section: __gcc_except_tab
|
||||
type: S_REGULAR
|
||||
attributes: [ ]
|
||||
address: 0x00000000000000A0
|
||||
content: [ 0x00, 0x00, 0x00, 0x00 ]
|
||||
local-symbols:
|
||||
- name: ltmp0
|
||||
type: N_SECT
|
||||
sect: 1
|
||||
value: 0x0000000000000000
|
||||
- name: L_str
|
||||
type: N_SECT
|
||||
sect: 2
|
||||
value: 0x0000000000000020
|
||||
- name: ltmp1
|
||||
type: N_SECT
|
||||
sect: 2
|
||||
value: 0x0000000000000020
|
||||
- name: ltmp2
|
||||
type: N_SECT
|
||||
sect: 3
|
||||
value: 0x0000000000000030
|
||||
- name: ltmp3
|
||||
type: N_SECT
|
||||
sect: 4
|
||||
value: 0x0000000000000050
|
||||
- name: ltmp4
|
||||
type: N_SECT
|
||||
sect: 4
|
||||
value: 0x0000000000000070
|
||||
global-symbols:
|
||||
- name: __Z3fooi
|
||||
type: N_SECT
|
||||
scope: [ N_EXT ]
|
||||
sect: 1
|
||||
value: 0x0000000000000000
|
||||
undefined-symbols:
|
||||
- name: __gxx_personality_v0
|
||||
type: N_UNDF
|
||||
scope: [ N_EXT ]
|
||||
value: 0x0000000000000000
|
||||
- name: _bar
|
||||
type: N_UNDF
|
||||
scope: [ N_EXT ]
|
||||
value: 0x0000000000000000
|
||||
- name: _puts
|
||||
type: N_UNDF
|
||||
scope: [ N_EXT ]
|
||||
value: 0x0000000000000000
|
||||
page-size: 0x00000000
|
||||
|
||||
# CHECK: defined-atoms:
|
||||
# CHECK: - ref-name: L{{[0-9]*}}
|
||||
# CHECK: scope: hidden
|
||||
# CHECK: type: c-string
|
||||
# CHECK: content: [ 48, 65, 6C, 6C, 6F, 20, 77, 6F, 72, 6C, 64, 00 ]
|
||||
# CHECK: merge: by-content
|
||||
# CHECK: - ref-name: L{{[0-9]*}}
|
||||
# CHECK: type: unwind-cfi
|
||||
# CHECK: content: [ 1C, 00, 00, 00, 00, 00, 00, 00, 01, 7A, 50, 4C,
|
||||
# CHECK: 52, 00, 01, 78, 1E, 0B, 00, ED, FF, FF, FF, FF,
|
||||
# CHECK: FF, FF, FF, 00, 10, 0C, 1F, 00 ]
|
||||
# CHECK: - type: unwind-cfi
|
||||
# CHECK: content: [ 24, 00, 00, 00, 24, 00, 00, 00, {{..}}, {{..}}, {{..}}, {{..}},
|
||||
# CHECK: {{..}}, {{..}}, {{..}}, {{..}}, 20, 00, 00, 00, 00, 00, 00, 00,
|
||||
# CHECK: 08, {{..}}, {{..}}, {{..}}, {{..}}, {{..}}, {{..}}, {{..}}, {{..}}, 48, 0E, 10,
|
||||
# CHECK: 9E, 01, 9D, 02 ]
|
||||
# CHECK: references:
|
||||
# CHECK: - kind: negDelta32
|
||||
# CHECK: offset: 4
|
||||
# CHECK: target: L{{[0-9]*}}
|
||||
# CHECK: - kind: unwindFDEToFunction
|
||||
# CHECK: offset: 8
|
||||
# CHECK: target: __Z3fooi
|
||||
# CHECK: - kind: unwindFDEToFunction
|
||||
# CHECK: offset: 25
|
||||
# CHECK: target: L{{[0-9]*}}
|
||||
# CHECK: - ref-name: L{{[0-9]*}}
|
||||
# CHECK: type: unwind-lsda
|
||||
# CHECK: content: [ 00, 00, 00, 00 ]
|
||||
# CHECK: - type: compact-unwind
|
||||
# CHECK: content: [ 00, 00, 00, 00, 00, 00, 00, 00, 20, 00, 00, 00,
|
||||
# CHECK: 00, 00, 00, 03, 00, 00, 00, 00, 00, 00, 00, 00,
|
||||
# CHECK: 00, 00, 00, 00, 00, 00, 00, 00 ]
|
||||
# CHECK: alignment: 8
|
||||
# CHECK: references:
|
||||
# CHECK: - kind: pointer64
|
||||
# CHECK: offset: 0
|
||||
# CHECK: target: __Z3fooi
|
||||
# CHECK: - name: __Z3fooi
|
||||
# CHECK: scope: global
|
||||
# CHECK: content: [ FD, 7B, BF, A9, FD, 03, 00, 91, 00, 00, 00, 90,
|
||||
# CHECK: 00, 00, 00, 91, 00, 00, 00, 94, 00, 00, 80, 52,
|
||||
# CHECK: FD, 7B, C1, A8, C0, 03, 5F, D6 ]
|
||||
# CHECK: alignment: 4
|
||||
# CHECK: references:
|
||||
# CHECK: - kind: page21
|
||||
# CHECK: offset: 8
|
||||
# CHECK: target: L{{[0-9]*}}
|
||||
# CHECK: - kind: offset12
|
||||
# CHECK: offset: 12
|
||||
# CHECK: target: L{{[0-9]*}}
|
||||
# CHECK: - kind: branch26
|
||||
# CHECK: offset: 16
|
||||
# CHECK: target: _puts
|
||||
|
||||
# Make sure we don't have any relocations in the __eh_frame section
|
||||
# CODE-NOT: RELOCATION RECORDS FOR [__eh_frame]
|
||||
|
||||
# Also make sure the reloc for the FDE->function is the correct offset
|
||||
# It should be the offset from the fixup location back to the address
|
||||
# of the function we are referencing
|
||||
# CODE: Contents of section __eh_frame:
|
||||
# This is the CIE:
|
||||
# CODE-NEXT: {{[0-9abcdef]*}} 1c000000 00000000 017a504c 52000178
|
||||
# CODE-NEXT: {{[0-9abcdef]*}} 1e0b00ed ffffffff ffffff00 100c1f00
|
||||
# This is the FDE:
|
||||
# CODE-NEXT: {{[0-9abcdef]*}} 24000000 24000000 a8ffffff ffffffff
|
||||
# This is the important offset for FDE->func ^~~~~~~~ ~~~~~~~~
|
||||
|
||||
# CODE-NEXT: {{[0-9abcdef]*}} 20000000 00000000 08c3ffff ffffffff
|
||||
# And this is the offset for FDE->lsda ^~~~~~~~ ~~~~~~
|
||||
# CODE-NEXT: {{[0-9abcdef]*}} ff480e10 9e019d02
|
||||
# And this byte ^~
|
@ -16,11 +16,18 @@ arch: arm64
|
||||
file-type: MH_OBJECT
|
||||
flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
|
||||
sections:
|
||||
- segment: __TEXT
|
||||
section: __text
|
||||
type: S_REGULAR
|
||||
attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
|
||||
alignment: 4
|
||||
address: 0x0000000000000000
|
||||
content: [ 0xC0, 0x03, 0x5F, 0xD6 ]
|
||||
- segment: __DATA
|
||||
section: __data
|
||||
type: S_REGULAR
|
||||
attributes: [ ]
|
||||
address: 0x0000000000000000
|
||||
address: 0x0000000000000004
|
||||
content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
@ -28,7 +35,7 @@ sections:
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xDC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xC0, 0xFF, 0xFF, 0xFF, 0xBE, 0xFF, 0xFF, 0xFF,
|
||||
0xB0, 0xFF, 0xFF, 0xFF ]
|
||||
@ -38,107 +45,114 @@ sections:
|
||||
length: 2
|
||||
pc-rel: true
|
||||
extern: true
|
||||
symbol: 1
|
||||
symbol: 2
|
||||
- offset: 0x0000004C
|
||||
type: ARM64_RELOC_SUBTRACTOR
|
||||
length: 2
|
||||
pc-rel: false
|
||||
extern: true
|
||||
symbol: 1
|
||||
symbol: 2
|
||||
- offset: 0x0000004C
|
||||
type: ARM64_RELOC_UNSIGNED
|
||||
length: 2
|
||||
pc-rel: false
|
||||
extern: true
|
||||
symbol: 1
|
||||
symbol: 2
|
||||
- offset: 0x00000048
|
||||
type: ARM64_RELOC_SUBTRACTOR
|
||||
length: 2
|
||||
pc-rel: false
|
||||
extern: true
|
||||
symbol: 1
|
||||
symbol: 2
|
||||
- offset: 0x00000048
|
||||
type: ARM64_RELOC_UNSIGNED
|
||||
length: 2
|
||||
pc-rel: false
|
||||
extern: true
|
||||
symbol: 1
|
||||
symbol: 2
|
||||
- offset: 0x00000040
|
||||
type: ARM64_RELOC_UNSIGNED
|
||||
length: 3
|
||||
pc-rel: false
|
||||
extern: true
|
||||
symbol: 1
|
||||
symbol: 2
|
||||
- offset: 0x00000038
|
||||
type: ARM64_RELOC_UNSIGNED
|
||||
length: 3
|
||||
pc-rel: false
|
||||
extern: false
|
||||
symbol: 1
|
||||
symbol: 2
|
||||
- offset: 0x00000030
|
||||
type: ARM64_RELOC_SUBTRACTOR
|
||||
length: 3
|
||||
pc-rel: false
|
||||
extern: true
|
||||
symbol: 1
|
||||
symbol: 2
|
||||
- offset: 0x00000030
|
||||
type: ARM64_RELOC_UNSIGNED
|
||||
length: 3
|
||||
pc-rel: false
|
||||
extern: true
|
||||
symbol: 1
|
||||
symbol: 2
|
||||
- offset: 0x00000028
|
||||
type: ARM64_RELOC_SUBTRACTOR
|
||||
length: 3
|
||||
pc-rel: false
|
||||
extern: true
|
||||
symbol: 1
|
||||
symbol: 2
|
||||
- offset: 0x00000028
|
||||
type: ARM64_RELOC_UNSIGNED
|
||||
length: 3
|
||||
pc-rel: false
|
||||
extern: true
|
||||
symbol: 1
|
||||
symbol: 2
|
||||
- offset: 0x00000020
|
||||
type: ARM64_RELOC_SUBTRACTOR
|
||||
length: 3
|
||||
pc-rel: false
|
||||
extern: true
|
||||
symbol: 1
|
||||
symbol: 2
|
||||
- offset: 0x00000020
|
||||
type: ARM64_RELOC_UNSIGNED
|
||||
length: 3
|
||||
pc-rel: false
|
||||
extern: true
|
||||
symbol: 1
|
||||
symbol: 2
|
||||
- offset: 0x00000018
|
||||
type: ARM64_RELOC_POINTER_TO_GOT
|
||||
length: 3
|
||||
pc-rel: false
|
||||
extern: true
|
||||
symbol: 1
|
||||
symbol: 2
|
||||
- offset: 0x00000010
|
||||
type: ARM64_RELOC_UNSIGNED
|
||||
length: 3
|
||||
pc-rel: false
|
||||
extern: true
|
||||
symbol: 1
|
||||
symbol: 2
|
||||
- offset: 0x00000008
|
||||
type: ARM64_RELOC_UNSIGNED
|
||||
length: 3
|
||||
pc-rel: false
|
||||
extern: true
|
||||
symbol: 1
|
||||
symbol: 2
|
||||
local-symbols:
|
||||
- name: _v1
|
||||
type: N_SECT
|
||||
sect: 2
|
||||
value: 0x000000000000000C
|
||||
global-symbols:
|
||||
- name: _bar
|
||||
type: N_SECT
|
||||
scope: [ N_EXT ]
|
||||
sect: 1
|
||||
value: 0x0000000000000008
|
||||
value: 0x0000000000000000
|
||||
undefined-symbols:
|
||||
- name: _foo
|
||||
type: N_UNDF
|
||||
scope: [ N_EXT ]
|
||||
value: 0x0000000000000000
|
||||
page-size: 0x00000000
|
||||
...
|
||||
|
||||
# CHECK: defined-atoms:
|
||||
@ -151,9 +165,9 @@ undefined-symbols:
|
||||
# CHECK: 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
|
||||
# CHECK: 00, 00, 00, 00, 00, 00, 00, 00, E0, FF, FF, FF,
|
||||
# CHECK: FF, FF, FF, FF, DC, FF, FF, FF, FF, FF, FF, FF,
|
||||
# CHECK: 00, 00, 00, 00, 00, 00, 00, 00, 04, 00, 00, 00,
|
||||
# CHECK: {{..}}, {{..}}, 00, 00, 00, 00, 00, 00, 04, 00, 00, 00,
|
||||
# CHECK: 00, 00, 00, 00, C0, FF, FF, FF, BE, FF, FF, FF,
|
||||
# CHECK: B0, FF, FF, FF ]
|
||||
# CHECK: {{B0|B8}}, {{..}}, FF, FF ]
|
||||
# CHECK: references:
|
||||
# CHECK: - kind: pointer64
|
||||
# CHECK: offset: 0
|
||||
@ -199,11 +213,19 @@ undefined-symbols:
|
||||
# CHECK: offset: 72
|
||||
# CHECK: target: _foo
|
||||
# CHECK-NOT: addend:
|
||||
# CHECK: - name: _bar
|
||||
# CHECK: scope: global
|
||||
# CHECK: content: [ C0, 03, 5F, D6 ]
|
||||
# CHECK: alignment: 4
|
||||
# CHECK: undefined-atoms:
|
||||
# CHECK: - name: _foo
|
||||
|
||||
|
||||
|
||||
# .subsections_via_symbols
|
||||
# .text
|
||||
# .globl_foo
|
||||
# .align2
|
||||
# _foo:
|
||||
# ret
|
||||
# .data
|
||||
#Lanon:
|
||||
# .quad 0
|
||||
|
@ -1,53 +0,0 @@
|
||||
# RUN: yaml2obj -format=elf %s > %t.obj
|
||||
# RUN: lld -flavor old-gnu -target amdgcn--hsa %t.obj -o %t.exe --noinhibit-exec
|
||||
# RUN: llvm-readobj -h -program-headers -s -symbols %t.exe | FileCheck %s
|
||||
|
||||
# CHECK: ElfHeader {
|
||||
# CHECK: Ident {
|
||||
# CHECK: Class: 64-bit (0x2)
|
||||
# CHECK: DataEncoding: LittleEndian (0x1)
|
||||
# CHECK: Machine: EM_AMDGPU (0xE0)
|
||||
|
||||
|
||||
# CHECK: Section {
|
||||
# CHECK: Name: .hsatext
|
||||
# CHECK: Type: SHT_PROGBITS (0x1)
|
||||
# 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: Symbol {
|
||||
# CHECK: Name: kernel
|
||||
# CHECK: Value: 0x0
|
||||
# CHECK: Binding: Local (0x0)
|
||||
# CHECK: Type: AMDGPU_HSA_KERNEL (0xA)
|
||||
|
||||
# CHECK: ProgramHeader {
|
||||
# CHECK: Type: PT_AMDGPU_HSA_LOAD_CODE_AGENT (0x60000003)
|
||||
|
||||
---
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
OSABI: ELFOSABI_GNU
|
||||
Type: ET_REL
|
||||
Machine: EM_AMDGPU
|
||||
Sections:
|
||||
- Name: .hsatext
|
||||
Type: SHT_PROGBITS
|
||||
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
|
||||
AddressAlign: 0x0000000000000004
|
||||
Content: ''
|
||||
- Name: .note
|
||||
Type: SHT_NOTE
|
||||
AddressAlign: 0x0000000000000001
|
||||
Content: '00'
|
||||
Symbols:
|
||||
Local:
|
||||
- Name: kernel
|
||||
Type: STT_GNU_IFUNC
|
||||
Section: .hsatext
|
||||
...
|
Loading…
x
Reference in New Issue
Block a user