[llvm-commits] CVS: llvm/lib/CodeGen/ELFWriter.cpp

Chris Lattner lattner at cs.uiuc.edu
Thu Jul 7 00:02:31 PDT 2005



Changes in directory llvm/lib/CodeGen:

ELFWriter.cpp updated: 1.1 -> 1.2
---
Log message:

Add support for emitting the symbol table (and its string table) of the 
module to the ELF file.  Test it by adding support for emitting common 
symbols.  This allows us to compile this:

%X = weak global int 0
%Y = weak global int 0
%Z = weak global int 0

to an elf file that 'readelf's this:

Symbol table '.symtab' contains 4 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 00000004     4 OBJECT  GLOBAL DEFAULT  COM X
     2: 00000004     4 OBJECT  GLOBAL DEFAULT  COM Y
     3: 00000004     4 OBJECT  GLOBAL DEFAULT  COM Z



---
Diffs of the changes:  (+140 -53)

 ELFWriter.cpp |  193 ++++++++++++++++++++++++++++++++++++++++++----------------
 1 files changed, 140 insertions(+), 53 deletions(-)


Index: llvm/lib/CodeGen/ELFWriter.cpp
diff -u llvm/lib/CodeGen/ELFWriter.cpp:1.1 llvm/lib/CodeGen/ELFWriter.cpp:1.2
--- llvm/lib/CodeGen/ELFWriter.cpp:1.1	Mon Jun 27 01:29:00 2005
+++ llvm/lib/CodeGen/ELFWriter.cpp	Thu Jul  7 02:02:20 2005
@@ -11,17 +11,18 @@
 // the ELF file in the following order:
 //
 //  #1. ELF Header
-//  #2. '.data' section
-//  #3. '.bss' section
+//  #2. '.text' section
+//  #3. '.data' section
+//  #4. '.bss' section  (conceptual position in file)
 //  ...
 //  #X. '.shstrtab' section
 //  #Y. Section Table
 //
 // The entries in the section table are laid out as:
 //  #0. Null entry [required]
-//  #1. ".data" entry - global variables with initializers.     [ if needed ]
-//  #2. ".bss" entry  - global variables without initializers.  [ if needed ]
-//  #3. ".text" entry - the program code
+//  #1. ".text" entry - the program code
+//  #2. ".data" entry - global variables with initializers.     [ if needed ]
+//  #3. ".bss" entry  - global variables without initializers.  [ if needed ]
 //  ...
 //  #N. ".shstrtab" entry - String table for the section names.
 
@@ -83,62 +84,50 @@
   // Add the null section.
   SectionList.push_back(ELFSection());
 
-  // Okay, the ELF header has been completed, emit the .data section next.
-  ELFSection DataSection(".data", OutputBuffer.size());
-  for (Module::global_iterator I = M.global_begin(), E = M.global_end();
-       I != E; ++I)
-    EmitDATASectionGlobal(I);
-
-  // If the .data section is nonempty, add it to our list.
-  if ((DataSection.Size = OutputBuffer.size()-DataSection.Offset)) {
-    DataSection.Align = 4;   // FIXME: Compute!
-    SectionList.push_back(DataSection);
-  }
+  // Start up the symbol table.  The first entry in the symtab is the null
+  // entry.
+  SymbolTable.push_back(ELFSym(0));
 
-  // Okay, emit the .bss section next.
-  ELFSection BSSSection(".bss", OutputBuffer.size());
-  for (Module::global_iterator I = M.global_begin(), E = M.global_end();
-       I != E; ++I)
-    EmitBSSSectionGlobal(I);
 
-  // If the .bss section is nonempty, add it to our list.
-  if ((BSSSection.Size = OutputBuffer.size()-BSSSection.Offset)) {
-    BSSSection.Align = 4;  // FIXME: Compute!
-    SectionList.push_back(BSSSection);
-  }
 
+  // FIXME: Should start the .text section.
   return false;
 }
 
-// isCOMM - A global variable should be emitted to the common area if it is zero
-// initialized and has linkage that permits it to be merged with other globals.
-static bool isCOMM(GlobalVariable *GV) {
-  return GV->getInitializer()->isNullValue() &&
-    (GV->hasLinkOnceLinkage() || GV->hasInternalLinkage() ||
-     GV->hasWeakLinkage());
-}
-
-// EmitDATASectionGlobal - Emit a global variable to the .data section if it
-// belongs there.
-void ELFWriter::EmitDATASectionGlobal(GlobalVariable *GV) {
-  if (!GV->hasInitializer()) return;
-
-  // Do not emit a symbol here if it should be emitted to the common area.
-  if (isCOMM(GV)) return;
-
-  EmitGlobal(GV);
-}
-
-void ELFWriter::EmitBSSSectionGlobal(GlobalVariable *GV) {
-  if (!GV->hasInitializer()) return;
+void ELFWriter::EmitGlobal(GlobalVariable *GV, ELFSection &DataSection,
+                           ELFSection &BSSSection) {
+  // If this is an external global, emit it...
+  assert(GV->hasInitializer() && "FIXME: unimp");
+  
+  // If this global has a zero initializer, it is part of the .bss or common
+  // section.
+  if (GV->getInitializer()->isNullValue()) {
+    // 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()) {
+      ELFSym CommonSym(GV);
+      // Value for common symbols is the alignment required.
+      const Type *GVType = (const Type*)GV->getType();
+      CommonSym.Value = TM.getTargetData().getTypeAlignment(GVType);
+      CommonSym.Size  = TM.getTargetData().getTypeSize(GVType);
+      CommonSym.SetBind(ELFSym::STB_GLOBAL);
+      CommonSym.SetType(ELFSym::STT_OBJECT);
+      // TODO SOMEDAY: add ELF visibility.
+      CommonSym.SectionIdx = ELFSection::SHN_COMMON;
+      SymbolTable.push_back(CommonSym);
+      return;
+    }
 
-  // FIXME: We don't support BSS yet!
-  return;
+    // FIXME: Implement the .bss section.
+    return;
+  }
 
-  EmitGlobal(GV);
-}
+  // FIXME: handle .rodata
+  //assert(!GV->isConstant() && "unimp");
 
-void ELFWriter::EmitGlobal(GlobalVariable *GV) {
+  // FIXME: handle .data
+  //assert(0 && "unimp");
 }
 
 
@@ -149,6 +138,37 @@
 /// doFinalization - Now that the module has been completely processed, emit
 /// the ELF file to 'O'.
 bool ELFWriter::doFinalization(Module &M) {
+  // Okay, the .text section has now been finalized.
+  // FIXME: finalize the .text section.
+
+  // Okay, the ELF header and .text sections have been completed, build the
+  // .data, .bss, and "common" sections next.
+  ELFSection DataSection(".data", OutputBuffer.size());
+  ELFSection BSSSection (".bss");
+  for (Module::global_iterator I = M.global_begin(), E = M.global_end();
+       I != E; ++I)
+    EmitGlobal(I, DataSection, BSSSection);
+
+  // If the .data section is nonempty, add it to our list.
+  if (DataSection.Size) {
+    DataSection.Align = 4;   // FIXME: Compute!
+    // FIXME: Set the right flags and stuff.
+    SectionList.push_back(DataSection);
+  }
+
+  // If the .bss section is nonempty, add it to our list.
+  if (BSSSection.Size) {
+    BSSSection.Offset = OutputBuffer.size();
+    BSSSection.Align = 4;  // FIXME: Compute!
+    // FIXME: Set the right flags and stuff.
+    SectionList.push_back(BSSSection);
+  }
+
+  // Emit the symbol table now, if non-empty.
+  EmitSymbolTable();
+
+  // FIXME: Emit the relocations now.
+
   // Emit the string table for the sections in the ELF file we have.
   EmitSectionTableStringTable();
 
@@ -163,13 +183,80 @@
   return false;
 }
 
+/// 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 (SymbolTable.size() == 1) return;  // Only the null entry.
+
+  // FIXME: compact all local symbols to the start of the symtab.
+  unsigned FirstNonLocalSymbol = 1;
+
+  SectionList.push_back(ELFSection(".strtab", OutputBuffer.size()));
+  ELFSection &StrTab = SectionList.back();
+  StrTab.Type = ELFSection::SHT_STRTAB;
+  StrTab.Align = 1;
+
+  // Set the zero'th symbol to a null byte, as required.
+  outbyte(0);
+  SymbolTable[0].NameIdx = 0;
+  unsigned Index = 1;
+  for (unsigned i = 1, e = SymbolTable.size(); i != e; ++i) {
+    // FIXME: USE A MANGLER!!
+    const std::string &Name = SymbolTable[i].GV->getName();
+
+    if (Name.empty()) {
+      SymbolTable[i].NameIdx = 0;
+    } else {
+      SymbolTable[i].NameIdx = Index;
+
+      // Add the name to the output buffer, including the null terminator.
+      OutputBuffer.insert(OutputBuffer.end(), Name.begin(), Name.end());
+
+      // Add a null terminator.
+      OutputBuffer.push_back(0);
+
+      // Keep track of the number of bytes emitted to this section.
+      Index += Name.size()+1;
+    }
+  }
+
+  StrTab.Size = OutputBuffer.size()-StrTab.Offset;
+
+  // Now that we have emitted the string table and know the offset into the
+  // string table of each symbol, emit the symbol table itself.
+  assert(!is64Bit && "Should this be 8 byte aligned for 64-bit?"
+         " (check .Align below also)");
+  align(4);
+
+  SectionList.push_back(ELFSection(".symtab", OutputBuffer.size()));
+  ELFSection &SymTab = SectionList.back();
+  SymTab.Type = ELFSection::SHT_SYMTAB;
+  SymTab.Align = 4;   // FIXME: check for ELF64
+  SymTab.Link = SectionList.size()-2;  // Section Index of .strtab.
+  SymTab.Info = FirstNonLocalSymbol;   // First non-STB_LOCAL symbol.
+  SymTab.EntSize = 16; // Size of each symtab entry. FIXME: wrong for ELF64
+
+  assert(!is64Bit && "check this!");
+  for (unsigned i = 0, e = SymbolTable.size(); i != e; ++i) {
+    ELFSym &Sym = SymbolTable[i];
+    outword(Sym.NameIdx);
+    outaddr(Sym.Value);
+    outword(Sym.Size);
+    outbyte(Sym.Info);
+    outbyte(Sym.Other);
+    outhalf(Sym.SectionIdx);
+  }
+
+  SymTab.Size = OutputBuffer.size()-SymTab.Offset;
+}
+
 /// EmitSectionTableStringTable - This method adds and emits a section for the
 /// ELF Section Table string table: the string table that holds all of the
 /// section names.
 void ELFWriter::EmitSectionTableStringTable() {
   // First step: add the section for the string table to the list of sections:
   SectionList.push_back(ELFSection(".shstrtab", OutputBuffer.size()));
-  SectionList.back().Type = 3;     // SHT_STRTAB
+  SectionList.back().Type = ELFSection::SHT_STRTAB;
 
   // Now that we know which section number is the .shstrtab section, update the
   // e_shstrndx entry in the ELF header.






More information about the llvm-commits mailing list