Support adding relocations for data sections, handling the cases where
authorBruno Cardoso Lopes <bruno.cardoso@gmail.com>
Tue, 21 Jul 2009 06:51:32 +0000 (06:51 +0000)
committerBruno Cardoso Lopes <bruno.cardoso@gmail.com>
Tue, 21 Jul 2009 06:51:32 +0000 (06:51 +0000)
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

lib/CodeGen/ELFCodeEmitter.cpp
lib/CodeGen/ELFWriter.cpp
lib/CodeGen/ELFWriter.h
lib/Target/X86/X86ELFWriterInfo.cpp

index 23210fcbc70c39e0c8d1912821e31c3a67e442e3..c77334aa28968296cb134930d64edfb987fd789e 100644 (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;
 
index f04efd5c8c77b10984d8a627b10788b345fba4e2..f4cd94a988abc9fde798fc32dcb96c8c56afd3cd 100644 (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;
index 34f82766c5863eb65b5394575e989f0538e9589a..6f083b925aec1b1bd57c60507df29db7f1d7ecad 100644 (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
index 618cc5b82b4948310a8c2d37514076a6304c5864..096c00ee305840f051fca0998720d4a486ede4fc 100644 (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");
     }