forked from OSchip/llvm-project
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:
parent
11982922be
commit
12e543228d
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue