mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 19:23:23 +01:00
Handle external symbols for ELF and add some static methods to ELFSym
llvm-svn: 77232
This commit is contained in:
parent
718ab76a04
commit
a536302ed5
@ -56,9 +56,74 @@ namespace llvm {
|
||||
/// added to logical symbol table for the module. This is eventually
|
||||
/// turned into a real symbol table in the file.
|
||||
struct ELFSym {
|
||||
// The global value this symbol matches. This should be null if the symbol
|
||||
// is not a global value.
|
||||
const GlobalValue *GV;
|
||||
|
||||
// ELF symbols are related to llvm ones by being one of the two llvm
|
||||
// types, for the other ones (section, file, func) a null pointer is
|
||||
// assumed.
|
||||
union {
|
||||
const GlobalValue *GV; // If this is a pointer to a GV
|
||||
const char *Ext; // If this is a pointer to a named symbol
|
||||
} Source;
|
||||
|
||||
// Describes from which source type this ELF symbol comes from,
|
||||
// they can be GlobalValue, ExternalSymbol or neither.
|
||||
enum {
|
||||
isGV, // The Source.GV field is valid.
|
||||
isExtSym, // The Source.ExtSym field is valid.
|
||||
isOther // Not a GlobalValue or External Symbol
|
||||
};
|
||||
unsigned SourceType;
|
||||
|
||||
bool isGlobalValue() { return SourceType == isGV; }
|
||||
bool isExternalSym() { return SourceType == isExtSym; }
|
||||
|
||||
// getGlobalValue - If this is a global value which originated the
|
||||
// elf symbol, return a reference to it.
|
||||
const GlobalValue *getGlobalValue() {
|
||||
assert(SourceType == isGV && "This is not a global value");
|
||||
return Source.GV;
|
||||
};
|
||||
|
||||
// getExternalSym - If this is an external symbol which originated the
|
||||
// elf symbol, return a reference to it.
|
||||
const char *getExternalSymbol() {
|
||||
assert(SourceType == isExtSym && "This is not an external symbol");
|
||||
return Source.Ext;
|
||||
};
|
||||
|
||||
// getGV - From a global value return a elf symbol to represent it
|
||||
static ELFSym *getGV(const GlobalValue *GV, unsigned Bind,
|
||||
unsigned Type, unsigned Visibility) {
|
||||
ELFSym *Sym = new ELFSym();
|
||||
Sym->Source.GV = GV;
|
||||
Sym->setBind(Bind);
|
||||
Sym->setType(Type);
|
||||
Sym->setVisibility(Visibility);
|
||||
Sym->SourceType = isGV;
|
||||
return Sym;
|
||||
}
|
||||
|
||||
// getExtSym - Create and return an elf symbol to represent an
|
||||
// external symbol
|
||||
static ELFSym *getExtSym(const char *Ext) {
|
||||
ELFSym *Sym = new ELFSym();
|
||||
Sym->Source.Ext = Ext;
|
||||
Sym->setBind(STB_GLOBAL);
|
||||
Sym->setType(STT_NOTYPE);
|
||||
Sym->setVisibility(STV_DEFAULT);
|
||||
Sym->SourceType = isExtSym;
|
||||
return Sym;
|
||||
}
|
||||
|
||||
// getSectionSym - Returns a elf symbol to represent an elf section
|
||||
static ELFSym *getSectionSym() {
|
||||
ELFSym *Sym = new ELFSym();
|
||||
Sym->setBind(ELFSym::STB_LOCAL);
|
||||
Sym->setType(ELFSym::STT_SECTION);
|
||||
Sym->setVisibility(ELFSym::STV_DEFAULT);
|
||||
Sym->SourceType = isOther;
|
||||
return Sym;
|
||||
}
|
||||
|
||||
// ELF specific fields
|
||||
unsigned NameIdx; // Index in .strtab of name, once emitted.
|
||||
@ -92,9 +157,9 @@ namespace llvm {
|
||||
STV_PROTECTED = 3 // Visible in other components but not preemptable
|
||||
};
|
||||
|
||||
ELFSym(const GlobalValue *gv) : GV(gv), NameIdx(0), Value(0),
|
||||
Size(0), Info(0), Other(STV_DEFAULT),
|
||||
SectionIdx(0), SymTabIdx(0) {}
|
||||
ELFSym() : SourceType(isOther), NameIdx(0), Value(0),
|
||||
Size(0), Info(0), Other(STV_DEFAULT), SectionIdx(0),
|
||||
SymTabIdx(0) {}
|
||||
|
||||
unsigned getBind() const { return (Info >> 4) & 0xf; }
|
||||
unsigned getType() const { return Info & 0xf; }
|
||||
|
@ -69,16 +69,11 @@ void ELFCodeEmitter::startFunction(MachineFunction &MF) {
|
||||
bool ELFCodeEmitter::finishFunction(MachineFunction &MF) {
|
||||
// Add a symbol to represent the function.
|
||||
const Function *F = MF.getFunction();
|
||||
ELFSym *FnSym = new ELFSym(F);
|
||||
FnSym->setType(ELFSym::STT_FUNC);
|
||||
FnSym->setBind(EW.getGlobalELFBinding(F));
|
||||
FnSym->setVisibility(EW.getGlobalELFVisibility(F));
|
||||
ELFSym *FnSym = ELFSym::getGV(F, EW.getGlobalELFBinding(F), ELFSym::STT_FUNC,
|
||||
EW.getGlobalELFVisibility(F));
|
||||
FnSym->SectionIdx = ES->SectionIdx;
|
||||
FnSym->Size = ES->getCurrentPCOffset()-FnStartOff;
|
||||
|
||||
// keep track of the emitted function leaving its symbol index as zero
|
||||
// to be patched up later when emitting the symbol table
|
||||
EW.setGlobalSymLookup(F, 0);
|
||||
EW.addGlobalSymbol(F);
|
||||
|
||||
// Offset from start of Section
|
||||
FnSym->Value = FnStartOff;
|
||||
@ -108,7 +103,9 @@ bool ELFCodeEmitter::finishFunction(MachineFunction &MF) {
|
||||
MachineRelocation &MR = Relocations[i];
|
||||
intptr_t Addr;
|
||||
if (MR.isGlobalValue()) {
|
||||
EW.PendingGlobals.insert(MR.getGlobalValue());
|
||||
EW.addGlobalSymbol(MR.getGlobalValue());
|
||||
} else if (MR.isExternalSymbol()) {
|
||||
EW.addExternalSymbol(MR.getExternalSymbol());
|
||||
} else if (MR.isBasicBlock()) {
|
||||
Addr = getMachineBasicBlockAddress(MR.getBasicBlock());
|
||||
MR.setConstantVal(ES->SectionIdx);
|
||||
|
@ -144,6 +144,21 @@ bool ELFWriter::doInitialization(Module &M) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// addGlobalSymbol - Add a global to be processed and to the
|
||||
// global symbol lookup, use a zero index for non private symbols
|
||||
// because the table index will be determined later.
|
||||
void ELFWriter::addGlobalSymbol(const GlobalValue *GV) {
|
||||
PendingGlobals.insert(GV);
|
||||
}
|
||||
|
||||
// addExternalSymbol - Add the external to be processed and to the
|
||||
// external symbol lookup, use a zero index because the symbol
|
||||
// table index will be determined later
|
||||
void ELFWriter::addExternalSymbol(const char *External) {
|
||||
PendingExternals.insert(External);
|
||||
ExtSymLookup[External] = 0;
|
||||
}
|
||||
|
||||
// Get jump table section on the section name returned by TAI
|
||||
ELFSection &ELFWriter::getJumpTableSection() {
|
||||
unsigned Align = TM.getTargetData()->getPointerABIAlignment();
|
||||
@ -169,7 +184,7 @@ ELFSection &ELFWriter::getConstantPoolSection(MachineConstantPoolEntry &CPE) {
|
||||
default: Kind = SectionKind::get(SectionKind::MergeableConst,false); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return getSection(TAI->getSectionForMergeableConstant(Kind)->getName(),
|
||||
ELFSection::SHT_PROGBITS,
|
||||
ELFSection::SHF_MERGE | ELFSection::SHF_ALLOC,
|
||||
@ -278,12 +293,18 @@ void ELFWriter::EmitGlobal(const GlobalValue *GV) {
|
||||
if (GblSymLookup.find(GV) != GblSymLookup.end())
|
||||
return;
|
||||
|
||||
// If the global is a function already emited in the text section
|
||||
// just add it to the global symbol lookup with a zero index to be
|
||||
// patched up later.
|
||||
if (isa<Function>(GV) && !GV->isDeclaration()) {
|
||||
GblSymLookup[GV] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle ELF Bind, Visibility and Type for the current symbol
|
||||
unsigned SymBind = getGlobalELFBinding(GV);
|
||||
ELFSym *GblSym = new ELFSym(GV);
|
||||
GblSym->setBind(SymBind);
|
||||
GblSym->setVisibility(getGlobalELFVisibility(GV));
|
||||
GblSym->setType(getGlobalELFType(GV));
|
||||
ELFSym *GblSym = ELFSym::getGV(GV, SymBind, getGlobalELFType(GV),
|
||||
getGlobalELFVisibility(GV));
|
||||
|
||||
if (isELFUndefSym(GV)) {
|
||||
GblSym->SectionIdx = ELFSection::SHN_UNDEF;
|
||||
@ -341,16 +362,18 @@ void ELFWriter::EmitGlobal(const GlobalValue *GV) {
|
||||
}
|
||||
}
|
||||
|
||||
// Private symbols must never go to the symbol table.
|
||||
unsigned SymIdx = 0;
|
||||
if (GV->hasPrivateLinkage()) {
|
||||
// For a private symbols, keep track of the index inside the
|
||||
// private list since it will never go to the symbol table and
|
||||
// won't be patched up later.
|
||||
PrivateSyms.push_back(GblSym);
|
||||
SymIdx = PrivateSyms.size()-1;
|
||||
GblSymLookup[GV] = PrivateSyms.size()-1;
|
||||
} else {
|
||||
// Non private symbol are left with zero indices until they are patched
|
||||
// up during the symbol table emition (where the indicies are created).
|
||||
SymbolList.push_back(GblSym);
|
||||
GblSymLookup[GV] = 0;
|
||||
}
|
||||
|
||||
setGlobalSymLookup(GV, SymIdx);
|
||||
}
|
||||
|
||||
void ELFWriter::EmitGlobalConstantStruct(const ConstantStruct *CVS,
|
||||
@ -478,10 +501,15 @@ bool ELFWriter::doFinalization(Module &M) {
|
||||
EmitGlobal(I);
|
||||
|
||||
// Emit all pending globals
|
||||
for (SetVector<GlobalValue*>::const_iterator I = PendingGlobals.begin(),
|
||||
E = PendingGlobals.end(); I != E; ++I)
|
||||
for (PendingGblsIter I = PendingGlobals.begin(), E = PendingGlobals.end();
|
||||
I != E; ++I)
|
||||
EmitGlobal(*I);
|
||||
|
||||
// Emit all pending externals
|
||||
for (PendingExtsIter I = PendingExternals.begin(), E = PendingExternals.end();
|
||||
I != E; ++I)
|
||||
SymbolList.push_back(ELFSym::getExtSym(*I));
|
||||
|
||||
// Emit non-executable stack note
|
||||
if (TAI->getNonexecutableStackDirective())
|
||||
getNonExecStackSection();
|
||||
@ -489,12 +517,8 @@ bool ELFWriter::doFinalization(Module &M) {
|
||||
// Emit a symbol for each section created until now, skip null section
|
||||
for (unsigned i = 1, e = SectionList.size(); i < e; ++i) {
|
||||
ELFSection &ES = *SectionList[i];
|
||||
ELFSym *SectionSym = new ELFSym(0);
|
||||
ELFSym *SectionSym = ELFSym::getSectionSym();
|
||||
SectionSym->SectionIdx = ES.SectionIdx;
|
||||
SectionSym->Size = 0;
|
||||
SectionSym->setBind(ELFSym::STB_LOCAL);
|
||||
SectionSym->setType(ELFSym::STT_SECTION);
|
||||
SectionSym->setVisibility(ELFSym::STV_DEFAULT);
|
||||
SymbolList.push_back(SectionSym);
|
||||
ES.Sym = SymbolList.back();
|
||||
}
|
||||
@ -589,6 +613,10 @@ void ELFWriter::EmitRelocations() {
|
||||
} else {
|
||||
Addend = TEW->getDefaultAddendForRelTy(RelType);
|
||||
}
|
||||
} else if (MR.isExternalSymbol()) {
|
||||
const char *ExtSym = MR.getExternalSymbol();
|
||||
SymIdx = ExtSymLookup[ExtSym];
|
||||
Addend = TEW->getDefaultAddendForRelTy(RelType);
|
||||
} else {
|
||||
// Get the symbol index for the section symbol
|
||||
unsigned SectionIdx = MR.getConstantVal();
|
||||
@ -695,7 +723,10 @@ void ELFWriter::EmitStringTable() {
|
||||
|
||||
// Use the name mangler to uniquify the LLVM symbol.
|
||||
std::string Name;
|
||||
if (Sym.GV) Name.append(Mang->getMangledName(Sym.GV));
|
||||
if (Sym.isGlobalValue())
|
||||
Name.append(Mang->getMangledName(Sym.getGlobalValue()));
|
||||
else if (Sym.isExternalSym())
|
||||
Name.append(Sym.getExternalSymbol());
|
||||
|
||||
if (Name.empty()) {
|
||||
Sym.NameIdx = 0;
|
||||
@ -755,7 +786,7 @@ void ELFWriter::EmitSymbolTable() {
|
||||
SymTab.EntSize = TEW->getSymTabEntrySize();
|
||||
|
||||
// The first entry in the symtab is the null symbol
|
||||
SymbolList.insert(SymbolList.begin(), new ELFSym(0));
|
||||
SymbolList.insert(SymbolList.begin(), new ELFSym());
|
||||
|
||||
// Reorder the symbol table with local symbols first!
|
||||
unsigned FirstNonLocalSymbol = SortSymbols();
|
||||
@ -767,8 +798,11 @@ void ELFWriter::EmitSymbolTable() {
|
||||
// Emit symbol to the symbol table
|
||||
EmitSymbol(SymTab, Sym);
|
||||
|
||||
// Record the symbol table index for each global value
|
||||
if (Sym.GV) setGlobalSymLookup(Sym.GV, i);
|
||||
// Record the symbol table index for each symbol
|
||||
if (Sym.isGlobalValue())
|
||||
GblSymLookup[Sym.getGlobalValue()] = i;
|
||||
else if (Sym.isExternalSym())
|
||||
ExtSymLookup[Sym.getExternalSymbol()] = i;
|
||||
|
||||
// Keep track on the symbol index into the symbol table
|
||||
Sym.SymTabIdx = i;
|
||||
|
@ -38,6 +38,8 @@ namespace llvm {
|
||||
|
||||
typedef std::vector<ELFSym*>::iterator ELFSymIter;
|
||||
typedef std::vector<ELFSection*>::iterator ELFSectionIter;
|
||||
typedef SetVector<const GlobalValue*>::const_iterator PendingGblsIter;
|
||||
typedef SetVector<const char *>::const_iterator PendingExtsIter;
|
||||
|
||||
/// ELFWriter - This class implements the common target-independent code for
|
||||
/// writing ELF files. Targets should derive a class from this to
|
||||
@ -108,11 +110,22 @@ namespace llvm {
|
||||
/// the SectionList. Used to quickly gather the Section Index from TAI names
|
||||
std::map<std::string, ELFSection*> SectionLookup;
|
||||
|
||||
/// PendingGlobals - Globals not processed as symbols yet.
|
||||
SetVector<const GlobalValue*> PendingGlobals;
|
||||
|
||||
/// GblSymLookup - This is a mapping from global value to a symbol index
|
||||
/// in the symbol table or private symbols list. This is useful since reloc
|
||||
/// symbol references must be quickly mapped to their indices on the lists
|
||||
/// symbol references must be quickly mapped to their indices on the lists.
|
||||
std::map<const GlobalValue*, uint32_t> GblSymLookup;
|
||||
|
||||
/// PendingExternals - Externals not processed as symbols yet.
|
||||
SetVector<const char *> PendingExternals;
|
||||
|
||||
/// ExtSymLookup - This is a mapping from externals to a symbol index
|
||||
/// in the symbol table list. This is useful since reloc symbol references
|
||||
/// must be quickly mapped to their symbol table indices.
|
||||
std::map<const char *, uint32_t> ExtSymLookup;
|
||||
|
||||
/// SymbolList - This is the list of symbols emitted to the symbol table.
|
||||
/// When the SymbolList is finally built, local symbols must be placed in
|
||||
/// the beginning while non-locals at the end.
|
||||
@ -122,11 +135,6 @@ namespace llvm {
|
||||
/// present in the SymbolList.
|
||||
std::vector<ELFSym*> PrivateSyms;
|
||||
|
||||
/// PendingGlobals - List of externally defined symbols that we have been
|
||||
/// asked to emit, but have not seen a reference to. When a reference
|
||||
/// is seen, the symbol will move from this list to the SymbolList.
|
||||
SetVector<GlobalValue*> PendingGlobals;
|
||||
|
||||
// Remove tab from section name prefix. This is necessary becase TAI
|
||||
// sometimes return a section name prefixed with elf unused chars. This is
|
||||
// a little bit dirty. FIXME: find a better approach, maybe add more
|
||||
@ -212,10 +220,15 @@ namespace llvm {
|
||||
unsigned getGlobalELFVisibility(const GlobalValue *GV);
|
||||
unsigned getElfSectionFlags(SectionKind Kind);
|
||||
|
||||
// setGlobalSymLookup - Set global value 'GV' with 'Index' in the lookup map
|
||||
void setGlobalSymLookup(const GlobalValue *GV, unsigned Index) {
|
||||
GblSymLookup[GV] = Index;
|
||||
}
|
||||
// addGlobalSymbol - Add a global to be processed and to the
|
||||
// global symbol lookup, use a zero index for non private symbols
|
||||
// because the table index will be determined later.
|
||||
void addGlobalSymbol(const GlobalValue *GV);
|
||||
|
||||
// addExternalSymbol - Add the external to be processed and to the
|
||||
// external symbol lookup, use a zero index because the symbol
|
||||
// table index will be determined later
|
||||
void addExternalSymbol(const char *External);
|
||||
|
||||
// As we complete the ELF file, we need to update fields in the ELF header
|
||||
// (e.g. the location of the section table). These members keep track of
|
||||
|
Loading…
Reference in New Issue
Block a user