Enable DebugInfo support for COFF object files.
authorDevang Patel <dpatel@apple.com>
Thu, 24 Feb 2011 21:04:00 +0000 (21:04 +0000)
committerDevang Patel <dpatel@apple.com>
Thu, 24 Feb 2011 21:04:00 +0000 (21:04 +0000)
Patch by Nathan Jeffords!

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@126425 91177308-0d34-0410-b5e6-96231b3b80d8

19 files changed:
include/llvm/MC/MCStreamer.h
lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp
lib/CodeGen/AsmPrinter/DIE.cpp
lib/CodeGen/AsmPrinter/DIE.h
lib/CodeGen/AsmPrinter/DwarfDebug.cpp
lib/CodeGen/AsmPrinter/DwarfDebug.h
lib/MC/MCAsmInfoCOFF.cpp
lib/MC/MCAsmStreamer.cpp
lib/MC/MCELFStreamer.cpp
lib/MC/MCLoggingStreamer.cpp
lib/MC/MCMachOStreamer.cpp
lib/MC/MCNullStreamer.cpp
lib/MC/MCPureStreamer.cpp
lib/MC/WinCOFFObjectWriter.cpp
lib/MC/WinCOFFStreamer.cpp
lib/Target/PTX/PTXMCAsmStreamer.cpp
lib/Target/X86/X86AsmBackend.cpp
lib/Target/X86/X86FixupKinds.h
lib/Target/X86/X86MCAsmInfo.cpp

index 4451199b7fb378e8a46d64fb53da99ed76076d8f..c5bc947b960cca70dcb11f5c76d73bcd02cb0b14 100644 (file)
@@ -239,6 +239,11 @@ namespace llvm {
     /// EndCOFFSymbolDef - Marks the end of the symbol definition.
     virtual void EndCOFFSymbolDef() = 0;
 
+    /// EmitCOFFSecRel32 - Emits a COFF section relative relocation.
+    ///
+    /// @param Symbol - Symbol the section relative realocation should point to.
+    virtual void EmitCOFFSecRel32(MCSymbol const *Symbol) = 0;
+
     /// EmitELFSize - Emit an ELF .size directive.
     ///
     /// This corresponds to an assembler statement such as:
index 98a1bf2f1ce4f8218a52c7b460acbfdc57b6b64b..9c2326cc1f18dd7f35e0303ed18a6bb73f466a25 100644 (file)
@@ -178,8 +178,7 @@ void AsmPrinter::EmitSectionOffset(const MCSymbol *Label,
                                    const MCSymbol *SectionLabel) const {
   // On COFF targets, we have to emit the special .secrel32 directive.
   if (const char *SecOffDir = MAI->getDwarfSectionOffsetDirective()) {
-    // FIXME: MCize.
-    OutStreamer.EmitRawText(SecOffDir + Twine(Label->getName()));
+    OutStreamer.EmitCOFFSecRel32(Label);
     return;
   }
   
index 21396ca37f065dc90b3eea635e61d65d5f7c44df..ff3c6da084b815a1ade18bea285103004c8ccf7f 100644 (file)
@@ -276,6 +276,29 @@ void DIELabel::print(raw_ostream &O) {
 }
 #endif
 
+//===----------------------------------------------------------------------===//
+// DIESectionOffset Implementation
+//===----------------------------------------------------------------------===//
+
+/// EmitValue - Emit label value.
+///
+void DIESectionOffset::EmitValue(AsmPrinter *AP, unsigned Form) const {
+  AP->EmitSectionOffset (Label, Label);
+}
+
+/// SizeOf - Determine size of label value in bytes.
+///
+unsigned DIESectionOffset::SizeOf(AsmPrinter *AP, unsigned Form) const {
+  if (Form == dwarf::DW_FORM_data4) return 4;
+  return AP->getTargetData().getPointerSize();
+}
+
+#ifndef NDEBUG
+void DIESectionOffset::print(raw_ostream &O) {
+  O << "SecRelLbl: " << Label->getName();
+}
+#endif
+
 //===----------------------------------------------------------------------===//
 // DIEDelta Implementation
 //===----------------------------------------------------------------------===//
index d56c0947795e058e3306cf6afc31bcd23030fee8..bf5768a4361eed0ecfa214d861b9d9aea5c7268c 100644 (file)
@@ -327,6 +327,36 @@ namespace llvm {
     static bool classof(const DIELabel *)  { return true; }
     static bool classof(const DIEValue *L) { return L->getType() == isLabel; }
 
+#ifndef NDEBUG
+    virtual void print(raw_ostream &O);
+#endif
+  };
+
+  //===--------------------------------------------------------------------===//
+  /// DIESectionOffset - A section relative label expression DIE.
+  //
+  class DIESectionOffset : public DIEValue {
+    const MCSymbol *Label;
+  public:
+    explicit DIESectionOffset(const MCSymbol *L) : DIEValue(isSectionOffset),
+      Label(L) {}
+
+    /// EmitValue - Emit label value.
+    ///
+    virtual void EmitValue(AsmPrinter *AP, unsigned Form) const;
+
+    /// getValue - Get MCSymbol.
+    ///
+    const MCSymbol *getValue()       const { return Label; }
+
+    /// SizeOf - Determine size of label value in bytes.
+    ///
+    virtual unsigned SizeOf(AsmPrinter *AP, unsigned Form) const;
+
+    // Implement isa/cast/dyncast.
+    static bool classof(const DIELabel *)  { return true; }
+    static bool classof(const DIEValue *L) { return L->getType() == isSectionOffset; }
+
 #ifndef NDEBUG
     virtual void print(raw_ostream &O);
 #endif
index 780fa405ef5122e1590956e9cfca6cedbe496880..9678078e76e571e0ec45dea36e21da43d1403f31 100644 (file)
@@ -481,6 +481,15 @@ void DwarfDebug::addLabel(DIE *Die, unsigned Attribute, unsigned Form,
   Die->addValue(Attribute, Form, Value);
 }
 
+/// addSectionOffset - Add a Dwarf section relative label attribute data and
+/// value.
+///
+void DwarfDebug::addSectionOffset(DIE *Die, unsigned Attribute, unsigned Form,
+                          const MCSymbol *Label) {
+  DIEValue *Value = new (DIEValueAllocator) DIESectionOffset(Label);
+  Die->addValue(Attribute, Form, Value);
+}
+
 /// addDelta - Add a label delta attribute data and value.
 ///
 void DwarfDebug::addDelta(DIE *Die, unsigned Attribute, unsigned Form,
@@ -1904,8 +1913,8 @@ void DwarfDebug::constructCompileUnit(const MDNode *N) {
   // DW_AT_stmt_list is a offset of line number information for this
   // compile unit in debug_line section.
   if (Asm->MAI->doesDwarfUsesAbsoluteLabelForStmtList())
-    addLabel(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_addr,
-             Asm->GetTempSymbol("section_line"));
+    addSectionOffset(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_addr,
+                     Asm->GetTempSymbol("section_line"));
   else
     addUInt(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4, 0);
 
index 7df0510fbfba581b5bba0b2c7d533b2529797ac7..2e920f502a2947cff057bdfb28614e8ca21cdcdf 100644 (file)
@@ -280,6 +280,12 @@ private:
   void addLabel(DIE *Die, unsigned Attribute, unsigned Form,
                 const MCSymbol *Label);
 
+  /// addSectionOffset - Add a Dwarf section relative label attribute data and
+  /// value.
+  ///
+  void addSectionOffset(DIE *Die, unsigned Attribute, unsigned Form,
+                const MCSymbol *Label);
+
   /// addDelta - Add a label delta attribute data and value.
   ///
   void addDelta(DIE *Die, unsigned Attribute, unsigned Form,
index 7fc7d7abb232c8283ce663fe7dbfb1d60b68a4f8..f6e240572b19df8afd824d307cd057bb7352da38 100644 (file)
@@ -33,5 +33,6 @@ MCAsmInfoCOFF::MCAsmInfoCOFF() {
   HasLEB128 = true;  // Target asm supports leb128 directives (little-endian)
   SupportsDebugInformation = true;
   DwarfSectionOffsetDirective = "\t.secrel32\t";
+  DwarfUsesAbsoluteLabelForStmtList = false;
   HasMicrosoftFastStdCallMangling = true;
 }
index 8d0698216f60e5c62cebe245c4f84fdee30b49a0..64fa8dd5f809b1c814ff516bbc4f1f9db420fd2d 100644 (file)
@@ -135,6 +135,7 @@ public:
   virtual void EmitCOFFSymbolStorageClass(int StorageClass);
   virtual void EmitCOFFSymbolType(int Type);
   virtual void EndCOFFSymbolDef();
+  virtual void EmitCOFFSecRel32(MCSymbol const *Symbol);
   virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value);
   virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
                                 unsigned ByteAlignment);
@@ -384,6 +385,11 @@ void MCAsmStreamer::EndCOFFSymbolDef() {
   EmitEOL();
 }
 
+void MCAsmStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol) {
+  OS << "\t.secrel32\t" << *Symbol << '\n';
+  EmitEOL();
+}
+
 void MCAsmStreamer::EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) {
   assert(MAI.hasDotTypeDotSizeDirective());
   OS << "\t.size\t" << *Symbol << ", " << *Value << '\n';
index e49074da399458f703100a26b9f853ced2c8bf55..bd55055333c00f11e29d739e68fbd9c388f23bde 100644 (file)
@@ -108,6 +108,10 @@ public:
     assert(0 && "ELF doesn't support this directive");
   }
 
+  virtual void EmitCOFFSecRel32(MCSymbol const *Symbol) {
+    assert(0 && "ELF doesn't support this directive");
+  }
+
   virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) {
      MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol);
      SD.setSize(Value);
index 012c7f62f8afabdcc95bf9efcdbf6020a82747ae..bb01167327e458b8999bf1585668badd26329a14 100644 (file)
@@ -120,6 +120,11 @@ public:
     return Child->EndCOFFSymbolDef();
   }
 
+  virtual void EmitCOFFSecRel32(MCSymbol const *Symbol) {
+    LogCall("EndCOFFSymbolDef");
+    return Child->EmitCOFFSecRel32(Symbol);
+  }
+
   virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) {
     LogCall("EmitELFSize");
     return Child->EmitELFSize(Symbol, Value);
index d1f9f5cd568e7a6ff2e4d2425ba07cb882b6c82e..a21dc1987d2981ee7777772f938247416a765c45 100644 (file)
@@ -63,6 +63,9 @@ public:
   virtual void EndCOFFSymbolDef() {
     assert(0 && "macho doesn't support this directive");
   }
+  virtual void EmitCOFFSecRel32(MCSymbol const *Symbol) {
+    assert(0 && "macho doesn't support this directive");
+  }
   virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) {
     assert(0 && "macho doesn't support this directive");
   }
index 08ddf01d1a36ad671bfb5444e11d256a64cf693f..25844e49799086a67e8f6aa25a8d0723dc6262a9 100644 (file)
@@ -54,6 +54,7 @@ namespace {
     virtual void EmitCOFFSymbolStorageClass(int StorageClass) {}
     virtual void EmitCOFFSymbolType(int Type) {}
     virtual void EndCOFFSymbolDef() {}
+    virtual void EmitCOFFSecRel32(MCSymbol const *Symbol) {}
 
     virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) {}
     virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
index 6098e6b8f38bb6f353aa5b0465aefe2304f82bdb..9e80b3bafdcdd7f6045f6360eb230e6c9920d077 100644 (file)
@@ -83,6 +83,9 @@ public:
   virtual void EndCOFFSymbolDef() {
     report_fatal_error("unsupported directive in pure streamer");
   }
+  virtual void EmitCOFFSecRel32(MCSymbol const *Symbol) {
+    report_fatal_error("unsupported directive in pure streamer");
+  }
   virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) {
     report_fatal_error("unsupported directive in pure streamer");
   }
index 6ca5d37fc32efcdfa1e1c230d1360cf2fca28cab..dca4cdd6e7a22a1a601918952fd4b74d0f6128e8 100644 (file)
@@ -705,6 +705,10 @@ void WinCOFFObjectWriter::RecordRelocation(const MCAssembler &Asm,
     else
       llvm_unreachable("unsupported relocation type");
     break;
+  case X86::reloc_coff_secrel32:
+    Reloc.Data.Type = Is64Bit ? COFF::IMAGE_REL_AMD64_SREL32
+                              : COFF::IMAGE_REL_I386_SECREL;
+    break;
   default:
     llvm_unreachable("unsupported relocation type");
   }
index 46968e601be75505bcb1f3e0896fe1db39768747..ebcf24aa8a30c6f119039df821aec198a3ad0b15 100644 (file)
@@ -31,6 +31,9 @@
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/raw_ostream.h"
+
+#include "../Target/X86/X86FixupKinds.h"
+
 using namespace llvm;
 
 namespace {
@@ -59,6 +62,7 @@ public:
   virtual void EmitCOFFSymbolStorageClass(int StorageClass);
   virtual void EmitCOFFSymbolType(int Type);
   virtual void EndCOFFSymbolDef();
+  virtual void EmitCOFFSecRel32(MCSymbol const *Symbol);
   virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value);
   virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
                                 unsigned ByteAlignment);
@@ -290,6 +294,16 @@ void WinCOFFStreamer::EndCOFFSymbolDef() {
   CurSymbol = NULL;
 }
 
+void WinCOFFStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol)
+{
+  MCDataFragment *DF = getOrCreateDataFragment();
+
+  DF->addFixup(MCFixup::Create(DF->getContents().size(),
+                               MCSymbolRefExpr::Create (Symbol, getContext ()),
+                               (MCFixupKind)X86::reloc_coff_secrel32));
+  DF->getContents().resize(DF->getContents().size() + 4, 0);
+}
+
 void WinCOFFStreamer::EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) {
   llvm_unreachable("not implemented");
 }
@@ -368,6 +382,10 @@ void WinCOFFStreamer::EmitInstruction(const MCInst &Instruction) {
 
   getCurrentSectionData()->setHasInstructions(true);
 
+  // Now that a machine instruction has been assembled into this section, make
+  // a line entry for any .loc directive that has been seen.
+  MCLineEntry::Make(this, getCurrentSection());
+
   MCInstFragment *Fragment =
     new MCInstFragment(Instruction, getCurrentSectionData());
 
index 0886ba8008f34152e88bff2772875419bddaa3f2..da62ebf39b5f99b5411b8addcdda30f360e14e29 100644 (file)
@@ -124,6 +124,7 @@ public:
   virtual void EmitCOFFSymbolStorageClass(int StorageClass);
   virtual void EmitCOFFSymbolType(int Type);
   virtual void EndCOFFSymbolDef();
+  virtual void EmitCOFFSecRel32(MCSymbol const *Symbol);
   virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value);
   virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
                                 unsigned ByteAlignment);
@@ -277,6 +278,8 @@ void PTXMCAsmStreamer::EmitCOFFSymbolType (int Type) {}
 
 void PTXMCAsmStreamer::EndCOFFSymbolDef() {}
 
+void PTXMCAsmStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol) {}
+
 void PTXMCAsmStreamer::EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) {}
 
 void PTXMCAsmStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
index da5f5b182ce95f26cb72b5519520140f72c8f7d8..6a0b059ca5a8fb8091c440889588057f3088bb8f 100644 (file)
@@ -40,6 +40,7 @@ static unsigned getFixupKindLog2Size(unsigned Kind) {
   case X86::reloc_riprel_4byte_movq_load:
   case X86::reloc_signed_4byte:
   case X86::reloc_global_offset_table:
+  case X86::reloc_coff_secrel32:
   case FK_Data_4: return 2;
   case FK_PCRel_8:
   case FK_Data_8: return 3;
@@ -69,7 +70,8 @@ public:
       { "reloc_riprel_4byte", 0, 4 * 8, MCFixupKindInfo::FKF_IsPCRel },
       { "reloc_riprel_4byte_movq_load", 0, 4 * 8, MCFixupKindInfo::FKF_IsPCRel},
       { "reloc_signed_4byte", 0, 4 * 8, 0},
-      { "reloc_global_offset_table", 0, 4 * 8, 0}
+      { "reloc_global_offset_table", 0, 4 * 8, 0},
+      { "reloc_coff_secrel32", 0, 4 * 8, 0}
     };
 
     if (Kind < FirstTargetFixupKind)
index 17d242ab761e3579a834a1ac653a640df1b39e35..d6cb39ae9a736307e206bc458a9e20df4758c43c 100644 (file)
@@ -23,6 +23,8 @@ enum Fixups {
   reloc_global_offset_table,                 // 32-bit, relative to the start
                                              // of the instruction. Used only
                                              // for _GLOBAL_OFFSET_TABLE_.
+  reloc_coff_secrel32,                       // PE-COFF section relative 32
+                                             // (only valid for win32 COFF)
   // Marker
   LastTargetFixupKind,
   NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind
index 6686214e06f57f134b8e3e269ab09d832be5bbdb..75bc1ed2bee691562824b622d806c0f8ddf99c76 100644 (file)
@@ -113,4 +113,7 @@ X86MCAsmInfoCOFF::X86MCAsmInfoCOFF(const Triple &Triple) {
   AssemblerDialect = AsmWriterFlavor;
 
   TextAlignFillValue = 0x90;
+  
+  // Debug Information
+  SupportsDebugInformation = true;
 }