aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBruno Cardoso Lopes <bruno.cardoso@gmail.com>2009-06-22 19:16:16 +0000
committerBruno Cardoso Lopes <bruno.cardoso@gmail.com>2009-06-22 19:16:16 +0000
commit0d3193ef3ce7377eeaa1d38ca08f8a62ebcd5f63 (patch)
treea7128bd8b2f69fc709ff68afc5ad43904421822e
parent8dcbbdd00ebb4beb8eeb822791df326eee5de827 (diff)
downloadexternal_llvm-0d3193ef3ce7377eeaa1d38ca08f8a62ebcd5f63.zip
external_llvm-0d3193ef3ce7377eeaa1d38ca08f8a62ebcd5f63.tar.gz
external_llvm-0d3193ef3ce7377eeaa1d38ca08f8a62ebcd5f63.tar.bz2
Add more methods to gather target specific elf stuff
Support for .text relocations, implementing TargetELFWriter overloaded methods for x86/x86_64. Use a map to track global values to their symbol table indexes Code cleanup and small fixes git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@73894 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/llvm/CodeGen/BinaryObject.h6
-rw-r--r--include/llvm/Target/TargetELFWriterInfo.h23
-rw-r--r--lib/CodeGen/ELF.h48
-rw-r--r--lib/CodeGen/ELFCodeEmitter.cpp30
-rw-r--r--lib/CodeGen/ELFWriter.cpp327
-rw-r--r--lib/CodeGen/ELFWriter.h61
-rw-r--r--lib/Target/X86/X86ELFWriterInfo.cpp46
-rw-r--r--lib/Target/X86/X86ELFWriterInfo.h32
8 files changed, 418 insertions, 155 deletions
diff --git a/include/llvm/CodeGen/BinaryObject.h b/include/llvm/CodeGen/BinaryObject.h
index 0780cd6..4b66fe8 100644
--- a/include/llvm/CodeGen/BinaryObject.h
+++ b/include/llvm/CodeGen/BinaryObject.h
@@ -61,6 +61,11 @@ public:
return Relocations;
}
+ /// hasRelocations - Return true if 'Relocations' is not empty
+ bool hasRelocations() const {
+ return !Relocations.empty();
+ }
+
/// emitByte - This callback is invoked when a byte needs to be
/// written to the data stream.
inline void emitByte(uint8_t B) {
@@ -317,6 +322,7 @@ public:
void addRelocation(const MachineRelocation& relocation) {
Relocations.push_back(relocation);
}
+
};
} // end namespace llvm
diff --git a/include/llvm/Target/TargetELFWriterInfo.h b/include/llvm/Target/TargetELFWriterInfo.h
index f7e3392..c1f54d2 100644
--- a/include/llvm/Target/TargetELFWriterInfo.h
+++ b/include/llvm/Target/TargetELFWriterInfo.h
@@ -78,11 +78,32 @@ namespace llvm {
/// Symbol Table Info
unsigned getSymTabEntrySize() const { return is64Bit ? 24 : 16; }
- unsigned getSymTabAlignment() const { return is64Bit ? 8 : 4; }
+
+ /// getPrefELFAlignment - Returns the preferred alignment for ELF. This
+ /// is used to align some sections.
+ unsigned getPrefELFAlignment() const { return is64Bit ? 8 : 4; }
+
+ /// getRelocationEntrySize - Entry size used in the relocation section
+ unsigned getRelocationEntrySize() const {
+ return is64Bit ? (hasRelocationAddend() ? 24 : 16)
+ : (hasRelocationAddend() ? 12 : 8);
+ }
/// getFunctionAlignment - Returns the alignment for function 'F', targets
/// with different alignment constraints should overload this method
virtual unsigned getFunctionAlignment(const Function *F) const;
+
+ /// getRelocationType - Returns the target specific ELF Relocation type.
+ /// 'MachineRelTy' contains the object code independent relocation type
+ virtual unsigned getRelocationType(unsigned MachineRelTy) const = 0;
+
+ /// hasRelocationAddend - True if the target uses an addend in the
+ /// ELF relocation entry.
+ virtual bool hasRelocationAddend() const = 0;
+
+ /// getAddendForRelTy - Gets the addend value for an ELF relocation entry
+ /// based on the target relocation type. If addend is not used returns 0.
+ virtual long int getAddendForRelTy(unsigned RelTy) const = 0;
};
} // end llvm namespace
diff --git a/lib/CodeGen/ELF.h b/lib/CodeGen/ELF.h
index 796bc2c..28b6be8 100644
--- a/lib/CodeGen/ELF.h
+++ b/lib/CodeGen/ELF.h
@@ -128,7 +128,13 @@ namespace llvm {
/// added to logical symbol table for the module. This is eventually
/// turned into a real symbol table in the file.
struct ELFSym {
- const GlobalValue *GV; // The global value this corresponds to.
+ // The global value this corresponds to. Global symbols can be on of the
+ // 3 types : if this symbol has a zero initializer, it is common or should
+ // be placed in bss section otherwise it's a constant.
+ const GlobalValue *GV;
+ bool IsCommon;
+ bool IsBss;
+ bool IsConstant;
// ELF specific fields
unsigned NameIdx; // Index in .strtab of name, once emitted.
@@ -159,8 +165,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(0),
+ ELFSym(const GlobalValue *gv) : GV(gv), IsCommon(false), IsBss(false),
+ IsConstant(false), NameIdx(0), Value(0),
+ Size(0), Info(0), Other(STV_DEFAULT),
SectionIdx(ELFSection::SHN_UNDEF) {
if (!GV)
return;
@@ -180,16 +187,47 @@ namespace llvm {
}
}
- void SetBind(unsigned X) {
+ unsigned getBind() {
+ return (Info >> 4) & 0xf;
+ }
+
+ void setBind(unsigned X) {
assert(X == (X & 0xF) && "Bind value out of range!");
Info = (Info & 0x0F) | (X << 4);
}
- void SetType(unsigned X) {
+ void setType(unsigned X) {
assert(X == (X & 0xF) && "Type value out of range!");
Info = (Info & 0xF0) | X;
}
};
+ /// ELFRelocation - This class contains all the information necessary to
+ /// to generate any 32-bit or 64-bit ELF relocation entry.
+ class ELFRelocation {
+ uint64_t r_offset; // offset in the section of the object this applies to
+ uint32_t r_symidx; // symbol table index of the symbol to use
+ uint32_t r_type; // machine specific relocation type
+ int64_t r_add; // explicit relocation addend
+ bool r_rela; // if true then the addend is part of the entry
+ // otherwise the addend is at the location specified
+ // by r_offset
+ public:
+ uint64_t getInfo(bool is64Bit) const {
+ if (is64Bit)
+ return ((uint64_t)r_symidx << 32) + ((uint64_t)r_type & 0xFFFFFFFFL);
+ else
+ return (r_symidx << 8) + (r_type & 0xFFL);
+ }
+
+ uint64_t getOffset() const { return r_offset; }
+ int64_t getAddend() const { return r_add; }
+
+ ELFRelocation(uint64_t off, uint32_t sym, uint32_t type,
+ bool rela = true, int64_t addend = 0) :
+ r_offset(off), r_symidx(sym), r_type(type),
+ r_add(addend), r_rela(rela) {}
+ };
+
} // end namespace llvm
#endif
diff --git a/lib/CodeGen/ELFCodeEmitter.cpp b/lib/CodeGen/ELFCodeEmitter.cpp
index ca68396..8cb7c94 100644
--- a/lib/CodeGen/ELFCodeEmitter.cpp
+++ b/lib/CodeGen/ELFCodeEmitter.cpp
@@ -71,39 +71,38 @@ bool ELFCodeEmitter::finishFunction(MachineFunction &MF) {
// Update Section Size
ES->Size = CurBufferPtr - BufferBegin;
+ // Set the symbol type as a function
+ FnSym.setType(ELFSym::STT_FUNC);
+ FnSym.SectionIdx = ES->SectionIdx;
+ FnSym.Size = CurBufferPtr-FnStartPtr;
+
+ // Offset from start of Section
+ FnSym.Value = FnStartPtr-BufferBegin;
+
// Figure out the binding (linkage) of the symbol.
switch (MF.getFunction()->getLinkage()) {
default:
// appending linkage is illegal for functions.
assert(0 && "Unknown linkage type!");
case GlobalValue::ExternalLinkage:
- FnSym.SetBind(ELFSym::STB_GLOBAL);
+ FnSym.setBind(ELFSym::STB_GLOBAL);
+ EW.SymbolList.push_back(FnSym);
break;
case GlobalValue::LinkOnceAnyLinkage:
case GlobalValue::LinkOnceODRLinkage:
case GlobalValue::WeakAnyLinkage:
case GlobalValue::WeakODRLinkage:
- FnSym.SetBind(ELFSym::STB_WEAK);
+ FnSym.setBind(ELFSym::STB_WEAK);
+ EW.SymbolList.push_back(FnSym);
break;
case GlobalValue::PrivateLinkage:
assert (0 && "PrivateLinkage should not be in the symbol table.");
case GlobalValue::InternalLinkage:
- FnSym.SetBind(ELFSym::STB_LOCAL);
+ FnSym.setBind(ELFSym::STB_LOCAL);
+ EW.SymbolList.push_front(FnSym);
break;
}
- // Set the symbol type as a function
- FnSym.SetType(ELFSym::STT_FUNC);
-
- FnSym.SectionIdx = ES->SectionIdx;
- FnSym.Size = CurBufferPtr-FnStartPtr;
-
- // Offset from start of Section
- FnSym.Value = FnStartPtr-BufferBegin;
-
- // Finally, add it to the symtab.
- EW.SymbolList.push_back(FnSym);
-
// Relocations
// -----------
// If we have emitted any relocations to function-specific objects such as
@@ -113,7 +112,6 @@ bool ELFCodeEmitter::finishFunction(MachineFunction &MF) {
for (unsigned i = 0, e = Relocations.size(); i != e; ++i) {
MachineRelocation &MR = Relocations[i];
intptr_t Addr;
-
if (MR.isBasicBlock()) {
Addr = getMachineBasicBlockAddress(MR.getBasicBlock());
MR.setConstantVal(ES->SectionIdx);
diff --git a/lib/CodeGen/ELFWriter.cpp b/lib/CodeGen/ELFWriter.cpp
index aeccefb..281cf2f 100644
--- a/lib/CodeGen/ELFWriter.cpp
+++ b/lib/CodeGen/ELFWriter.cpp
@@ -136,105 +136,41 @@ bool ELFWriter::doInitialization(Module &M) {
ElfHdr.emitWord16(0); // Placeholder
// Add the null section, which is required to be first in the file.
- getSection("", ELFSection::SHT_NULL, 0);
-
- // Start up the symbol table. The first entry in the symtab is the null
- // entry.
- SymbolList.push_back(ELFSym(0));
+ getNullSection();
return false;
}
-void ELFWriter::EmitGlobal(GlobalVariable *GV) {
+unsigned ELFWriter::getGlobalELFLinkage(const GlobalVariable *GV) {
+ if (GV->hasInternalLinkage())
+ return ELFSym::STB_LOCAL;
- // XXX: put local symbols *before* global ones!
- const Section *S = TAI->SectionForGlobal(GV);
- DOUT << "Section " << S->getName() << " for global " << GV->getName() << "\n";
+ if (GV->hasWeakLinkage())
+ return ELFSym::STB_WEAK;
- // If this is an external global, emit it now. TODO: Note that it would be
- // better to ignore the symbol here and only add it to the symbol table if
- // referenced.
- if (!GV->hasInitializer()) {
- ELFSym ExternalSym(GV);
- ExternalSym.SetBind(ELFSym::STB_GLOBAL);
- ExternalSym.SetType(ELFSym::STT_NOTYPE);
- ExternalSym.SectionIdx = ELFSection::SHN_UNDEF;
- SymbolList.push_back(ExternalSym);
- return;
- }
+ return ELFSym::STB_GLOBAL;
+}
+// For global symbols without a section, return the Null section as a
+// placeholder
+ELFSection &ELFWriter::getGlobalSymELFSection(const GlobalVariable *GV,
+ ELFSym &Sym) {
+ const Section *S = TAI->SectionForGlobal(GV);
+ unsigned Flags = S->getFlags();
+ unsigned SectionType = ELFSection::SHT_PROGBITS;
+ unsigned SHdrFlags = ELFSection::SHF_ALLOC;
const TargetData *TD = TM.getTargetData();
unsigned Align = TD->getPreferredAlignment(GV);
Constant *CV = GV->getInitializer();
- unsigned Size = TD->getTypeAllocSize(CV->getType());
- // If this global has a zero initializer, go to .bss or common section.
- if (CV->isNullValue() || isa<UndefValue>(CV)) {
- // If this global is part of the common block, add it now. Variables are
- // part of the common block if they are zero initialized and allowed to be
- // merged with other symbols.
- if (GV->hasLinkOnceLinkage() || GV->hasWeakLinkage() ||
- GV->hasCommonLinkage()) {
- ELFSym CommonSym(GV);
- // Value for common symbols is the alignment required.
- CommonSym.Value = Align;
- CommonSym.Size = Size;
- CommonSym.SetBind(ELFSym::STB_GLOBAL);
- CommonSym.SetType(ELFSym::STT_OBJECT);
- CommonSym.SectionIdx = ELFSection::SHN_COMMON;
- SymbolList.push_back(CommonSym);
- getSection(S->getName(), ELFSection::SHT_NOBITS,
- ELFSection::SHF_WRITE | ELFSection::SHF_ALLOC, 1);
- return;
- }
-
- // Otherwise, this symbol is part of the .bss section. Emit it now.
- // Handle alignment. Ensure section is aligned at least as much as required
- // by this symbol.
- ELFSection &BSSSection = getBSSSection();
- BSSSection.Align = std::max(BSSSection.Align, Align);
-
- // Within the section, emit enough virtual padding to get us to an alignment
- // boundary.
- if (Align)
- BSSSection.Size = (BSSSection.Size + Align - 1) & ~(Align-1);
-
- ELFSym BSSSym(GV);
- BSSSym.Value = BSSSection.Size;
- BSSSym.Size = Size;
- BSSSym.SetType(ELFSym::STT_OBJECT);
-
- switch (GV->getLinkage()) {
- default: // weak/linkonce/common handled above
- assert(0 && "Unexpected linkage type!");
- case GlobalValue::AppendingLinkage: // FIXME: This should be improved!
- case GlobalValue::ExternalLinkage:
- BSSSym.SetBind(ELFSym::STB_GLOBAL);
- break;
- case GlobalValue::InternalLinkage:
- BSSSym.SetBind(ELFSym::STB_LOCAL);
- break;
- }
-
- // Set the idx of the .bss section
- BSSSym.SectionIdx = BSSSection.SectionIdx;
- if (!GV->hasPrivateLinkage())
- SymbolList.push_back(BSSSym);
+ DOUT << "Section " << S->getName() << " for global " << GV->getName() << "\n";
- // Reserve space in the .bss section for this symbol.
- BSSSection.Size += Size;
- return;
+ // If this is an external global, the symbol does not have a section.
+ if (!GV->hasInitializer()) {
+ Sym.SectionIdx = ELFSection::SHN_UNDEF;
+ return getNullSection();
}
- /// Emit the Global symbol to the right ELF section
- ELFSym GblSym(GV);
- GblSym.Size = Size;
- GblSym.SetType(ELFSym::STT_OBJECT);
- GblSym.SetBind(ELFSym::STB_GLOBAL);
- unsigned Flags = S->getFlags();
- unsigned SectType = ELFSection::SHT_PROGBITS;
- unsigned SHdrFlags = ELFSection::SHF_ALLOC;
-
if (Flags & SectionFlags::Code)
SHdrFlags |= ELFSection::SHF_EXECINSTR;
if (Flags & SectionFlags::Writeable)
@@ -246,29 +182,78 @@ void ELFWriter::EmitGlobal(GlobalVariable *GV) {
if (Flags & SectionFlags::Strings)
SHdrFlags |= ELFSection::SHF_STRINGS;
- // Remove tab from section name prefix
- std::string SectionName(S->getName());
- size_t Pos = SectionName.find("\t");
- if (Pos != std::string::npos)
- SectionName.erase(Pos, 1);
-
- // The section alignment should be bound to the element with
- // the largest alignment
- ELFSection &ElfS = getSection(SectionName, SectType, SHdrFlags);
- GblSym.SectionIdx = ElfS.SectionIdx;
- if (Align > ElfS.Align)
- ElfS.Align = Align;
-
- // S.Value should contain the symbol index inside the section,
- // and all symbols should start on their required alignment boundary
- GblSym.Value = (ElfS.size() + (Align-1)) & (-Align);
- ElfS.emitAlignment(Align);
-
- // Emit the constant symbol to its section
- EmitGlobalConstant(CV, ElfS);
+ // If this global has a zero initializer, go to .bss or common section.
+ // Variables are part of the common block if they are zero initialized
+ // and allowed to be merged with other symbols.
+ if (CV->isNullValue() || isa<UndefValue>(CV)) {
+ SectionType = ELFSection::SHT_NOBITS;
+ ELFSection &ElfS = getSection(S->getName(), SectionType, SHdrFlags);
+ if (GV->hasLinkOnceLinkage() || GV->hasWeakLinkage() ||
+ GV->hasCommonLinkage()) {
+ Sym.SectionIdx = ELFSection::SHN_COMMON;
+ Sym.IsCommon = true;
+ return ElfS;
+ }
+ Sym.IsBss = true;
+ Sym.SectionIdx = ElfS.SectionIdx;
+ if (Align) ElfS.Size = (ElfS.Size + Align-1) & ~(Align-1);
+ ElfS.Align = std::max(ElfS.Align, Align);
+ return ElfS;
+ }
+
+ Sym.IsConstant = true;
+ ELFSection &ElfS = getSection(S->getName(), SectionType, SHdrFlags);
+ Sym.SectionIdx = ElfS.SectionIdx;
+ ElfS.Align = std::max(ElfS.Align, Align);
+ return ElfS;
+}
+
+void ELFWriter::EmitFunctionDeclaration(const Function *F) {
+ ELFSym GblSym(F);
+ GblSym.setBind(ELFSym::STB_GLOBAL);
+ GblSym.setType(ELFSym::STT_NOTYPE);
+ GblSym.SectionIdx = ELFSection::SHN_UNDEF;
SymbolList.push_back(GblSym);
}
+void ELFWriter::EmitGlobalVar(const GlobalVariable *GV) {
+ unsigned SymBind = getGlobalELFLinkage(GV);
+ ELFSym GblSym(GV);
+ GblSym.setBind(SymBind);
+
+ if (GV->hasInitializer())
+ GblSym.setType(ELFSym::STT_OBJECT);
+ else
+ GblSym.setType(ELFSym::STT_NOTYPE);
+
+ ELFSection &GblSection = getGlobalSymELFSection(GV, GblSym);
+ const TargetData *TD = TM.getTargetData();
+ unsigned Align = TD->getPreferredAlignment(GV);
+ unsigned Size = TD->getTypeAllocSize(GV->getInitializer()->getType());
+ GblSym.Size = Size;
+
+ if (GblSym.IsCommon) {
+ GblSym.Value = Align;
+ } else if (GblSym.IsBss) {
+ GblSym.Value = GblSection.Size;
+ GblSection.Size += Size;
+ } else if (GblSym.IsConstant){
+ // GblSym.Value should contain the symbol index inside the section,
+ // and all symbols should start on their required alignment boundary
+ GblSym.Value = (GblSection.size() + (Align-1)) & (-Align);
+ GblSection.emitAlignment(Align);
+ EmitGlobalConstant(GV->getInitializer(), GblSection);
+ }
+
+ // Local symbols should come first on the symbol table.
+ if (!GV->hasPrivateLinkage()) {
+ if (SymBind == ELFSym::STB_LOCAL)
+ SymbolList.push_front(GblSym);
+ else
+ SymbolList.push_back(GblSym);
+ }
+}
+
void ELFWriter::EmitGlobalConstantStruct(const ConstantStruct *CVS,
ELFSection &GblS) {
@@ -306,6 +291,7 @@ void ELFWriter::EmitGlobalConstant(const Constant *CV, ELFSection &GblS) {
if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV)) {
if (CVA->isString()) {
std::string GblStr = CVA->getAsString();
+ GblStr.resize(GblStr.size()-1);
GblS.emitString(GblStr);
} else { // Not a string. Print the values in successive locations
for (unsigned i = 0, e = CVA->getNumOperands(); i != e; ++i)
@@ -370,8 +356,31 @@ bool ELFWriter::doFinalization(Module &M) {
// Build and emit data, bss and "common" sections.
for (Module::global_iterator I = M.global_begin(), E = M.global_end();
- I != E; ++I)
- EmitGlobal(I);
+ I != E; ++I) {
+ EmitGlobalVar(I);
+ GblSymLookup[I] = 0;
+ }
+
+ // Emit all pending globals
+ // TODO: this should be done only for referenced symbols
+ for (SetVector<GlobalValue*>::const_iterator I = PendingGlobals.begin(),
+ E = PendingGlobals.end(); I != E; ++I) {
+
+ // No need to emit the symbol again
+ if (GblSymLookup.find(*I) != GblSymLookup.end())
+ continue;
+
+ if (GlobalVariable *GV = dyn_cast<GlobalVariable>(*I)) {
+ EmitGlobalVar(GV);
+ } else if (Function *F = dyn_cast<Function>(*I)) {
+ // If function is not in GblSymLookup, it doesn't have a body,
+ // so emit the symbol as a function declaration (no section associated)
+ EmitFunctionDeclaration(F);
+ } else {
+ assert("unknown howto handle pending global");
+ }
+ GblSymLookup[*I] = 0;
+ }
// Emit non-executable stack note
if (TAI->getNonexecutableStackDirective())
@@ -400,6 +409,67 @@ bool ELFWriter::doFinalization(Module &M) {
/// EmitRelocations - Emit relocations
void ELFWriter::EmitRelocations() {
+
+ // Create Relocation sections for each section which needs it.
+ for (std::list<ELFSection>::iterator I = SectionList.begin(),
+ E = SectionList.end(); I != E; ++I) {
+
+ // This section does not have relocations
+ if (!I->hasRelocations()) continue;
+
+ // Get the relocation section for section 'I'
+ bool HasRelA = TEW->hasRelocationAddend();
+ ELFSection &RelSec = getRelocSection(I->getName(), HasRelA);
+
+ // 'Link' - Section hdr idx of the associated symbol table
+ // 'Info' - Section hdr idx of the section to which the relocation applies
+ ELFSection &SymTab = getSymbolTableSection();
+ RelSec.Link = SymTab.SectionIdx;
+ RelSec.Info = I->SectionIdx;
+ RelSec.EntSize = TEW->getRelocationEntrySize();
+
+ // Get the relocations from Section
+ std::vector<MachineRelocation> Relos = I->getRelocations();
+ for (std::vector<MachineRelocation>::iterator MRI = Relos.begin(),
+ MRE = Relos.end(); MRI != MRE; ++MRI) {
+ MachineRelocation &MR = *MRI;
+
+ // Offset from the start of the section containing the symbol
+ unsigned Offset = MR.getMachineCodeOffset();
+
+ // Symbol index in the symbol table
+ unsigned SymIdx = 0;
+
+ // Target specific ELF relocation type
+ unsigned RelType = TEW->getRelocationType(MR.getRelocationType());
+
+ // Constant addend used to compute the value to be stored
+ // into the relocatable field
+ int64_t Addend = TEW->getAddendForRelTy(RelType);
+
+ // There are several machine relocations types, and each one of
+ // them needs a different approach to retrieve the symbol table index.
+ if (MR.isGlobalValue()) {
+ const GlobalValue *G = MR.getGlobalValue();
+ SymIdx = GblSymLookup[G];
+ } else {
+ assert(0 && "dunno how to handle other relocation types");
+ }
+
+ // Get the relocation entry and emit to the relocation section
+ ELFRelocation Rel(Offset, SymIdx, RelType, HasRelA, Addend);
+ EmitRelocation(RelSec, Rel, HasRelA);
+ }
+ }
+}
+
+/// EmitRelocation - Write relocation 'Rel' to the relocation section 'Rel'
+void ELFWriter::EmitRelocation(BinaryObject &RelSec, ELFRelocation &Rel,
+ bool HasRelA) {
+ RelSec.emitWord(Rel.getOffset());
+ RelSec.emitWord(Rel.getInfo(is64Bit));
+ if (HasRelA)
+ RelSec.emitWord(Rel.getAddend());
}
/// EmitSymbol - Write symbol 'Sym' to the symbol table 'SymbolTable'
@@ -451,25 +521,27 @@ void ELFWriter::EmitSectionHeader(BinaryObject &SHdrTab,
/// EmitSymbolTable - If the current symbol table is non-empty, emit the string
/// table for it and then the symbol table itself.
void ELFWriter::EmitSymbolTable() {
- if (SymbolList.size() == 1) return; // Only the null entry.
+ if (!SymbolList.size()) return; // Empty symbol table.
- // FIXME: compact all local symbols to the start of the symtab.
unsigned FirstNonLocalSymbol = 1;
-
ELFSection &StrTab = getStringTableSection();
// Set the zero'th symbol to a null byte, as required.
StrTab.emitByte(0);
+ // Walk on the symbol list and write symbol names into the
+ // string table.
unsigned Index = 1;
- for (unsigned i = 1, e = SymbolList.size(); i != e; ++i) {
+ for (std::list<ELFSym>::iterator I = SymbolList.begin(),
+ E = SymbolList.end(); I != E; ++I) {
+
// Use the name mangler to uniquify the LLVM symbol.
- std::string Name = Mang->getValueName(SymbolList[i].GV);
+ std::string Name = Mang->getValueName(I->GV);
if (Name.empty()) {
- SymbolList[i].NameIdx = 0;
+ I->NameIdx = 0;
} else {
- SymbolList[i].NameIdx = Index;
+ I->NameIdx = Index;
StrTab.emitString(Name);
// Keep track of the number of bytes emitted to this section.
@@ -482,16 +554,33 @@ void ELFWriter::EmitSymbolTable() {
// Now that we have emitted the string table and know the offset into the
// string table of each symbol, emit the symbol table itself.
ELFSection &SymTab = getSymbolTableSection();
- SymTab.Align = TEW->getSymTabAlignment();
+ SymTab.Align = TEW->getPrefELFAlignment();
SymTab.Link = StrTab.SectionIdx; // Section Index of .strtab.
- SymTab.Info = FirstNonLocalSymbol; // First non-STB_LOCAL symbol.
// Size of each symtab entry.
SymTab.EntSize = TEW->getSymTabEntrySize();
- for (unsigned i = 0, e = SymbolList.size(); i != e; ++i)
- EmitSymbol(SymTab, SymbolList[i]);
+ // The first entry in the symtab is the null symbol
+ ELFSym NullSym = ELFSym(0);
+ EmitSymbol(SymTab, NullSym);
+
+ // Emit all the symbols to the symbol table. Skip the null
+ // symbol, cause it's emitted already
+ Index = 1;
+ for (std::list<ELFSym>::iterator I = SymbolList.begin(),
+ E = SymbolList.end(); I != E; ++I, ++Index) {
+ // Keep track of the first non-local symbol
+ if (I->getBind() == ELFSym::STB_LOCAL)
+ FirstNonLocalSymbol++;
+
+ // Emit symbol to the symbol table
+ EmitSymbol(SymTab, *I);
+
+ // Record the symbol table index for each global value
+ GblSymLookup[I->GV] = Index;
+ }
+ SymTab.Info = FirstNonLocalSymbol;
SymTab.Size = SymTab.size();
}
@@ -559,7 +648,7 @@ void ELFWriter::OutputSectionsAndSectionTable() {
}
// Align Section Header.
- unsigned TableAlign = is64Bit ? 8 : 4;
+ unsigned TableAlign = TEW->getPrefELFAlignment();
FileOff = (FileOff+TableAlign-1) & ~(TableAlign-1);
// Now that we know where all of the sections will be emitted, set the e_shnum
diff --git a/lib/CodeGen/ELFWriter.h b/lib/CodeGen/ELFWriter.h
index 8a380f0..c713e33 100644
--- a/lib/CodeGen/ELFWriter.h
+++ b/lib/CodeGen/ELFWriter.h
@@ -16,7 +16,7 @@
#include "llvm/ADT/SetVector.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
-#include "llvm/Support/OutputBuffer.h"
+#include "llvm/Support/Debug.h"
#include "llvm/Target/TargetAsmInfo.h"
#include "llvm/Target/TargetELFWriterInfo.h"
#include "ELF.h"
@@ -89,7 +89,7 @@ namespace llvm {
bool doFinalization(Module &M);
private:
- // Blob containing the Elf header
+ /// Blob containing the Elf header
BinaryObject ElfHdr;
/// SectionList - This is the list of sections that we have emitted to the
@@ -102,14 +102,35 @@ namespace llvm {
/// the SectionList.
std::map<std::string, ELFSection*> SectionLookup;
+ /// GblSymLookup - This is a mapping from global value to a symbol index
+ /// in the symbol table. This is useful since relocations symbol references
+ /// must be quickly mapped to a symbol table index
+ std::map<const GlobalValue*, uint32_t> GblSymLookup;
+
+ /// SymbolList - This is the list of symbols emitted to the symbol table
+ /// Local symbols go to the front and Globals to the back.
+ std::list<ELFSym> SymbolList;
+
+ /// 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;
+
/// getSection - Return the section with the specified name, creating a new
/// section if one does not already exist.
- ELFSection &getSection(const std::string &Name, unsigned Type,
+ ELFSection &getSection(const std::string &Name, unsigned Type,
unsigned Flags = 0, unsigned Align = 0) {
ELFSection *&SN = SectionLookup[Name];
if (SN) return *SN;
- SectionList.push_back(ELFSection(Name, isLittleEndian, is64Bit));
+ // Remove tab from section name prefix. This is necessary becase TAI
+ // sometimes return a section name prefixed with a "\t" char.
+ std::string SectionName(Name);
+ size_t Pos = SectionName.find("\t");
+ if (Pos != std::string::npos)
+ SectionName.erase(Pos, 1);
+
+ SectionList.push_back(ELFSection(SectionName, isLittleEndian, is64Bit));
SN = &SectionList.back();
SN->SectionIdx = NumSections++;
SN->Type = Type;
@@ -119,11 +140,25 @@ namespace llvm {
return *SN;
}
+ /// TODO: support mangled names here to emit the right .text section
+ /// for c++ object files.
ELFSection &getTextSection() {
return getSection(".text", ELFSection::SHT_PROGBITS,
ELFSection::SHF_EXECINSTR | ELFSection::SHF_ALLOC);
}
+ /// Return the relocation section of section 'S'. 'RelA' is true
+ /// if the relocation section contains entries with addends.
+ ELFSection &getRelocSection(std::string SName, bool RelA) {
+ std::string RelSName(".rel");
+ unsigned SHdrTy = RelA ? ELFSection::SHT_RELA : ELFSection::SHT_REL;
+
+ if (RelA) RelSName.append("a");
+ RelSName.append(SName);
+
+ return getSection(RelSName, SHdrTy, 0, TEW->getPrefELFAlignment());
+ }
+
ELFSection &getNonExecStackSection() {
return getSection(".note.GNU-stack", ELFSection::SHT_PROGBITS, 0, 1);
}
@@ -146,15 +181,9 @@ namespace llvm {
ELFSection::SHF_WRITE | ELFSection::SHF_ALLOC);
}
- /// SymbolList - This is the list of symbols we have emitted to the file.
- /// This actually gets rearranged before emission to the file (to put the
- /// local symbols first in the list).
- std::vector<ELFSym> SymbolList;
-
- /// 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;
+ ELFSection &getNullSection() {
+ return getSection("", ELFSection::SHT_NULL, 0);
+ }
// 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
@@ -165,11 +194,15 @@ namespace llvm {
unsigned ELFHdr_e_shnum_Offset; // e_shnum in ELF header.
private:
- void EmitGlobal(GlobalVariable *GV);
+ void EmitFunctionDeclaration(const Function *F);
+ void EmitGlobalVar(const GlobalVariable *GV);
void EmitGlobalConstant(const Constant *C, ELFSection &GblS);
void EmitGlobalConstantStruct(const ConstantStruct *CVS,
ELFSection &GblS);
+ unsigned getGlobalELFLinkage(const GlobalVariable *GV);
+ ELFSection &getGlobalSymELFSection(const GlobalVariable *GV, ELFSym &Sym);
void EmitRelocations();
+ void EmitRelocation(BinaryObject &RelSec, ELFRelocation &Rel, bool HasRelA);
void EmitSectionHeader(BinaryObject &SHdrTab, const ELFSection &SHdr);
void EmitSectionTableStringTable();
void EmitSymbol(BinaryObject &SymbolTable, ELFSym &Sym);
diff --git a/lib/Target/X86/X86ELFWriterInfo.cpp b/lib/Target/X86/X86ELFWriterInfo.cpp
index d84034b..315118f 100644
--- a/lib/Target/X86/X86ELFWriterInfo.cpp
+++ b/lib/Target/X86/X86ELFWriterInfo.cpp
@@ -12,11 +12,17 @@
//===----------------------------------------------------------------------===//
#include "X86ELFWriterInfo.h"
+#include "X86Relocations.h"
#include "llvm/Function.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetMachine.h"
+
using namespace llvm;
+//===----------------------------------------------------------------------===//
+// Implementation of the X86ELFWriterInfo class
+//===----------------------------------------------------------------------===//
+
X86ELFWriterInfo::X86ELFWriterInfo(TargetMachine &TM)
: TargetELFWriterInfo(TM) {
bool is64Bit = TM.getTargetData()->getPointerSizeInBits() == 64;
@@ -25,6 +31,34 @@ X86ELFWriterInfo::X86ELFWriterInfo(TargetMachine &TM)
X86ELFWriterInfo::~X86ELFWriterInfo() {}
+unsigned X86ELFWriterInfo::getRelocationType(unsigned MachineRelTy) const {
+ if (is64Bit) {
+ switch(MachineRelTy) {
+ case X86::reloc_pcrel_word:
+ return R_X86_64_PC32;
+ case X86::reloc_absolute_word:
+ return R_X86_64_32;
+ case X86::reloc_absolute_dword:
+ return R_X86_64_64;
+ case X86::reloc_picrel_word:
+ default:
+ assert(0 && "unknown relocation type");
+ }
+ } else {
+ switch(MachineRelTy) {
+ case X86::reloc_pcrel_word:
+ return R_386_PC32;
+ case X86::reloc_absolute_word:
+ return R_386_32;
+ case X86::reloc_absolute_dword:
+ case X86::reloc_picrel_word:
+ default:
+ assert(0 && "unknown relocation type");
+ }
+ }
+ return 0;
+}
+
unsigned X86ELFWriterInfo::getFunctionAlignment(const Function *F) const {
unsigned FnAlign = 4;
@@ -36,3 +70,15 @@ unsigned X86ELFWriterInfo::getFunctionAlignment(const Function *F) const {
return (1 << FnAlign);
}
+
+long int X86ELFWriterInfo::getAddendForRelTy(unsigned RelTy) const {
+ if (is64Bit) {
+ switch(RelTy) {
+ case R_X86_64_PC32: return -4;
+ break;
+ default:
+ assert(0 && "unknown x86 relocation type");
+ }
+ }
+ return 0;
+}
diff --git a/lib/Target/X86/X86ELFWriterInfo.h b/lib/Target/X86/X86ELFWriterInfo.h
index e9c5bc4..96485b8 100644
--- a/lib/Target/X86/X86ELFWriterInfo.h
+++ b/lib/Target/X86/X86ELFWriterInfo.h
@@ -19,11 +19,43 @@
namespace llvm {
class X86ELFWriterInfo : public TargetELFWriterInfo {
+
+ // ELF Relocation types for X86
+ enum X86RelocationType {
+ R_386_NONE = 0,
+ R_386_32 = 1,
+ R_386_PC32 = 2
+ };
+
+ // ELF Relocation types for X86_64
+ enum X86_64RelocationType {
+ R_X86_64_NONE = 0,
+ R_X86_64_64 = 1,
+ R_X86_64_PC32 = 2,
+ R_X86_64_32 = 10,
+ R_X86_64_32S = 11,
+ R_X86_64_PC64 = 24
+ };
+
public:
X86ELFWriterInfo(TargetMachine &TM);
virtual ~X86ELFWriterInfo();
+ /// getFunctionAlignment - Returns the alignment for function 'F', targets
+ /// with different alignment constraints should overload this method
virtual unsigned getFunctionAlignment(const Function *F) const;
+
+ /// getRelocationType - Returns the target specific ELF Relocation type.
+ /// 'MachineRelTy' contains the object code independent relocation type
+ virtual unsigned getRelocationType(unsigned MachineRelTy) const;
+
+ /// hasRelocationAddend - True if the target uses an addend in the
+ /// ELF relocation entry.
+ virtual bool hasRelocationAddend() const { return is64Bit ? true : false; }
+
+ /// getAddendForRelTy - Gets the addend value for an ELF relocation entry
+ /// based on the target relocation type
+ virtual long int getAddendForRelTy(unsigned RelTy) const;
};
} // end llvm namespace