aboutsummaryrefslogtreecommitdiffstats
path: root/lib/CodeGen
diff options
context:
space:
mode:
authorBruno Cardoso Lopes <bruno.cardoso@gmail.com>2009-07-27 18:54:47 +0000
committerBruno Cardoso Lopes <bruno.cardoso@gmail.com>2009-07-27 18:54:47 +0000
commit746e3bb3547d848af86c4d677dfdc2c4481c7518 (patch)
tree0122a9f049cefc91a94df18373d68f2f96c66811 /lib/CodeGen
parente0f21bd47f3fed91124e3d8187e1bf8a66c6aef3 (diff)
downloadexternal_llvm-746e3bb3547d848af86c4d677dfdc2c4481c7518.zip
external_llvm-746e3bb3547d848af86c4d677dfdc2c4481c7518.tar.gz
external_llvm-746e3bb3547d848af86c4d677dfdc2c4481c7518.tar.bz2
Handle external symbols for ELF and add some static methods to ELFSym
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@77232 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen')
-rw-r--r--lib/CodeGen/ELF.h77
-rw-r--r--lib/CodeGen/ELFCodeEmitter.cpp15
-rw-r--r--lib/CodeGen/ELFWriter.cpp76
-rw-r--r--lib/CodeGen/ELFWriter.h33
4 files changed, 155 insertions, 46 deletions
diff --git a/lib/CodeGen/ELF.h b/lib/CodeGen/ELF.h
index d4dc151..cd0c68a 100644
--- a/lib/CodeGen/ELF.h
+++ b/lib/CodeGen/ELF.h
@@ -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; }
diff --git a/lib/CodeGen/ELFCodeEmitter.cpp b/lib/CodeGen/ELFCodeEmitter.cpp
index 1c27428..a62a884 100644
--- a/lib/CodeGen/ELFCodeEmitter.cpp
+++ b/lib/CodeGen/ELFCodeEmitter.cpp
@@ -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);
diff --git a/lib/CodeGen/ELFWriter.cpp b/lib/CodeGen/ELFWriter.cpp
index c61d421..f2a9bf3 100644
--- a/lib/CodeGen/ELFWriter.cpp
+++ b/lib/CodeGen/ELFWriter.cpp
@@ -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;
diff --git a/lib/CodeGen/ELFWriter.h b/lib/CodeGen/ELFWriter.h
index 8dcd970..021fbeb 100644
--- a/lib/CodeGen/ELFWriter.h
+++ b/lib/CodeGen/ELFWriter.h
@@ -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