summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruno Cardoso Lopes <bruno.cardoso@gmail.com>2009-07-21 06:51:32 +0000
committerBruno Cardoso Lopes <bruno.cardoso@gmail.com>2009-07-21 06:51:32 +0000
commit68491c12179f963b346aa4cb8e1b924184d79970 (patch)
treeb1c556d30ff436e16f321632a9ac977532824adf
parent634d61b13500764a506100eb5115b1afe1e427eb (diff)
downloadllvm-68491c12179f963b346aa4cb8e1b924184d79970.tar.gz
llvm-68491c12179f963b346aa4cb8e1b924184d79970.tar.bz2
llvm-68491c12179f963b346aa4cb8e1b924184d79970.tar.xz
Support adding relocations for data sections, handling the cases where
global declared symbols are initialized with references from other global symbols. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@76540 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/CodeGen/ELFCodeEmitter.cpp4
-rw-r--r--lib/CodeGen/ELFWriter.cpp72
-rw-r--r--lib/CodeGen/ELFWriter.h5
-rw-r--r--lib/Target/X86/X86ELFWriterInfo.cpp4
4 files changed, 60 insertions, 25 deletions
diff --git a/lib/CodeGen/ELFCodeEmitter.cpp b/lib/CodeGen/ELFCodeEmitter.cpp
index 23210fcbc7..c77334aa28 100644
--- a/lib/CodeGen/ELFCodeEmitter.cpp
+++ b/lib/CodeGen/ELFCodeEmitter.cpp
@@ -68,6 +68,10 @@ bool ELFCodeEmitter::finishFunction(MachineFunction &MF) {
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);
+
// Offset from start of Section
FnSym->Value = FnStartOff;
diff --git a/lib/CodeGen/ELFWriter.cpp b/lib/CodeGen/ELFWriter.cpp
index f04efd5c8c..f4cd94a988 100644
--- a/lib/CodeGen/ELFWriter.cpp
+++ b/lib/CodeGen/ELFWriter.cpp
@@ -240,30 +240,31 @@ static bool isELFUndefSym(const GlobalValue *GV) {
// isELFBssSym - for an undef or null value, the symbol must go to a bss
// section if it's not weak for linker, otherwise it's a common sym.
-static bool isELFBssSym(const GlobalValue *GV) {
- return (!GV->isDeclaration() &&
- (GV->isNullValue() || isa<UndefValue>(GV)) &&
- !GV->isWeakForLinker());
+static bool isELFBssSym(const GlobalVariable *GV) {
+ const Constant *CV = GV->getInitializer();
+ return ((CV->isNullValue() || isa<UndefValue>(CV)) && !GV->isWeakForLinker());
}
// isELFCommonSym - for an undef or null value, the symbol must go to a
// common section if it's weak for linker, otherwise bss.
-static bool isELFCommonSym(const GlobalValue *GV) {
- return (!GV->isDeclaration() &&
- (GV->isNullValue() || isa<UndefValue>(GV))
- && GV->isWeakForLinker());
+static bool isELFCommonSym(const GlobalVariable *GV) {
+ const Constant *CV = GV->getInitializer();
+ return ((CV->isNullValue() || isa<UndefValue>(CV)) && GV->isWeakForLinker());
}
// isELFDataSym - if the symbol is an initialized but no null constant
// it must go to some kind of data section gathered from TAI
-static bool isELFDataSym(const GlobalValue *GV) {
- return (!GV->isDeclaration() &&
- !(GV->isNullValue() || isa<UndefValue>(GV)));
+static bool isELFDataSym(const Constant *CV) {
+ return (!(CV->isNullValue() || isa<UndefValue>(CV)));
}
// EmitGlobal - Choose the right section for global and emit it
void ELFWriter::EmitGlobal(const GlobalValue *GV) {
+ // Check if the referenced symbol is already emitted
+ if (GblSymLookup.find(GV) != GblSymLookup.end())
+ return;
+
// Handle ELF Bind, Visibility and Type for the current symbol
unsigned SymBind = getGlobalELFBinding(GV);
ELFSym *GblSym = new ELFSym(GV);
@@ -287,7 +288,7 @@ void ELFWriter::EmitGlobal(const GlobalValue *GV) {
unsigned Size = TD->getTypeAllocSize(GVar->getInitializer()->getType());
GblSym->Size = Size;
- if (isELFCommonSym(GV)) {
+ if (isELFCommonSym(GVar)) {
GblSym->SectionIdx = ELFSection::SHN_COMMON;
getSection(S->getName(), ELFSection::SHT_NOBITS, SectionFlags, 1);
@@ -296,7 +297,7 @@ void ELFWriter::EmitGlobal(const GlobalValue *GV) {
// value contains its alignment.
GblSym->Value = Align;
- } else if (isELFBssSym(GV)) {
+ } else if (isELFBssSym(GVar)) {
ELFSection &ES =
getSection(S->getName(), ELFSection::SHT_NOBITS, SectionFlags);
GblSym->SectionIdx = ES.SectionIdx;
@@ -336,7 +337,7 @@ void ELFWriter::EmitGlobal(const GlobalValue *GV) {
SymbolList.push_back(GblSym);
}
- GblSymLookup[GV] = SymIdx;
+ setGlobalSymLookup(GV, SymIdx);
}
void ELFWriter::EmitGlobalConstantStruct(const ConstantStruct *CVS,
@@ -410,8 +411,37 @@ void ELFWriter::EmitGlobalConstant(const Constant *CV, ELFSection &GblS) {
for (unsigned I = 0, E = PTy->getNumElements(); I < E; ++I)
EmitGlobalConstant(CP->getOperand(I), GblS);
return;
+ } else if (const GlobalValue *GV = dyn_cast<GlobalValue>(CV)) {
+ // This is a constant address for a global variable or function and
+ // therefore must be referenced using a relocation entry.
+
+ // Check if the referenced symbol is already emitted
+ if (GblSymLookup.find(GV) == GblSymLookup.end())
+ EmitGlobal(GV);
+
+ // Create the relocation entry for the global value
+ MachineRelocation MR =
+ MachineRelocation::getGV(GblS.getCurrentPCOffset(),
+ TEW->getAbsoluteLabelMachineRelTy(),
+ const_cast<GlobalValue*>(GV));
+
+ // Fill the data entry with zeros
+ for (unsigned i=0; i < Size; ++i)
+ GblS.emitByte(0);
+
+ // Add the relocation entry for the current data section
+ GblS.addRelocation(MR);
+ return;
+ } else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) {
+ if (CE->getOpcode() == Instruction::BitCast) {
+ EmitGlobalConstant(CE->getOperand(0), GblS);
+ return;
+ }
+ // See AsmPrinter::EmitConstantValueOnly for other ConstantExpr types
+ llvm_unreachable("Unsupported ConstantExpr type");
}
- llvm_unreachable("unknown global constant");
+
+ llvm_unreachable("Unknown global constant type");
}
@@ -431,19 +461,13 @@ 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) {
+ I != E; ++I)
EmitGlobal(I);
- }
// 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;
+ E = PendingGlobals.end(); I != E; ++I)
EmitGlobal(*I);
- }
// Emit non-executable stack note
if (TAI->getNonexecutableStackDirective())
@@ -731,7 +755,7 @@ void ELFWriter::EmitSymbolTable() {
EmitSymbol(SymTab, Sym);
// Record the symbol table index for each global value
- if (Sym.GV) GblSymLookup[Sym.GV] = i;
+ if (Sym.GV) setGlobalSymLookup(Sym.GV, 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 34f82766c5..6f083b925a 100644
--- a/lib/CodeGen/ELFWriter.h
+++ b/lib/CodeGen/ELFWriter.h
@@ -211,6 +211,11 @@ namespace llvm {
unsigned getGlobalELFVisibility(const GlobalValue *GV);
unsigned getElfSectionFlags(unsigned Flags);
+ // setGlobalSymLookup - Set global value 'GV' with 'Index' in the lookup map
+ void setGlobalSymLookup(const GlobalValue *GV, unsigned Index) {
+ GblSymLookup[GV] = Index;
+ }
+
// 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
// the offset in ELFHeader of these various pieces to update and other
diff --git a/lib/Target/X86/X86ELFWriterInfo.cpp b/lib/Target/X86/X86ELFWriterInfo.cpp
index 618cc5b82b..096c00ee30 100644
--- a/lib/Target/X86/X86ELFWriterInfo.cpp
+++ b/lib/Target/X86/X86ELFWriterInfo.cpp
@@ -64,7 +64,9 @@ long int X86ELFWriterInfo::getDefaultAddendForRelTy(unsigned RelTy) const {
if (is64Bit) {
switch(RelTy) {
case R_X86_64_PC32: return -4;
- case R_X86_64_32: return 0;
+ case R_X86_64_32:
+ case R_X86_64_64:
+ return 0;
default:
llvm_unreachable("unknown x86_64 relocation type");
}