add trivial support for passing label definitions through the MCStreamer.
[oota-llvm.git] / lib / CodeGen / ELF.h
index c22f6ed92e7191a4e041b9a61a32960a9282b2be..28b6be8910e525a57ee8ad8444cf1b3e09771739 100644 (file)
 // This header contains common, non-processor-specific data structures and
 // constants for the ELF file format.
 //
-// The details of the ELF32 bits in this file are largely based on
-// the Tool Interface Standard (TIS) Executable and Linking Format
-// (ELF) Specification Version 1.2, May 1995. The ELF64 stuff is not
-// standardized, as far as I can tell. It was largely based on information
-// I found in OpenBSD header files.
+// The details of the ELF32 bits in this file are largely based on the Tool
+// Interface Standard (TIS) Executable and Linking Format (ELF) Specification
+// Version 1.2, May 1995. The ELF64 is based on HP/Intel definition of the
+// ELF-64 object file format document, Version 1.5 Draft 2 May 27, 1998
 //
 //===----------------------------------------------------------------------===//
 
 #ifndef CODEGEN_ELF_H
 #define CODEGEN_ELF_H
 
+#include "llvm/GlobalVariable.h"
+#include "llvm/CodeGen/BinaryObject.h"
 #include "llvm/CodeGen/MachineRelocation.h"
 #include "llvm/Support/DataTypes.h"
 #include <cstring>
 
 namespace llvm {
-  class GlobalVariable;
+  class BinaryObject;
 
   // Identification Indexes
   enum {
@@ -47,71 +48,28 @@ namespace llvm {
     ET_HIPROC = 0xffff  // Processor-specific
   };
 
-  // Object file classes.
-  enum {
-    ELFCLASS32 = 1, // 32-bit object file
-    ELFCLASS64 = 2  // 64-bit object file
-  };
-
-  // Object file byte orderings.
-  enum {
-    ELFDATA2LSB = 1, // Little-endian object file
-    ELFDATA2MSB = 2  // Big-endian object file
-  };
-
   // Versioning
   enum {
     EV_NONE = 0,
     EV_CURRENT = 1
   };
 
-  struct ELFHeader {
-    // e_machine - This field is the target specific value to emit as the
-    // e_machine member of the ELF header.
-    unsigned short e_machine;
-
-    // e_flags - The machine flags for the target.  This defaults to zero.
-    unsigned e_flags;
-
-    // e_size - Holds the ELF header's size in bytes
-    unsigned e_ehsize;
-
-    // Endianess and ELF Class (64 or 32 bits)
-    unsigned ByteOrder;
-    unsigned ElfClass;
-
-    unsigned getByteOrder() const { return ByteOrder; }
-    unsigned getElfClass() const { return ElfClass; }
-    unsigned getSize() const { return e_ehsize; }
-    unsigned getMachine() const { return e_machine; }
-    unsigned getFlags() const { return e_flags; }
-
-    ELFHeader(unsigned short machine, unsigned flags,
-              bool is64Bit, bool isLittleEndian)
-      : e_machine(machine), e_flags(flags) {
-        ElfClass  = is64Bit ? ELFCLASS64 : ELFCLASS32;
-        ByteOrder = isLittleEndian ? ELFDATA2LSB : ELFDATA2MSB;
-        e_ehsize  = is64Bit ? 64 : 52;
-      }
-  };
-
   /// ELFSection - This struct contains information about each section that is
   /// emitted to the file.  This is eventually turned into the section header
   /// table at the end of the file.
-  struct ELFSection {
-
+  class ELFSection : public BinaryObject {
+    public:
     // ELF specific fields
-    std::string Name;       // Name of the section.
-    unsigned NameIdx;       // Index in .shstrtab of name, once emitted.
-    unsigned Type;
-    unsigned Flags;
-    uint64_t Addr;
-    unsigned Offset;
-    unsigned Size;
-    unsigned Link;
-    unsigned Info;
-    unsigned Align;
-    unsigned EntSize;
+    unsigned NameIdx;   // sh_name - .shstrtab idx of name, once emitted.
+    unsigned Type;      // sh_type - Section contents & semantics 
+    unsigned Flags;     // sh_flags - Section flags.
+    uint64_t Addr;      // sh_addr - The mem addr this section is in.
+    unsigned Offset;    // sh_offset - Offset from the file start
+    unsigned Size;      // sh_size - The section size.
+    unsigned Link;      // sh_link - Section header table index link.
+    unsigned Info;      // sh_info - Auxillary information.
+    unsigned Align;     // sh_addralign - Alignment of section.
+    unsigned EntSize;   // sh_entsize - Size of entries in the section e
 
     // Section Header Flags
     enum {
@@ -141,8 +99,8 @@ namespace llvm {
       SHT_REL      = 9,  // Relocation entries; no explicit addends.
       SHT_SHLIB    = 10, // Reserved.
       SHT_DYNSYM   = 11, // Symbol table.
-      SHT_LOPROC   = 0x70000000, // Lowest processor architecture-specific type.
-      SHT_HIPROC   = 0x7fffffff, // Highest processor architecture-specific type.
+      SHT_LOPROC   = 0x70000000, // Lowest processor arch-specific type.
+      SHT_HIPROC   = 0x7fffffff, // Highest processor arch-specific type.
       SHT_LOUSER   = 0x80000000, // Lowest type reserved for applications.
       SHT_HIUSER   = 0xffffffff  // Highest type reserved for applications.
     };
@@ -161,29 +119,22 @@ namespace llvm {
     /// SectionIdx - The number of the section in the Section Table.
     unsigned short SectionIdx;
 
-    /// SectionData - The actual data for this section which we are building
-    /// up for emission to the file.
-    std::vector<unsigned char> SectionData;
-
-    /// Relocations - The relocations that we have encountered so far in this 
-    /// section that we will need to convert to Elf relocation entries when
-    /// the file is written.
-    std::vector<MachineRelocation> Relocations;
-
-    /// Section Header Size 
-    static unsigned getSectionHdrSize(bool is64Bit)
-      { return is64Bit ? 64 : 40; }
-
-    ELFSection(const std::string &name)
-      : Name(name), Type(0), Flags(0), Addr(0), Offset(0), Size(0),
-        Link(0), Info(0), Align(0), EntSize(0) {}
+    ELFSection(const std::string &name, bool isLittleEndian, bool is64Bit)
+      : BinaryObject(name, isLittleEndian, is64Bit), Type(0), Flags(0), Addr(0),
+        Offset(0), Size(0), Link(0), Info(0), Align(0), EntSize(0) {}
   };
 
   /// ELFSym - This struct contains information about each symbol that is
   /// added to logical symbol table for the module.  This is eventually
   /// turned into a real symbol table in the file.
   struct ELFSym {
-    const GlobalValue *GV;    // The global value this corresponds to.
+    // The global value this corresponds to. Global symbols can be on of the 
+    // 3 types : if this symbol has a zero initializer, it is common or should
+    // be placed in bss section otherwise it's a constant.
+    const GlobalValue *GV;
+    bool IsCommon;
+    bool IsBss;
+    bool IsConstant;
 
     // ELF specific fields
     unsigned NameIdx;         // Index in .strtab of name, once emitted.
@@ -207,20 +158,76 @@ namespace llvm {
       STT_FILE = 4 
     };
 
-    ELFSym(const GlobalValue *gv) : GV(gv), NameIdx(0), Value(0),
-                                    Size(0), Info(0), Other(0),
-                                    SectionIdx(ELFSection::SHN_UNDEF) {}
+    enum {
+      STV_DEFAULT = 0,  // Visibility is specified by binding type
+      STV_INTERNAL = 1, // Defined by processor supplements
+      STV_HIDDEN = 2,   // Not visible to other components
+      STV_PROTECTED = 3 // Visible in other components but not preemptable
+    };
 
-    void SetBind(unsigned X) {
+    ELFSym(const GlobalValue *gv) : GV(gv), IsCommon(false), IsBss(false),
+                                    IsConstant(false), NameIdx(0), Value(0),
+                                    Size(0), Info(0), Other(STV_DEFAULT),
+                                    SectionIdx(ELFSection::SHN_UNDEF) {
+      if (!GV)
+        return;
+
+      switch (GV->getVisibility()) {
+      default:
+        assert(0 && "unknown visibility type");
+      case GlobalValue::DefaultVisibility:
+        Other = STV_DEFAULT;
+        break;
+      case GlobalValue::HiddenVisibility:
+        Other = STV_HIDDEN;
+        break;
+      case GlobalValue::ProtectedVisibility:
+        Other = STV_PROTECTED;
+        break;
+      }
+    }
+
+    unsigned getBind() {
+      return (Info >> 4) & 0xf;
+    }
+
+    void setBind(unsigned X) {
       assert(X == (X & 0xF) && "Bind value out of range!");
       Info = (Info & 0x0F) | (X << 4);
     }
-    void SetType(unsigned X) {
+    void setType(unsigned X) {
       assert(X == (X & 0xF) && "Type value out of range!");
       Info = (Info & 0xF0) | X;
     }
   };
 
+  /// ELFRelocation - This class contains all the information necessary to
+  /// to generate any 32-bit or 64-bit ELF relocation entry.
+  class ELFRelocation {
+    uint64_t r_offset;    // offset in the section of the object this applies to
+    uint32_t r_symidx;    // symbol table index of the symbol to use
+    uint32_t r_type;      // machine specific relocation type
+    int64_t  r_add;       // explicit relocation addend
+    bool     r_rela;      // if true then the addend is part of the entry
+                          // otherwise the addend is at the location specified
+                          // by r_offset
+  public:
+    uint64_t getInfo(bool is64Bit) const {
+      if (is64Bit)
+        return ((uint64_t)r_symidx << 32) + ((uint64_t)r_type & 0xFFFFFFFFL);
+      else
+        return (r_symidx << 8)  + (r_type & 0xFFL);
+    }
+
+    uint64_t getOffset() const { return r_offset; }
+    int64_t getAddend() const { return r_add; }
+
+    ELFRelocation(uint64_t off, uint32_t sym, uint32_t type,
+                  bool rela = true, int64_t addend = 0) :
+      r_offset(off), r_symidx(sym), r_type(type),
+      r_add(addend), r_rela(rela) {}
+  };
+
 } // end namespace llvm
 
 #endif