Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion include/eld/Diagnostics/DiagSymbolVersioning.inc
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,6 @@ DIAG(trace_clear_export_due_to_local_scope, DiagnosticEngine::Trace,
DIAG(error_missing_version_node, DiagnosticEngine::Error,
"%0: symbol %1 has undefined version %2")
DIAG(trace_assign_output_version_ids, DiagnosticEngine::Trace,
"Assigning version IDs to output symbols")
"Assigning version IDs to output symbols")
DIAG(trace_adding_verneed_entry, DiagnosticEngine::Trace,
"Adding verneed entry: '%0' -> '%1'")
1 change: 1 addition & 0 deletions include/eld/Fragment/Fragment.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ class Fragment {
#ifdef ELD_ENABLE_SYMBOL_VERSIONING
GNUVerDef,
GNUVerSym,
GNUVerNeed
#endif
};

Expand Down
72 changes: 72 additions & 0 deletions include/eld/Fragment/GNUVerNeedFragment.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
//===- GNUVerNeedFragment.h----------------------------------------------------===//
// Part of the eld Project, under the BSD License
// See https://github.com/qualcomm/eld/LICENSE.txt for license information.
// SPDX-License-Identifier: BSD-3-Clause
//===--------------------------------------------------------------------------===//
//
// The MCLinker Project
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===--------------------------------------------------------------------------===//

#ifndef ELD_FRAGMENT_GNUVERNEEDFRAGMENT_H
#define ELD_FRAGMENT_GNUVERNEEDFRAGMENT_H

#include "eld/Fragment/Fragment.h"
#include "llvm/ADT/StringRef.h"

namespace eld {
class DiagnosticEngine;
class ELFSection;
class InputFile;
class ELFFileFormat;

/** \class VerNeedFragment
* \brief VerNeedFragment is a kind of Fragment containing input memory region
*/
// Region fragment expression
class GNUVerNeedFragment : public Fragment {
public:
GNUVerNeedFragment(ELFSection *S);

static bool classof(const Fragment *F) {
return F->getKind() == Fragment::Type::GNUVerNeed;
}

template <class ELFT>
eld::Expected<void>
computeVersionNeeds(const std::vector<InputFile *> &DynamicObjectFiles,
ELFFileFormat *FileFormat, DiagnosticEngine &DE);

eld::Expected<void> emit(MemoryRegion &Mr, Module &M) override;

size_t size() const override;

template <class ELFT>
eld::Expected<void> emitImpl(uint8_t *Buf, Module &M);

size_t needCount() { return VersionNeeds.size(); }

public:
struct VernAuxInfo {
uint32_t VersionNameOffset = 0;
uint32_t VersionID = 0;
uint32_t VersionNameHash = 0;
};

struct VerNeedInfo {
uint32_t SONameOffset = 0;
std::vector<VernAuxInfo> Vernauxs;
};

protected:
std::vector<VerNeedInfo> VersionNeeds;
size_t VerNeedEntrySize = 0;
size_t VernAuxEntrySize = 0;
};

} // namespace eld

#endif
110 changes: 110 additions & 0 deletions include/eld/Input/ELFDynObjectFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@

#include "eld/Input/ELFFileBase.h"
#include "eld/Input/Input.h"
#ifdef ELD_ENABLE_SYMBOL_VERSIONING
// FIXME: Are we using these headers?
#include "llvm/BinaryFormat/ELF.h"
#include <cassert>
#include <sys/types.h>
#endif

namespace eld {

Expand Down Expand Up @@ -35,8 +41,112 @@ class ELFDynObjectFile : public ELFFileBase {

std::string getFallbackSOName() const;

#ifdef ELD_ENABLE_SYMBOL_VERSIONING
void setVerDefSection(ELFSection *S) { VerDefSection = S; }

ELFSection *getVerDefSection() const { return VerDefSection; }

void setVerNeedSection(ELFSection *S) { VerNeedSection = S; }

ELFSection *getVerNeedSection() const { return VerNeedSection; }

void setVerSymSection(ELFSection *S) { VerSymSection = S; }

ELFSection *getVerSymSection() const { return VerSymSection; }

void setVerDefs(std::vector<const void *> VDefs) { VerDefs = VDefs; }

const std::vector<const void *> &getVerDefs() const { return VerDefs; }

void setVerNeeds(std::vector<uint32_t> VNeeds) { VerNeeds = VNeeds; }

const std::vector<uint32_t> &getVerNeeds() const { return VerNeeds; }

void setVerSyms(std::vector<uint16_t> VSyms) { VerSyms = VSyms; }

const std::vector<uint16_t> &getVerSyms() const { return VerSyms; }

void setDynStrTabSection(ELFSection *S) { DynStrTabSection = S; }

llvm::StringRef getDynStringTable() const;

template <class ELFT>
llvm::StringRef getSymbolVersionName(uint32_t SymIdx,
ResolveInfo::Desc SymDesc) const {
uint16_t SymVerID = getSymbolVersionID(SymIdx);
llvm::StringRef VerName;
if (SymVerID == llvm::ELF::VER_NDX_LOCAL ||
SymVerID == llvm::ELF::VER_NDX_GLOBAL)
return VerName;
if (SymDesc == ResolveInfo::Desc::Undefined)
VerName = getDynStringTable().data() + VerNeeds[SymVerID];
else {
auto VerNameOffset =
reinterpret_cast<const typename ELFT::Verdef *>(VerDefs[SymVerID])
->getAux()
->vda_name;
VerName = getDynStringTable().data() + VerNameOffset;
}
return VerName;
}

uint16_t getSymbolVersionID(uint32_t SymIdx) const {
assert(SymIdx < VerSyms.size() && "Invalid SymIdx");
return VerSyms[SymIdx] & ~llvm::ELF::VERSYM_HIDDEN;
}

bool isDefaultVersionedSymbol(uint32_t SymIdx) const {
assert(SymIdx < VerSyms.size() && "Invalid SymIdx");
return VerSyms[SymIdx] == getSymbolVersionID(SymIdx);
}

uint16_t getOutputVernAuxID(uint16_t InputVerID) {
if (InputVerID >= OutputVernAuxIDMap.size())
OutputVernAuxIDMap.resize(InputVerID + 1, 0);
return OutputVernAuxIDMap[InputVerID];
}

void setOutputVernAuxID(uint16_t InputVerID, uint16_t OutputVerID) {
if (InputVerID >= OutputVernAuxIDMap.size())
OutputVernAuxIDMap.resize(InputVerID + 1, 0);
OutputVernAuxIDMap[InputVerID] = OutputVerID;
}

const std::vector<uint16_t> &getOutputVernAuxIDMap() const {
return OutputVernAuxIDMap;
}

const void *getVerDef(uint16_t InputVerID) {
assert(InputVerID < VerDefs.size() && "Invalid InputVerID");
return VerDefs[InputVerID];
}

bool hasSymbolVersioningInfo() const { return VerSymSection != nullptr; }

void addNonCanonicalSymbol(LDSymbol *Sym) {
NonCanonicalSymbols.push_back(Sym);
}

const std::vector<LDSymbol *> &getNonCanonicalSymbols() const {
return NonCanonicalSymbols;
}
#endif

private:
std::vector<ELFSection *> Sections;
#ifdef ELD_ENABLE_SYMBOL_VERSIONING
ELFSection *VerDefSection = nullptr;
ELFSection *VerNeedSection = nullptr;
ELFSection *VerSymSection = nullptr;
ELFSection *DynStrTabSection = nullptr;
std::vector<const void *> VerDefs;
std::vector<uint32_t> VerNeeds;
std::vector<uint16_t> VerSyms;

std::vector<uint16_t> OutputVernAuxIDMap;

std::vector<LDSymbol *> NonCanonicalSymbols;
#endif
};

} // namespace eld
Expand Down
2 changes: 2 additions & 0 deletions include/eld/Input/ELFFileBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ class ELFFileBase : public ObjectFile {

ELFSection *getStringTable() const { return StringTable; }

llvm::StringRef getStringTableData() const;

/// ------------ Extended Symbol Table ---------------------------------------
void setExtendedSymbolTable(ELFSection *SymTab) {
ExtendedSymbolTable = SymTab;
Expand Down
14 changes: 14 additions & 0 deletions include/eld/Readers/DynamicELFReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,23 @@ template <class ELFT> class DynamicELFReader : public ELFReader<ELFT> {
eld::Expected<ELFSection *>
createSection(typename ELFReader<ELFT>::Elf_Shdr rawSectHdr) override;

#ifdef ELD_ENABLE_SYMBOL_VERSIONING
void
setSectionInInputFile(ELFSection *S,
typename ELFReader<ELFT>::Elf_Shdr rawSectHdr) override;

eld::Expected<void> readSections() override;
#endif

protected:
explicit DynamicELFReader(Module &module, InputFile &inputFile,
plugin::DiagnosticEntry &diagEntry);
#ifdef ELD_ENABLE_SYMBOL_VERSIONING
private:
eld::Expected<void> readVerDefSection();
eld::Expected<void> readVerSymSection();
eld::Expected<void> readVerNeedSection();
#endif
};
} // namespace eld
#endif
2 changes: 1 addition & 1 deletion include/eld/Readers/ELFReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ template <class ELFT> class ELFReader : public ELFReaderBase {
/// - SHT_SYMTAB
/// - SHT_SYMTAB_SHNDX
/// - SHT_STRTAB
void setSectionInInputFile(ELFSection *S, Elf_Shdr rawSectHdr);
virtual void setSectionInInputFile(ELFSection *S, Elf_Shdr rawSectHdr);

/// Set link and info attributes to the sections.
bool setLinkInfoAttributes();
Expand Down
2 changes: 2 additions & 0 deletions include/eld/Readers/ELFReaderBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ class ELFReaderBase {

virtual eld::Expected<bool> readRelocationSection(ELFSection *RS);

virtual eld::Expected<void> readSections();

/// Returns the symbol type.
static ResolveInfo::Type getSymbolType(uint8_t info, uint32_t shndx);

Expand Down
13 changes: 12 additions & 1 deletion include/eld/SymbolResolver/IRBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,10 @@ class IRBuilder {
Relocation::Type Type, LDSymbol &PSym,
uint32_t POffset, Relocation::Address CurAddend);

#ifdef ELD_ENABLE_SYMBOL_VERSIONING
void normalizeSymbols();
#endif

private:
LDSymbol *
addSymbolFromObject(InputFile &Input, const std::string &SymbolName,
Expand All @@ -111,7 +115,8 @@ class IRBuilder {
ResolveInfo::SizeType Size,
LDSymbol::ValueType Value,
ResolveInfo::Visibility Visibility,
uint32_t Shndx, bool IsPostLtoPhase);
uint32_t Shndx, bool IsPostLtoPhase,
uint32_t SymIdx);

public:
void addToCref(InputFile &Input, Resolver::Result PResult);
Expand All @@ -126,6 +131,12 @@ class IRBuilder {
LinkerConfig &ThisConfig;
bool IsGarbageCollected;
InputBuilder ThisInputBuilder;

#ifdef ELD_ENABLE_SYMBOL_VERSIONING
// 0th element -> Canonical version symbol, 1st element -> Non-canonical
// version symbol.
std::vector<std::pair<LDSymbol *, LDSymbol *>> VersionedSymbols;
#endif
};

template <>
Expand Down
6 changes: 6 additions & 0 deletions include/eld/SymbolResolver/NamePool.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,12 @@ class NamePool {
SharedLibsSymbols[Sym->resolveInfo()] = Sym;
}

#ifdef ELD_ENABLE_SYMBOL_VERSIONING
void addSharedLibSymbol(LDSymbol *Sym, ResolveInfo *RI) {
SharedLibsSymbols[RI] = Sym;
}
#endif

LDSymbol *getSharedLibSymbol(const ResolveInfo *RI) {
auto Iter = SharedLibsSymbols.find(RI);
if (Iter != SharedLibsSymbols.end())
Expand Down
2 changes: 2 additions & 0 deletions include/eld/SymbolResolver/ResolveInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,8 @@ class ResolveInfo {

llvm::StringRef getName() const { return SymbolName; }

void setName(llvm::StringRef SymName) { SymbolName = SymName; }

unsigned int nameSize() const { return SymbolName.size(); }

uint32_t info() const { return (ThisBitField & InfoMask); }
Expand Down
5 changes: 5 additions & 0 deletions include/eld/Target/GNULDBackend.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ class ELFObjectFileFormat;
class ELFSegmentFactory;
#ifdef ELD_ENABLE_SYMBOL_VERSIONING
class GNUVerDefFragment;
class GNUVerNeedFragment;
#endif
class TargetInfo;
class Layout;
Expand Down Expand Up @@ -846,6 +847,8 @@ class GNULDBackend {
ELFSection *getGNUVerSymSection() const { return GNUVerSymSection; }
ELFSection *getGNUVerDefSection() const { return GNUVerDefSection; }
GNUVerDefFragment *getGNUVerDefFragment() const { return GNUVerDefFrag; }
ELFSection *getGNUVerNeedSection() const { return GNUVerNeedSection; }
GNUVerNeedFragment *getGNUVerNeedFragment() const { return GNUVerNeedFrag; }
void setShouldEmitVersioningSections(bool Should) {
ShouldEmitVersioningSections = Should;
}
Expand Down Expand Up @@ -1182,6 +1185,8 @@ class GNULDBackend {
ELFSection *GNUVerSymSection = nullptr;
ELFSection *GNUVerDefSection = nullptr;
GNUVerDefFragment *GNUVerDefFrag = nullptr;
ELFSection *GNUVerNeedSection = nullptr;
GNUVerNeedFragment *GNUVerNeedFrag = nullptr;
std::unordered_map<const ResolveInfo *, uint16_t> OutputVersionIDs;
#endif
};
Expand Down
3 changes: 3 additions & 0 deletions lib/Core/Linker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,9 @@ bool Linker::normalize() {
if (!ObjLinker->normalize())
return false;
}
#ifdef ELD_ENABLE_SYMBOL_VERSIONING
IR->normalizeSymbols();
#endif
return true;
}

Expand Down
3 changes: 2 additions & 1 deletion lib/Fragment/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ llvm_add_library(
PARTIAL_SOURCES_INTENDED)

if (ELD_ENABLE_SYMBOL_VERSIONING)
target_sources(ELDFragment PRIVATE GNUVerDefFragment.cpp GNUVerSymFragment.cpp)
target_sources(ELDFragment PRIVATE GNUVerDefFragment.cpp GNUVerNeedFragment.cpp
GNUVerSymFragment.cpp)
endif()

target_link_libraries(ELDFragment PRIVATE ELDSymbolResolver)
Loading