Vendor import of lld trunk r257626:

https://llvm.org/svn/llvm-project/lld/trunk@257626
This commit is contained in:
Dimitry Andric 2016-01-13 20:06:04 +00:00
parent fba2c04f31
commit b289257c7f
93 changed files with 2027 additions and 850 deletions

View File

@ -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)

View File

@ -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

View File

@ -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());

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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() {

View File

@ -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

View File

@ -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";

View File

@ -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;

View File

@ -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);

View 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;

View File

@ -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) {

View File

@ -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>

View File

@ -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

View File

@ -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();
}

View File

@ -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> *);

View File

@ -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.

View File

@ -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 {

View File

@ -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.

View File

@ -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)

View File

@ -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

View File

@ -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>;

View File

@ -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>

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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
)

View File

@ -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
)

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -1,4 +1,4 @@
add_llvm_library(lldAArch64ELFTarget
add_lld_library(lldAArch64ELFTarget
AArch64LinkingContext.cpp
AArch64TargetHandler.cpp
AArch64RelocationHandler.cpp

View File

@ -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();
}

View File

@ -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

View File

@ -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 &registry) {
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

View File

@ -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

View File

@ -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();
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
)

View File

@ -1,4 +1,4 @@
add_llvm_library(lldARMELFTarget
add_lld_library(lldARMELFTarget
ARMLinkingContext.cpp
ARMTargetHandler.cpp
ARMRelocationHandler.cpp

View File

@ -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)

View File

@ -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");
}

View File

@ -1,4 +1,4 @@
add_llvm_library(lldHexagonELFTarget
add_lld_library(lldHexagonELFTarget
HexagonLinkingContext.cpp
HexagonRelocationHandler.cpp
HexagonTargetHandler.cpp

View File

@ -1,4 +1,4 @@
add_llvm_library(lldMipsELFTarget
add_lld_library(lldMipsELFTarget
MipsAbiInfoHandler.cpp
MipsCtorsOrderPass.cpp
MipsELFFile.cpp

View File

@ -1,4 +1,4 @@
add_llvm_library(lldX86ELFTarget
add_lld_library(lldX86ELFTarget
X86LinkingContext.cpp
X86TargetHandler.cpp
X86RelocationHandler.cpp

View File

@ -1,4 +1,4 @@
add_llvm_library(lldX86_64ELFTarget
add_lld_library(lldX86_64ELFTarget
X86_64LinkingContext.cpp
X86_64TargetHandler.cpp
X86_64RelocationHandler.cpp

View File

@ -1,4 +1,4 @@
add_llvm_library(lldExampleSubTarget
add_lld_library(lldExampleSubTarget
ExampleLinkingContext.cpp
ExampleTargetHandler.cpp
LINK_LIBS

View File

@ -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;

View File

@ -1,4 +1,4 @@
add_llvm_library(lldMachO
add_lld_library(lldMachO
ArchHandler.cpp
ArchHandler_arm.cpp
ArchHandler_arm64.cpp

View File

@ -168,7 +168,8 @@ void relocatableSectionInfoForContentType(DefinedAtom::ContentType atomType,
StringRef &segmentName,
StringRef &sectionName,
SectionType &sectionType,
SectionAttr &sectionAttrs);
SectionAttr &sectionAttrs,
bool &relocsToDefinedCanBeImplicit);
} // namespace normalized
} // namespace mach_o

View File

@ -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,

View File

@ -1034,7 +1034,8 @@ void relocatableSectionInfoForContentType(DefinedAtom::ContentType atomType,
StringRef &segmentName,
StringRef &sectionName,
SectionType &sectionType,
SectionAttr &sectionAttrs) {
SectionAttr &sectionAttrs,
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");

View File

@ -1,4 +1,4 @@
add_llvm_library(lldYAML
add_lld_library(lldYAML
ReaderWriterYAML.cpp
LINK_LIBS
lldCore

View File

@ -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)

View File

@ -0,0 +1,17 @@
.globl _foo
_foo:
nop
nop
nop
nop
.globl _bar
_bar:
nop
nop
nop
.globl _dah
_dah:
nop
nop

View 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

View File

@ -0,0 +1,12 @@
.globl _foo
_foo:
nop
nop
nop
nop
.globl _bar
_bar:
nop
nop
nop

Binary file not shown.

4
test/ELF/Inputs/wrap.s Normal file
View File

@ -0,0 +1,4 @@
.globl foo, __wrap_foo, __real_foo
foo = 0x11000
__wrap_foo = 0x11010
__real_foo = 0x11020

View 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

View 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

View 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
View 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]

View 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
View 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
View 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
View 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: }

View File

@ -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: ]

View File

@ -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
View 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: ]

View File

@ -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: ]

View File

@ -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: ]

View File

@ -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: ]

View File

@ -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: }

View File

@ -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
View 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
View 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

View File

@ -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

View File

@ -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
View 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

View File

@ -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.

View File

@ -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 ]

View 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 ^~

View File

@ -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

View File

@ -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
...