llvm.org GIT mirror llvm / 3ab0ce0
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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@202785 91177308-0d34-0410-b5e6-96231b3b80d8 Rui Ueyama 5 years ago
5 changed file(s) with 138 addition(s) and 54 deletion(s). Raw diff Collapse all Expand all
test/tools/llvm-objdump/Inputs/win64-unwind.exe.coff-x86_64 less more
Binary diff not shown
0 // This test checks that the unwind data is dumped by llvm-objdump.
1 // RUN: llvm-objdump -u %p/Inputs/win64-unwind.exe.coff-x86_64 | FileCheck %s
1 // RUN: llvm-objdump -u %p/Inputs/win64-unwind.exe.coff-x86_64.obj \
2 // RUN: | FileCheck -check-prefix=OBJ %s
3 // RUN: llvm-objdump -u %p/Inputs/win64-unwind.exe.coff-x86_64.exe \
4 // RUN: | FileCheck -check-prefix=EXE %s
25
3 CHECK: Unwind info:
4 CHECK: Function Table:
5 CHECK-NEXT: Start Address: func
6 CHECK-NEXT: End Address: func + 0x001b
7 CHECK-NEXT: Unwind Info Address: .xdata
8 CHECK-NEXT: Version: 1
9 CHECK-NEXT: Flags: 1 UNW_ExceptionHandler
10 CHECK-NEXT: Size of prolog: 18
11 CHECK-NEXT: Number of Codes: 8
12 CHECK-NEXT: Frame register: RBX
13 CHECK-NEXT: Frame offset: 0
14 CHECK-NEXT: Unwind Codes:
15 CHECK-NEXT: 0x12: UOP_SetFPReg
16 CHECK-NEXT: 0x0f: UOP_PushNonVol RBX
17 CHECK-NEXT: 0x0e: UOP_SaveXMM128 XMM8 [0x0000]
18 CHECK-NEXT: 0x09: UOP_SaveNonVol RSI [0x0010]
19 CHECK-NEXT: 0x04: UOP_AllocSmall 24
20 CHECK-NEXT: 0x00: UOP_PushMachFrame w/o error code
21 CHECK: Function Table:
22 CHECK-NEXT: Start Address: func + 0x0012
23 CHECK-NEXT: End Address: func + 0x0012
24 CHECK-NEXT: Unwind Info Address: .xdata + 0x001c
25 CHECK-NEXT: Version: 1
26 CHECK-NEXT: Flags: 4 UNW_ChainInfo
27 CHECK-NEXT: Size of prolog: 0
28 CHECK-NEXT: Number of Codes: 0
29 CHECK-NEXT: No frame pointer used
30 CHECK: Function Table:
31 CHECK-NEXT: Start Address: smallFunc
32 CHECK-NEXT: End Address: smallFunc + 0x0001
33 CHECK-NEXT: Unwind Info Address: .xdata + 0x002c
34 CHECK-NEXT: Version: 1
35 CHECK-NEXT: Flags: 0
36 CHECK-NEXT: Size of prolog: 0
37 CHECK-NEXT: Number of Codes: 0
38 CHECK-NEXT: No frame pointer used
39 CHECK: Function Table:
40 CHECK-NEXT: Start Address: allocFunc
41 CHECK-NEXT: End Address: allocFunc + 0x001d
42 CHECK-NEXT: Unwind Info Address: .xdata + 0x0034
43 CHECK-NEXT: Version: 1
44 CHECK-NEXT: Flags: 0
45 CHECK-NEXT: Size of prolog: 14
46 CHECK-NEXT: Number of Codes: 6
47 CHECK-NEXT: No frame pointer used
48 CHECK-NEXT: Unwind Codes:
49 CHECK-NEXT: 0x0e: UOP_AllocLarge 8454128
50 CHECK-NEXT: 0x07: UOP_AllocLarge 8190
51 CHECK-NEXT: 0x00: UOP_PushMachFrame w/o error code
6 OBJ: Unwind info:
7 OBJ: Function Table:
8 OBJ-NEXT: Start Address: func
9 OBJ-NEXT: End Address: func + 0x001b
10 OBJ-NEXT: Unwind Info Address: .xdata
11 OBJ-NEXT: Version: 1
12 OBJ-NEXT: Flags: 1 UNW_ExceptionHandler
13 OBJ-NEXT: Size of prolog: 18
14 OBJ-NEXT: Number of Codes: 8
15 OBJ-NEXT: Frame register: RBX
16 OBJ-NEXT: Frame offset: 0
17 OBJ-NEXT: Unwind Codes:
18 OBJ-NEXT: 0x12: UOP_SetFPReg
19 OBJ-NEXT: 0x0f: UOP_PushNonVol RBX
20 OBJ-NEXT: 0x0e: UOP_SaveXMM128 XMM8 [0x0000]
21 OBJ-NEXT: 0x09: UOP_SaveNonVol RSI [0x0010]
22 OBJ-NEXT: 0x04: UOP_AllocSmall 24
23 OBJ-NEXT: 0x00: UOP_PushMachFrame w/o error code
24 OBJ: Function Table:
25 OBJ-NEXT: Start Address: func + 0x0012
26 OBJ-NEXT: End Address: func + 0x0012
27 OBJ-NEXT: Unwind Info Address: .xdata + 0x001c
28 OBJ-NEXT: Version: 1
29 OBJ-NEXT: Flags: 4 UNW_ChainInfo
30 OBJ-NEXT: Size of prolog: 0
31 OBJ-NEXT: Number of Codes: 0
32 OBJ-NEXT: No frame pointer used
33 OBJ: Function Table:
34 OBJ-NEXT: Start Address: smallFunc
35 OBJ-NEXT: End Address: smallFunc + 0x0001
36 OBJ-NEXT: Unwind Info Address: .xdata + 0x002c
37 OBJ-NEXT: Version: 1
38 OBJ-NEXT: Flags: 0
39 OBJ-NEXT: Size of prolog: 0
40 OBJ-NEXT: Number of Codes: 0
41 OBJ-NEXT: No frame pointer used
42 OBJ: Function Table:
43 OBJ-NEXT: Start Address: allocFunc
44 OBJ-NEXT: End Address: allocFunc + 0x001d
45 OBJ-NEXT: Unwind Info Address: .xdata + 0x0034
46 OBJ-NEXT: Version: 1
47 OBJ-NEXT: Flags: 0
48 OBJ-NEXT: Size of prolog: 14
49 OBJ-NEXT: Number of Codes: 6
50 OBJ-NEXT: No frame pointer used
51 OBJ-NEXT: Unwind Codes:
52 OBJ-NEXT: 0x0e: UOP_AllocLarge 8454128
53 OBJ-NEXT: 0x07: UOP_AllocLarge 8190
54 OBJ-NEXT: 0x00: UOP_PushMachFrame w/o error code
55
56 EXE: Function Table:
57 EXE: Start Address: 0x1000
58 EXE: End Address: 0x101b
59 EXE: Unwind Info Address: : 0x2000
60 EXE: Version: 1
61 EXE: Flags: 1 UNW_ExceptionHandler
62 EXE: Size of prolog: 18
63 EXE: Number of Codes: 8
64 EXE: Frame register: RBX
65 EXE: Frame offset: 0
66 EXE: Unwind Codes:
67 EXE: 0x12: UOP_SetFPReg
68 EXE: 0x0f: UOP_PushNonVol RBX
69 EXE: 0x0e: UOP_SaveXMM128 XMM8 [0x0000]
70 EXE: 0x09: UOP_SaveNonVol RSI [0x0010]
71 EXE: 0x04: UOP_AllocSmall 24
72 EXE: 0x00: UOP_PushMachFrame w/o error code
73
74 EXE: Function Table:
75 EXE: Start Address: 0x1012
76 EXE: End Address: 0x1012
77 EXE: Unwind Info Address: : 0x201c
78 EXE: Version: 1
79 EXE: Flags: 4 UNW_ChainInfo
80 EXE: Size of prolog: 0
81 EXE: Number of Codes: 0
82 EXE: No frame pointer used
83
84 EXE: Function Table:
85 EXE: Start Address: 0x101b
86 EXE: End Address: 0x101c
87 EXE: Unwind Info Address: : 0x202c
88 EXE: Version: 1
89 EXE: Flags: 0
90 EXE: Size of prolog: 0
91 EXE: Number of Codes: 0
92 EXE: No frame pointer used
93
94 EXE: Function Table:
95 EXE: Start Address: 0x101c
96 EXE: End Address: 0x1039
97 EXE: Unwind Info Address: : 0x2034
98 EXE: Version: 1
99 EXE: Flags: 0
100 EXE: Size of prolog: 14
101 EXE: Number of Codes: 6
102 EXE: No frame pointer used
103 EXE: Unwind Codes:
104 EXE: 0x0e: UOP_AllocLarge 8454128
105 EXE: 0x07: UOP_AllocLarge 8190
106 EXE: 0x00: UOP_PushMachFrame w/o error code
452452 outs().flush();
453453 }
454454
455 /// Prints out the given RuntumeFunction struct for x64, assuming that Obj is
456 /// pointing to an executable file.
455457 static void printRuntimeFunction(const COFFObjectFile *Obj,
456 const RuntimeFunction &RF,
457 uint64_t SectionOffset,
458 const std::vector &Rels) {
458 const RuntimeFunction &RF) {
459 if (!RF.StartAddress)
460 return;
461 outs() << "Function Table:\n"
462 << format(" Start Address: 0x%04x\n", RF.StartAddress)
463 << format(" End Address: 0x%04x\n", RF.EndAddress)
464 << format(" Unwind Info Address: : 0x%04x\n\n", RF.UnwindInfoOffset);
465 uintptr_t addr;
466 if (Obj->getRvaPtr(RF.UnwindInfoOffset, addr))
467 return;
468 printWin64EHUnwindInfo(reinterpret_cast(addr));
469 }
470
471 /// Prints out the given RuntumeFunction struct for x64, assuming that Obj is
472 /// pointing to an object file. Unlike executable, fields in RuntumeFunction
473 /// struct are filled with zeros, but instead there are relocations pointing to
474 /// them so that the linker will fill targets' RVAs to the fields at link
475 /// time. This function interprets the relocations to find the data to be used
476 /// in the resulting executable.
477 static void printRuntimeFunctionRels(const COFFObjectFile *Obj,
478 const RuntimeFunction &RF,
479 uint64_t SectionOffset,
480 const std::vector &Rels) {
459481 outs() << "Function Table:\n";
460482 outs() << " Start Address: ";
461483 printCOFFSymbolAddress(outs(), Rels,
515537 return;
516538 ArrayRef RFs(RFStart, NumRFs);
517539
540 bool IsExecutable = Rels.empty();
541 if (IsExecutable) {
542 for (const RuntimeFunction &RF : RFs)
543 printRuntimeFunction(Obj, RF);
544 return;
545 }
546
518547 for (const RuntimeFunction &RF : RFs) {
519548 uint64_t SectionOffset =
520549 std::distance(RFs.begin(), &RF) * sizeof(RuntimeFunction);
521 printRuntimeFunction(Obj, RF, SectionOffset, Rels);
550 printRuntimeFunctionRels(Obj, RF, SectionOffset, Rels);
522551 }
523552 }
524553