[llvm] r221150 - Emit .eh_frame with relocations to functions, rather than sections

Oliver Stannard oliver.stannard at arm.com
Mon Nov 3 04:02:52 PST 2014


Author: olista01
Date: Mon Nov  3 06:02:51 2014
New Revision: 221150

URL: http://llvm.org/viewvc/llvm-project?rev=221150&view=rev
Log:
Emit .eh_frame with relocations to functions, rather than sections

When LLVM emits DWARF call frame information, it currently creates a local,
section-relative symbol in the code section, which is pointed to by a
relocation on the .eh_frame section. However, for C++ we emit some functions in
section groups, and the SysV ABI has some rules to make it easier to remove
these sections
(http://www.sco.com/developers/gabi/latest/ch4.sheader.html#section_group_rules):

  A symbol table entry with STB_LOCAL binding that is defined relative to one
  of a group's sections, and that is contained in a symbol table section that is
  not part of the group, must be discarded if the group members are discarded.
  References to this symbol table entry from outside the group are not allowed.

This means that we need to use the function symbol for the relocation, not a
temporary symbol.

There was a comment in the code claiming that the local symbol was used to
avoid creating a relocation, but a relocation must be created anyway as the
code and CFI are in different sections.


Modified:
    llvm/trunk/include/llvm/MC/MCObjectStreamer.h
    llvm/trunk/include/llvm/MC/MCStreamer.h
    llvm/trunk/lib/CodeGen/AsmPrinter/ARMException.cpp
    llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp
    llvm/trunk/lib/MC/MCAsmStreamer.cpp
    llvm/trunk/lib/MC/MCObjectStreamer.cpp
    llvm/trunk/lib/MC/MCParser/AsmParser.cpp
    llvm/trunk/lib/MC/MCStreamer.cpp
    llvm/trunk/test/DebugInfo/AArch64/eh_frame.s
    llvm/trunk/test/DebugInfo/AArch64/eh_frame_personality.ll

Modified: llvm/trunk/include/llvm/MC/MCObjectStreamer.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCObjectStreamer.h?rev=221150&r1=221149&r2=221150&view=diff
==============================================================================
--- llvm/trunk/include/llvm/MC/MCObjectStreamer.h (original)
+++ llvm/trunk/include/llvm/MC/MCObjectStreamer.h Mon Nov  3 06:02:51 2014
@@ -41,7 +41,8 @@ class MCObjectStreamer : public MCStream
   SmallVector<MCSymbolData *, 2> PendingLabels;
 
   virtual void EmitInstToData(const MCInst &Inst, const MCSubtargetInfo&) = 0;
-  void EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) override;
+  void EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame,
+                            MCSymbol *FuncSym) override;
   void EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) override;
 
   // If any labels have been emitted but not assigned fragments, ensure that

Modified: llvm/trunk/include/llvm/MC/MCStreamer.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCStreamer.h?rev=221150&r1=221149&r2=221150&view=diff
==============================================================================
--- llvm/trunk/include/llvm/MC/MCStreamer.h (original)
+++ llvm/trunk/include/llvm/MC/MCStreamer.h Mon Nov  3 06:02:51 2014
@@ -198,7 +198,7 @@ class MCStreamer {
 protected:
   MCStreamer(MCContext &Ctx);
 
-  virtual void EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame);
+  virtual void EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame, MCSymbol *FuncSym);
   virtual void EmitCFIEndProcImpl(MCDwarfFrameInfo &CurFrame);
 
   WinEH::FrameInfo *getCurrentWinFrameInfo() {
@@ -661,7 +661,7 @@ public:
 
   virtual MCSymbol *getDwarfLineTableSymbol(unsigned CUID);
   virtual void EmitCFISections(bool EH, bool Debug);
-  void EmitCFIStartProc(bool IsSimple);
+  void EmitCFIStartProc(bool IsSimple, MCSymbol *FuncSym);
   void EmitCFIEndProc();
   virtual void EmitCFIDefCfa(int64_t Register, int64_t Offset);
   virtual void EmitCFIDefCfaOffset(int64_t Offset);

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/ARMException.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/ARMException.cpp?rev=221150&r1=221149&r2=221150&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/ARMException.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/ARMException.cpp Mon Nov  3 06:02:51 2014
@@ -66,7 +66,7 @@ void ARMException::beginFunction(const M
          "non-EH CFI not yet supported in prologue with EHABI lowering");
   if (MoveType == AsmPrinter::CFI_M_Debug) {
     shouldEmitCFI = true;
-    Asm->OutStreamer.EmitCFIStartProc(false);
+    Asm->OutStreamer.EmitCFIStartProc(false, Asm->CurrentFnSym);
   }
 }
 

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp?rev=221150&r1=221149&r2=221150&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp Mon Nov  3 06:02:51 2014
@@ -102,7 +102,7 @@ void DwarfCFIException::beginFunction(co
   if (!shouldEmitPersonality && !shouldEmitMoves)
     return;
 
-  Asm->OutStreamer.EmitCFIStartProc(/*IsSimple=*/false);
+  Asm->OutStreamer.EmitCFIStartProc(/*IsSimple=*/false, Asm->CurrentFnSym);
 
   // Indicate personality routine, if any.
   if (!shouldEmitPersonality)

Modified: llvm/trunk/lib/MC/MCAsmStreamer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCAsmStreamer.cpp?rev=221150&r1=221149&r2=221150&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCAsmStreamer.cpp (original)
+++ llvm/trunk/lib/MC/MCAsmStreamer.cpp Mon Nov  3 06:02:51 2014
@@ -54,7 +54,8 @@ private:
   unsigned UseDwarfDirectory : 1;
 
   void EmitRegisterName(int64_t Register);
-  void EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) override;
+  void EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame,
+                            MCSymbol *FuncSym) override;
   void EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) override;
 
 public:
@@ -925,7 +926,8 @@ void MCAsmStreamer::EmitCFISections(bool
   EmitEOL();
 }
 
-void MCAsmStreamer::EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) {
+void MCAsmStreamer::EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame,
+                                         MCSymbol *FuncSym) {
   OS << "\t.cfi_startproc";
   if (Frame.IsSimple)
     OS << " simple";

Modified: llvm/trunk/lib/MC/MCObjectStreamer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCObjectStreamer.cpp?rev=221150&r1=221149&r2=221150&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCObjectStreamer.cpp (original)
+++ llvm/trunk/lib/MC/MCObjectStreamer.cpp Mon Nov  3 06:02:51 2014
@@ -128,10 +128,13 @@ void MCObjectStreamer::EmitValueImpl(con
   DF->getContents().resize(DF->getContents().size() + Size, 0);
 }
 
-void MCObjectStreamer::EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) {
-  // We need to create a local symbol to avoid relocations.
-  Frame.Begin = getContext().CreateTempSymbol();
-  EmitLabel(Frame.Begin);
+void MCObjectStreamer::EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame,
+                                            MCSymbol *FuncSym) {
+  if (!FuncSym) {
+    FuncSym = getContext().CreateTempSymbol();
+    EmitLabel(FuncSym);
+  }
+  Frame.Begin = FuncSym;
 }
 
 void MCObjectStreamer::EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) {

Modified: llvm/trunk/lib/MC/MCParser/AsmParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCParser/AsmParser.cpp?rev=221150&r1=221149&r2=221150&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCParser/AsmParser.cpp (original)
+++ llvm/trunk/lib/MC/MCParser/AsmParser.cpp Mon Nov  3 06:02:51 2014
@@ -172,6 +172,9 @@ private:
   /// \brief Are we parsing ms-style inline assembly?
   bool ParsingInlineAsm;
 
+  /// \brief The last symbol we emitted, used for call frame information.
+  MCSymbol *LastFuncSymbol;
+
 public:
   AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
             const MCAsmInfo &MAI);
@@ -491,7 +494,8 @@ AsmParser::AsmParser(SourceMgr &_SM, MCC
     : Lexer(_MAI), Ctx(_Ctx), Out(_Out), MAI(_MAI), SrcMgr(_SM),
       PlatformParser(nullptr), CurBuffer(_SM.getMainFileID()),
       MacrosEnabledFlag(true), HadError(false), CppHashLineNumber(0),
-      AssemblerDialect(~0U), IsDarwin(false), ParsingInlineAsm(false) {
+      AssemblerDialect(~0U), IsDarwin(false), ParsingInlineAsm(false),
+      LastFuncSymbol(nullptr) {
   // Save the old handler.
   SavedDiagHandler = SrcMgr.getDiagHandler();
   SavedDiagContext = SrcMgr.getDiagContext();
@@ -1305,6 +1309,9 @@ bool AsmParser::parseStatement(ParseStat
     if (!ParsingInlineAsm)
       Out.EmitLabel(Sym);
 
+    // Record the symbol, so that it can be used for call frame information
+    LastFuncSymbol = Sym;
+
     // If we are generating dwarf for assembly source files then gather the
     // info to make a dwarf label entry for this label if needed.
     if (getContext().getGenDwarfForAssembly())
@@ -2961,7 +2968,7 @@ bool AsmParser::parseDirectiveCFIStartPr
     if (parseIdentifier(Simple) || Simple != "simple")
       return TokError("unexpected token in .cfi_startproc directive");
 
-  getStreamer().EmitCFIStartProc(!Simple.empty());
+  getStreamer().EmitCFIStartProc(!Simple.empty(), LastFuncSymbol);
   return false;
 }
 

Modified: llvm/trunk/lib/MC/MCStreamer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCStreamer.cpp?rev=221150&r1=221149&r2=221150&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCStreamer.cpp (original)
+++ llvm/trunk/lib/MC/MCStreamer.cpp Mon Nov  3 06:02:51 2014
@@ -211,14 +211,14 @@ void MCStreamer::EmitCFISections(bool EH
   assert(EH || Debug);
 }
 
-void MCStreamer::EmitCFIStartProc(bool IsSimple) {
+void MCStreamer::EmitCFIStartProc(bool IsSimple, MCSymbol *FuncSym) {
   MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
   if (CurFrame && !CurFrame->End)
     report_fatal_error("Starting a frame before finishing the previous one!");
 
   MCDwarfFrameInfo Frame;
   Frame.IsSimple = IsSimple;
-  EmitCFIStartProcImpl(Frame);
+  EmitCFIStartProcImpl(Frame, FuncSym);
 
   const MCAsmInfo* MAI = Context.getAsmInfo();
   if (MAI) {
@@ -233,8 +233,8 @@ void MCStreamer::EmitCFIStartProc(bool I
   DwarfFrameInfos.push_back(Frame);
 }
 
-void MCStreamer::EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) {
-}
+void MCStreamer::EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame,
+                                      MCSymbol *FuncSym) {}
 
 void MCStreamer::EmitCFIEndProc() {
   EnsureValidDwarfFrame();

Modified: llvm/trunk/test/DebugInfo/AArch64/eh_frame.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/AArch64/eh_frame.s?rev=221150&r1=221149&r2=221150&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/AArch64/eh_frame.s (original)
+++ llvm/trunk/test/DebugInfo/AArch64/eh_frame.s Mon Nov  3 06:02:51 2014
@@ -1,5 +1,6 @@
 // RUN: llvm-mc -triple aarch64-none-linux-gnu -filetype=obj %s -o %t
-// RUN: llvm-objdump -s %t | FileCheck %s
+// RUN: llvm-objdump -s %t | FileCheck %s --check-prefix=CHECK
+// RUN: llvm-readobj -r %t | FileCheck %s --check-prefix=RELOC
         .text
         .globl foo
         .type foo, at function
@@ -46,3 +47,11 @@ foo:
 // 00000000: PC begin for this FDE is at 00000000 (relocation is applied here)
 // 04000000: FDE applies up to PC begin+0x14
 // 00: Augmentation string length 0 for this FDE
+
+
+// Check the relocations applied to the .eh_frame section.
+// These must not contain section-relative relocations to a section which
+// is part of a group, as it could be removed.
+// RELOC: Section ({{[0-9]+}}) .rela.eh_frame {
+// RELOC-NEXT:   0x{{[0-9A-F]+}} R_AARCH64_PREL32 foo 0x0
+// RELOC-NEXT: }

Modified: llvm/trunk/test/DebugInfo/AArch64/eh_frame_personality.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/AArch64/eh_frame_personality.ll?rev=221150&r1=221149&r2=221150&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/AArch64/eh_frame_personality.ll (original)
+++ llvm/trunk/test/DebugInfo/AArch64/eh_frame_personality.ll Mon Nov  3 06:02:51 2014
@@ -1,5 +1,6 @@
 ; RUN: llc -verify-machineinstrs -mtriple=aarch64-none-linux-gnu %s -filetype=obj -o %t
-; RUN: llvm-objdump -s %t | FileCheck %s
+; RUN: llvm-objdump -s %t | FileCheck %s --check-prefix=CHECK
+; RUN: llvm-readobj -r %t | FileCheck %s --check-prefix=RELOC
 
 declare i32 @__gxx_personality_v0(...)
 
@@ -44,3 +45,12 @@ clean:
 ; 00: Second part of aug (language-specific data): absolute pointer format used
 ; 1b: pointer format: pc-relative signed 4-byte. Just like GNU.
 ; 0c 1f 00: Initial instructions ("DW_CFA_def_cfa x31 ofs 0" in this case)
+
+; Check the relocations applied to the .eh_frame section.
+; These must not contain section-relative relocations to a section which
+; is part of a group, as it could be removed.
+; RELOC: Section ({{[0-9]+}}) .rela.eh_frame {
+; RELOC-NEXT:   0x{{[0-9A-F]+}} R_AARCH64_ABS64 __gxx_personality_v0 0x0
+; RELOC-NEXT:   0x{{[0-9A-F]+}} R_AARCH64_PREL32 foo 0x0
+; RELOC-NEXT:   0x{{[0-9A-F]+}} R_AARCH64_ABS64 .gcc_except_table 0x0
+; RELOC-NEXT: }





More information about the llvm-commits mailing list