Support adding relocations for data sections, handling the cases where

global declared symbols are initialized with references from other global
symbols.

llvm-svn: 76540
This commit is contained in:
Bruno Cardoso Lopes 2009-07-21 06:51:32 +00:00
parent 11982922be
commit 12e543228d
4 changed files with 60 additions and 25 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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");
}