[llvm] r202785 - llvm-objdump: Print x64 unwind info in executable.

Rui Ueyama ruiu at google.com
Mon Mar 3 20:00:56 PST 2014


Author: ruiu
Date: Mon Mar  3 22:00:55 2014
New Revision: 202785

URL: http://llvm.org/viewvc/llvm-project?rev=202785&view=rev
Log:
llvm-objdump: Print x64 unwind info in executable.

The original code does not work correctly on executable files because the
code is written in such a way that only object files are assumed to be given
to llvm-objdump.

Contents of RuntimeFunction are different between executables and objects. In
executables, fields in RuntimeFunction have actual addresses to unwind info
structures. On the other hand, in object files, the fields have zero value,
but instead there are relocations pointing to the fields, so that Linker will
fill them at link-time.

So, when we are reading an object file, we need to use relocation info to
find the location of unwind info. When executable, we should just look at the
values in RuntimeFunction.

Added:
    llvm/trunk/test/tools/llvm-objdump/Inputs/win64-unwind.exe.coff-x86_64.exe
    llvm/trunk/test/tools/llvm-objdump/Inputs/win64-unwind.exe.coff-x86_64.obj
      - copied, changed from r202783, llvm/trunk/test/tools/llvm-objdump/Inputs/win64-unwind.exe.coff-x86_64
Removed:
    llvm/trunk/test/tools/llvm-objdump/Inputs/win64-unwind.exe.coff-x86_64
Modified:
    llvm/trunk/test/tools/llvm-objdump/win64-unwind-data.test
    llvm/trunk/tools/llvm-objdump/COFFDump.cpp

Removed: llvm/trunk/test/tools/llvm-objdump/Inputs/win64-unwind.exe.coff-x86_64
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-objdump/Inputs/win64-unwind.exe.coff-x86_64?rev=202784&view=auto
==============================================================================
Binary files llvm/trunk/test/tools/llvm-objdump/Inputs/win64-unwind.exe.coff-x86_64 (original) and llvm/trunk/test/tools/llvm-objdump/Inputs/win64-unwind.exe.coff-x86_64 (removed) differ

Added: llvm/trunk/test/tools/llvm-objdump/Inputs/win64-unwind.exe.coff-x86_64.exe
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-objdump/Inputs/win64-unwind.exe.coff-x86_64.exe?rev=202785&view=auto
==============================================================================
Binary files llvm/trunk/test/tools/llvm-objdump/Inputs/win64-unwind.exe.coff-x86_64.exe (added) and llvm/trunk/test/tools/llvm-objdump/Inputs/win64-unwind.exe.coff-x86_64.exe Mon Mar  3 22:00:55 2014 differ

Copied: llvm/trunk/test/tools/llvm-objdump/Inputs/win64-unwind.exe.coff-x86_64.obj (from r202783, llvm/trunk/test/tools/llvm-objdump/Inputs/win64-unwind.exe.coff-x86_64)
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-objdump/Inputs/win64-unwind.exe.coff-x86_64.obj?p2=llvm/trunk/test/tools/llvm-objdump/Inputs/win64-unwind.exe.coff-x86_64.obj&p1=llvm/trunk/test/tools/llvm-objdump/Inputs/win64-unwind.exe.coff-x86_64&r1=202783&r2=202785&rev=202785&view=diff
==============================================================================
    (empty)

Modified: llvm/trunk/test/tools/llvm-objdump/win64-unwind-data.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-objdump/win64-unwind-data.test?rev=202785&r1=202784&r2=202785&view=diff
==============================================================================
--- llvm/trunk/test/tools/llvm-objdump/win64-unwind-data.test (original)
+++ llvm/trunk/test/tools/llvm-objdump/win64-unwind-data.test Mon Mar  3 22:00:55 2014
@@ -1,52 +1,107 @@
 // This test checks that the unwind data is dumped by llvm-objdump.
-// RUN: llvm-objdump -u %p/Inputs/win64-unwind.exe.coff-x86_64 | FileCheck %s
+// RUN: llvm-objdump -u %p/Inputs/win64-unwind.exe.coff-x86_64.obj \
+// RUN:   | FileCheck -check-prefix=OBJ %s
+// RUN: llvm-objdump -u %p/Inputs/win64-unwind.exe.coff-x86_64.exe \
+// RUN:   | FileCheck -check-prefix=EXE %s
 
-CHECK:      Unwind info:
-CHECK:      Function Table:
-CHECK-NEXT:   Start Address: func
-CHECK-NEXT:   End Address: func + 0x001b
-CHECK-NEXT:   Unwind Info Address: .xdata
-CHECK-NEXT:   Version: 1
-CHECK-NEXT:   Flags: 1 UNW_ExceptionHandler
-CHECK-NEXT:   Size of prolog: 18
-CHECK-NEXT:   Number of Codes: 8
-CHECK-NEXT:   Frame register: RBX
-CHECK-NEXT:   Frame offset: 0
-CHECK-NEXT:   Unwind Codes:
-CHECK-NEXT:     0x12: UOP_SetFPReg
-CHECK-NEXT:     0x0f: UOP_PushNonVol RBX
-CHECK-NEXT:     0x0e: UOP_SaveXMM128 XMM8 [0x0000]
-CHECK-NEXT:     0x09: UOP_SaveNonVol RSI [0x0010]
-CHECK-NEXT:     0x04: UOP_AllocSmall 24
-CHECK-NEXT:     0x00: UOP_PushMachFrame w/o error code
-CHECK:      Function Table:
-CHECK-NEXT:   Start Address: func + 0x0012
-CHECK-NEXT:   End Address: func + 0x0012
-CHECK-NEXT:   Unwind Info Address: .xdata + 0x001c
-CHECK-NEXT:   Version: 1
-CHECK-NEXT:   Flags: 4 UNW_ChainInfo
-CHECK-NEXT:   Size of prolog: 0
-CHECK-NEXT:   Number of Codes: 0
-CHECK-NEXT:   No frame pointer used
-CHECK:      Function Table:
-CHECK-NEXT:   Start Address: smallFunc
-CHECK-NEXT:   End Address: smallFunc + 0x0001
-CHECK-NEXT:   Unwind Info Address: .xdata + 0x002c
-CHECK-NEXT:   Version: 1
-CHECK-NEXT:   Flags: 0
-CHECK-NEXT:   Size of prolog: 0
-CHECK-NEXT:   Number of Codes: 0
-CHECK-NEXT:   No frame pointer used
-CHECK:      Function Table:
-CHECK-NEXT:   Start Address: allocFunc
-CHECK-NEXT:   End Address: allocFunc + 0x001d
-CHECK-NEXT:   Unwind Info Address: .xdata + 0x0034
-CHECK-NEXT:   Version: 1
-CHECK-NEXT:   Flags: 0
-CHECK-NEXT:   Size of prolog: 14
-CHECK-NEXT:   Number of Codes: 6
-CHECK-NEXT:   No frame pointer used
-CHECK-NEXT:   Unwind Codes:
-CHECK-NEXT:     0x0e: UOP_AllocLarge 8454128
-CHECK-NEXT:     0x07: UOP_AllocLarge 8190
-CHECK-NEXT:     0x00: UOP_PushMachFrame w/o error code
+OBJ:      Unwind info:
+OBJ:      Function Table:
+OBJ-NEXT:   Start Address: func
+OBJ-NEXT:   End Address: func + 0x001b
+OBJ-NEXT:   Unwind Info Address: .xdata
+OBJ-NEXT:   Version: 1
+OBJ-NEXT:   Flags: 1 UNW_ExceptionHandler
+OBJ-NEXT:   Size of prolog: 18
+OBJ-NEXT:   Number of Codes: 8
+OBJ-NEXT:   Frame register: RBX
+OBJ-NEXT:   Frame offset: 0
+OBJ-NEXT:   Unwind Codes:
+OBJ-NEXT:     0x12: UOP_SetFPReg
+OBJ-NEXT:     0x0f: UOP_PushNonVol RBX
+OBJ-NEXT:     0x0e: UOP_SaveXMM128 XMM8 [0x0000]
+OBJ-NEXT:     0x09: UOP_SaveNonVol RSI [0x0010]
+OBJ-NEXT:     0x04: UOP_AllocSmall 24
+OBJ-NEXT:     0x00: UOP_PushMachFrame w/o error code
+OBJ:      Function Table:
+OBJ-NEXT:   Start Address: func + 0x0012
+OBJ-NEXT:   End Address: func + 0x0012
+OBJ-NEXT:   Unwind Info Address: .xdata + 0x001c
+OBJ-NEXT:   Version: 1
+OBJ-NEXT:   Flags: 4 UNW_ChainInfo
+OBJ-NEXT:   Size of prolog: 0
+OBJ-NEXT:   Number of Codes: 0
+OBJ-NEXT:   No frame pointer used
+OBJ:      Function Table:
+OBJ-NEXT:   Start Address: smallFunc
+OBJ-NEXT:   End Address: smallFunc + 0x0001
+OBJ-NEXT:   Unwind Info Address: .xdata + 0x002c
+OBJ-NEXT:   Version: 1
+OBJ-NEXT:   Flags: 0
+OBJ-NEXT:   Size of prolog: 0
+OBJ-NEXT:   Number of Codes: 0
+OBJ-NEXT:   No frame pointer used
+OBJ:      Function Table:
+OBJ-NEXT:   Start Address: allocFunc
+OBJ-NEXT:   End Address: allocFunc + 0x001d
+OBJ-NEXT:   Unwind Info Address: .xdata + 0x0034
+OBJ-NEXT:   Version: 1
+OBJ-NEXT:   Flags: 0
+OBJ-NEXT:   Size of prolog: 14
+OBJ-NEXT:   Number of Codes: 6
+OBJ-NEXT:   No frame pointer used
+OBJ-NEXT:   Unwind Codes:
+OBJ-NEXT:     0x0e: UOP_AllocLarge 8454128
+OBJ-NEXT:     0x07: UOP_AllocLarge 8190
+OBJ-NEXT:     0x00: UOP_PushMachFrame w/o error code
+
+EXE: Function Table:
+EXE:   Start Address: 0x1000
+EXE:   End Address: 0x101b
+EXE:   Unwind Info Address: : 0x2000
+EXE:   Version: 1
+EXE:   Flags: 1 UNW_ExceptionHandler
+EXE:   Size of prolog: 18
+EXE:   Number of Codes: 8
+EXE:   Frame register: RBX
+EXE:   Frame offset: 0
+EXE:   Unwind Codes:
+EXE:     0x12: UOP_SetFPReg
+EXE:     0x0f: UOP_PushNonVol RBX
+EXE:     0x0e: UOP_SaveXMM128 XMM8 [0x0000]
+EXE:     0x09: UOP_SaveNonVol RSI [0x0010]
+EXE:     0x04: UOP_AllocSmall 24
+EXE:     0x00: UOP_PushMachFrame w/o error code
+
+EXE: Function Table:
+EXE:   Start Address: 0x1012
+EXE:   End Address: 0x1012
+EXE:   Unwind Info Address: : 0x201c
+EXE:   Version: 1
+EXE:   Flags: 4 UNW_ChainInfo
+EXE:   Size of prolog: 0
+EXE:   Number of Codes: 0
+EXE:   No frame pointer used
+
+EXE: Function Table:
+EXE:   Start Address: 0x101b
+EXE:   End Address: 0x101c
+EXE:   Unwind Info Address: : 0x202c
+EXE:   Version: 1
+EXE:   Flags: 0
+EXE:   Size of prolog: 0
+EXE:   Number of Codes: 0
+EXE:   No frame pointer used
+
+EXE: Function Table:
+EXE:   Start Address: 0x101c
+EXE:   End Address: 0x1039
+EXE:   Unwind Info Address: : 0x2034
+EXE:   Version: 1
+EXE:   Flags: 0
+EXE:   Size of prolog: 14
+EXE:   Number of Codes: 6
+EXE:   No frame pointer used
+EXE:   Unwind Codes:
+EXE:     0x0e: UOP_AllocLarge 8454128
+EXE:     0x07: UOP_AllocLarge 8190
+EXE:     0x00: UOP_PushMachFrame w/o error code

Modified: llvm/trunk/tools/llvm-objdump/COFFDump.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-objdump/COFFDump.cpp?rev=202785&r1=202784&r2=202785&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-objdump/COFFDump.cpp (original)
+++ llvm/trunk/tools/llvm-objdump/COFFDump.cpp Mon Mar  3 22:00:55 2014
@@ -453,10 +453,32 @@ static void printWin64EHUnwindInfo(const
   outs().flush();
 }
 
+/// Prints out the given RuntumeFunction struct for x64, assuming that Obj is
+/// pointing to an executable file.
 static void printRuntimeFunction(const COFFObjectFile *Obj,
-                                 const RuntimeFunction &RF,
-                                 uint64_t SectionOffset,
-                                 const std::vector<RelocationRef> &Rels) {
+                                 const RuntimeFunction &RF) {
+  if (!RF.StartAddress)
+    return;
+  outs() << "Function Table:\n"
+         << format("  Start Address: 0x%04x\n", RF.StartAddress)
+         << format("  End Address: 0x%04x\n", RF.EndAddress)
+         << format("  Unwind Info Address: : 0x%04x\n\n", RF.UnwindInfoOffset);
+  uintptr_t addr;
+  if (Obj->getRvaPtr(RF.UnwindInfoOffset, addr))
+    return;
+  printWin64EHUnwindInfo(reinterpret_cast<const Win64EH::UnwindInfo *>(addr));
+}
+
+/// Prints out the given RuntumeFunction struct for x64, assuming that Obj is
+/// pointing to an object file. Unlike executable, fields in RuntumeFunction
+/// struct are filled with zeros, but instead there are relocations pointing to
+/// them so that the linker will fill targets' RVAs to the fields at link
+/// time. This function interprets the relocations to find the data to be used
+/// in the resulting executable.
+static void printRuntimeFunctionRels(const COFFObjectFile *Obj,
+                                     const RuntimeFunction &RF,
+                                     uint64_t SectionOffset,
+                                     const std::vector<RelocationRef> &Rels) {
   outs() << "Function Table:\n";
   outs() << "  Start Address: ";
   printCOFFSymbolAddress(outs(), Rels,
@@ -516,10 +538,17 @@ void llvm::printCOFFUnwindInfo(const COF
     return;
   ArrayRef<RuntimeFunction> RFs(RFStart, NumRFs);
 
+  bool IsExecutable = Rels.empty();
+  if (IsExecutable) {
+    for (const RuntimeFunction &RF : RFs)
+      printRuntimeFunction(Obj, RF);
+    return;
+  }
+
   for (const RuntimeFunction &RF : RFs) {
     uint64_t SectionOffset =
         std::distance(RFs.begin(), &RF) * sizeof(RuntimeFunction);
-    printRuntimeFunction(Obj, RF, SectionOffset, Rels);
+    printRuntimeFunctionRels(Obj, RF, SectionOffset, Rels);
   }
 }
 





More information about the llvm-commits mailing list