xref: /llvm-project/llvm/test/tools/llvm-readobj/ELF/unwind.test (revision fe8476472467acd15a4d3771313e5532d1eb032f)
1## In this test we check how the unwind information is dumped with the use of --unwind.
2
3## First, check that both llvm-readobj and llvm-readelf are able to dump a valid unwind information.
4## Check that the output is the same for these tools.
5## The memory size of the PT_GNU_EH_FRAME equals its file size and they both are equal to 0x3c.
6## 0x3c is the size of the .eh_frame_hdr section.
7# RUN: yaml2obj --docnum=1 %s -DMEMSIZE=0x3c -DFILESIZE=0x3c -o %t1.valid
8# RUN: llvm-readobj --unwind %t1.valid | FileCheck %s
9# RUN: llvm-readelf --sections --unwind %t1.valid | FileCheck %s --check-prefixes=SIZE,CHECK
10
11## Validate the size of the .eh_frame_hdr section.
12# SIZE: [Nr] Name          Type     Address          Off    Size
13# SIZE: [ 2] .eh_frame_hdr PROGBITS 00000000004013c0 0000bc 00003c
14
15# CHECK:      EHFrameHeader {
16# CHECK-NEXT:  Address: 0x4013c0
17# CHECK-NEXT:  Offset: 0xbc
18# CHECK-NEXT:  Size: 0x3c
19# CHECK-NEXT:  Corresponding Section: .eh_frame_hdr
20# CHECK-NEXT:  Header {
21# CHECK-NEXT:    version: 1
22# CHECK-NEXT:    eh_frame_ptr_enc: 0x1b
23# CHECK-NEXT:    fde_count_enc: 0x3
24# CHECK-NEXT:    table_enc: 0x3b
25# CHECK-NEXT:    eh_frame_ptr: 0x401400
26# CHECK-NEXT:    fde_count: 6
27# CHECK-NEXT:    entry 0 {
28# CHECK-NEXT:      initial_location: 0x4004a0
29# CHECK-NEXT:      address: 0x401448
30# CHECK-NEXT:    }
31# CHECK-NEXT:    entry 1 {
32# CHECK-NEXT:      initial_location: 0x4004d0
33# CHECK-NEXT:      address: 0x401418
34# CHECK-NEXT:    }
35# CHECK-NEXT:    entry 2 {
36# CHECK-NEXT:      initial_location: 0x4005b6
37# CHECK-NEXT:      address: 0x401470
38# CHECK-NEXT:    }
39# CHECK-NEXT:    entry 3 {
40# CHECK-NEXT:      initial_location: 0x4005d0
41# CHECK-NEXT:      address: 0x401490
42# CHECK-NEXT:    }
43# CHECK-NEXT:    entry 4 {
44# CHECK-NEXT:      initial_location: 0x401250
45# CHECK-NEXT:      address: 0x4014c0
46# CHECK-NEXT:    }
47# CHECK-NEXT:    entry 5 {
48# CHECK-NEXT:      initial_location: 0x4012c0
49# CHECK-NEXT:      address: 0x4014f0
50# CHECK-NEXT:    }
51# CHECK-NEXT:  }
52# CHECK-NEXT:}
53
54# CHECK:      .eh_frame section at offset 0xf8 address 0x401400:
55# CHECK-NEXT:  [0x401400] CIE length=20
56# CHECK-NEXT:    version: 1
57# CHECK-NEXT:    augmentation: zR
58# CHECK-NEXT:    code_alignment_factor: 1
59# CHECK-NEXT:    data_alignment_factor: -8
60# CHECK-NEXT:    return_address_register: 16
61
62# CHECK:         Program:
63# CHECK-NEXT:      DW_CFA_def_cfa: reg7 +8
64# CHECK-NEXT:      DW_CFA_offset: reg16 -8
65# CHECK-NEXT:      DW_CFA_undefined: reg16
66
67# CHECK:       [0x401418] FDE length=20 cie=[0x401400]
68# CHECK-NEXT:    initial_location: 0x4004d0
69# CHECK-NEXT:    address_range: 0x2a (end : 0x4004fa)
70
71# CHECK:         Program:
72# CHECK-NEXT:      DW_CFA_nop:
73# CHECK-NEXT:      DW_CFA_nop:
74# CHECK-NEXT:      DW_CFA_nop:
75# CHECK-NEXT:      DW_CFA_nop:
76# CHECK-NEXT:      DW_CFA_nop:
77# CHECK-NEXT:      DW_CFA_nop:
78# CHECK-NEXT:      DW_CFA_nop:
79
80# CHECK:       [0x401430] CIE length=20
81# CHECK-NEXT:    version: 1
82# CHECK-NEXT:    augmentation: zR
83# CHECK-NEXT:    code_alignment_factor: 1
84# CHECK-NEXT:    data_alignment_factor: -8
85# CHECK-NEXT:    return_address_register: 16
86
87# CHECK:         Program:
88# CHECK-NEXT:      DW_CFA_def_cfa: reg7 +8
89# CHECK-NEXT:      DW_CFA_offset: reg16 -8
90# CHECK-NEXT:      DW_CFA_nop:
91# CHECK-NEXT:      DW_CFA_nop:
92
93# CHECK:       [0x401448] FDE length=36 cie=[0x401430]
94# CHECK-NEXT:    initial_location: 0x4004a0
95# CHECK-NEXT:    address_range: 0x20 (end : 0x4004c0)
96
97# CHECK:         Program:
98# CHECK-NEXT:      DW_CFA_def_cfa_offset: +16
99# CHECK-NEXT:      DW_CFA_advance_loc: 6 to 0x4004a6
100# CHECK-NEXT:      DW_CFA_def_cfa_offset: +24
101# CHECK-NEXT:      DW_CFA_advance_loc: 10 to 0x4004b0
102# CHECK-NEXT:      DW_CFA_def_cfa_expression: DW_OP_breg7 +8, DW_OP_breg16 +0, DW_OP_lit15, DW_OP_and, DW_OP_lit11, DW_OP_ge, DW_OP_lit3, DW_OP_shl, DW_OP_plus
103# CHECK-NEXT:      DW_CFA_nop:
104# CHECK-NEXT:      DW_CFA_nop:
105# CHECK-NEXT:      DW_CFA_nop:
106# CHECK-NEXT:      DW_CFA_nop:
107
108# CHECK:       [0x401470] FDE length=28 cie=[0x401430]
109# CHECK-NEXT:    initial_location: 0x4005b6
110# CHECK-NEXT:    address_range: 0x10 (end : 0x4005c6)
111
112# CHECK:         Program:
113# CHECK-NEXT:      DW_CFA_advance_loc: 1 to 0x4005b7
114# CHECK-NEXT:      DW_CFA_def_cfa_offset: +16
115# CHECK-NEXT:      DW_CFA_offset: reg6 -16
116# CHECK-NEXT:      DW_CFA_advance_loc: 3 to 0x4005ba
117# CHECK-NEXT:      DW_CFA_def_cfa_register: reg6
118# CHECK-NEXT:      DW_CFA_advance_loc: 11 to 0x4005c5
119# CHECK-NEXT:      DW_CFA_def_cfa: reg7 +8
120# CHECK-NEXT:      DW_CFA_nop:
121# CHECK-NEXT:      DW_CFA_nop:
122# CHECK-NEXT:      DW_CFA_nop:
123
124# CHECK:       [0x401490] FDE length=44 cie=[0x401430]
125# CHECK-NEXT:    initial_location: 0x4005d0
126# CHECK-NEXT:    address_range: 0xc7f (end : 0x40124f)
127
128# CHECK:         Program:
129# CHECK-NEXT:      DW_CFA_advance_loc: 5 to 0x4005d5
130# CHECK-NEXT:      DW_CFA_def_cfa: reg10 +0
131# CHECK-NEXT:      DW_CFA_advance_loc: 9 to 0x4005de
132# CHECK-NEXT:      DW_CFA_expression: reg6 DW_OP_breg6 +0
133# CHECK-NEXT:      DW_CFA_advance_loc: 5 to 0x4005e3
134# CHECK-NEXT:      DW_CFA_def_cfa_expression: DW_OP_breg6 -8, DW_OP_deref
135# CHECK-NEXT:      DW_CFA_advance_loc2: 3174 to 0x401249
136# CHECK-NEXT:      DW_CFA_def_cfa: reg10 +0
137# CHECK-NEXT:      DW_CFA_advance_loc: 5 to 0x40124e
138# CHECK-NEXT:      DW_CFA_def_cfa: reg7 +8
139# CHECK-NEXT:      DW_CFA_nop:
140# CHECK-NEXT:      DW_CFA_nop:
141# CHECK-NEXT:      DW_CFA_nop:
142# CHECK-NEXT:      DW_CFA_nop:
143
144# CHECK:       [0x4014c0] FDE length=44 cie=[0x401430]
145# CHECK-NEXT:    initial_location: 0x401250
146# CHECK-NEXT:    address_range: 0x66 (end : 0x4012b6)
147
148# CHECK:         Program:
149# CHECK-NEXT:      DW_CFA_advance_loc: 1 to 0x401251
150# CHECK-NEXT:      DW_CFA_def_cfa_offset: +16
151# CHECK-NEXT:      DW_CFA_offset: reg6 -16
152# CHECK-NEXT:      DW_CFA_advance_loc: 3 to 0x401254
153# CHECK-NEXT:      DW_CFA_def_cfa_register: reg6
154# CHECK-NEXT:      DW_CFA_advance_loc: 2 to 0x401256
155# CHECK-NEXT:      DW_CFA_offset: reg15 -24
156# CHECK-NEXT:      DW_CFA_advance_loc: 5 to 0x40125b
157# CHECK-NEXT:      DW_CFA_offset: reg14 -32
158# CHECK-NEXT:      DW_CFA_advance_loc: 7 to 0x401262
159# CHECK-NEXT:      DW_CFA_offset: reg13 -40
160# CHECK-NEXT:      DW_CFA_offset: reg12 -48
161# CHECK-NEXT:      DW_CFA_advance_loc: 8 to 0x40126a
162# CHECK-NEXT:      DW_CFA_offset: reg3 -56
163# CHECK-NEXT:      DW_CFA_advance_loc1: 75 to 0x4012b5
164# CHECK-NEXT:      DW_CFA_def_cfa: reg7 +8
165# CHECK-NEXT:      DW_CFA_nop:
166# CHECK-NEXT:      DW_CFA_nop:
167# CHECK-NEXT:      DW_CFA_nop:
168# CHECK-NEXT:      DW_CFA_nop:
169
170# CHECK:       [0x4014f0] FDE length=20 cie=[0x401430]
171# CHECK-NEXT:    initial_location: 0x4012c0
172# CHECK-NEXT:    address_range: 0x1 (end : 0x4012c1)
173
174# CHECK:         Program:
175# CHECK-NEXT:      DW_CFA_nop:
176# CHECK-NEXT:      DW_CFA_nop:
177# CHECK-NEXT:      DW_CFA_nop:
178# CHECK-NEXT:      DW_CFA_nop:
179# CHECK-NEXT:      DW_CFA_nop:
180# CHECK-NEXT:      DW_CFA_nop:
181# CHECK-NEXT:      DW_CFA_nop:
182
183--- !ELF
184FileHeader:
185  Class:           ELFCLASS64
186  Data:            ELFDATA2LSB
187  Type:            ET_EXEC
188  Machine:         EM_X86_64
189  Entry:           0x0000000000400000
190Sections:
191  - Name:            .text
192    Type:            SHT_PROGBITS
193    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
194    Address:         0x0000000000400000
195    AddressAlign:    16
196    Content:         50C704240020400031C05AC3
197  - Name:            .eh_frame_hdr
198    Type:            SHT_PROGBITS
199    Flags:           [ SHF_ALLOC ]
200    Address:         0x00000000004013c0
201    AddressAlign:    4
202    Content:         011B033B3C00000006000000E0F0FFFF8800000010F1FFFF58000000F6F1FFFFB000000010F2FFFFD000000090FEFFFF0001000000FFFFFF30010000
203  - Name:            .eh_frame
204    Type:            SHT_PROGBITS
205    Flags:           [ SHF_ALLOC ]
206    Address:         0x0000000000401400
207    AddressAlign:    8
208    Content:         1400000000000000017A5200017810011B0C070890010710140000001C000000B0F0FFFF2A00000000000000000000001400000000000000017A5200017810011B0C070890010000240000001C00000050F0FFFF20000000000E10460E184A0F0B770880003F1A3B2A332422000000001C000000440000003EF1FFFF1000000000410E108602430D064B0C07080000002C0000006400000038F1FFFF7F0C000000450C0A00491006027600450F0376780603660C0C0A00450C070800000000002C0000009400000088FDFFFF6600000000410E108602430D06428F03458E04478D058C06488307024B0C07080000000014000000C4000000C8FDFFFF01000000000000000000000000000000
209Symbols:
210  - Name:            myfunc
211    Type:            STT_FUNC
212    Section:         .text
213    Value:           0x0000000000400000
214    Binding:         STB_GLOBAL
215ProgramHeaders:
216  - Type:     PT_LOAD
217    Flags:    [ PF_X, PF_R ]
218    VAddr:    0x00400000
219    PAddr:    0x00400000
220    FirstSec: .text
221    LastSec:  .text
222  - Type:     PT_GNU_EH_FRAME
223    Flags:    [ PF_X, PF_R ]
224    VAddr:    0x004013C0
225    PAddr:    0x004013C0
226    MemSize:  [[MEMSIZE]]
227    FileSize: [[FILESIZE]]
228    FirstSec: .eh_frame_hdr
229    LastSec:  .eh_frame_hdr
230
231## Document we report a error when the memory size of the PT_GNU_EH_FRAME does not match its file size.
232## TODO: we want to report a warning and continue dumping instead.
233# RUN: yaml2obj --docnum=1 %s -DMEMSIZE=0x3b -DFILESIZE=0x3c -o %t1.size.mismatch
234# RUN: not llvm-readobj --unwind %t1.size.mismatch 2>&1 | \
235# RUN:   FileCheck -DFILE=%t1.size.mismatch %s --check-prefix=SIZE-MISMATCH
236# RUN: not llvm-readelf --unwind %t1.size.mismatch 2>&1 | \
237# RUN:   FileCheck -DFILE=%t1.size.mismatch %s --check-prefix=SIZE-MISMATCH
238
239# SIZE-MISMATCH: error: '[[FILE]]': p_memsz does not match p_filesz for GNU_EH_FRAME
240
241## Check we partially dump the unwind information when the PT_GNU_EH_FRAME segment
242## points to truncated data.
243# RUN: yaml2obj --docnum=1 %s -DMEMSIZE=0x1 -DFILESIZE=0x1 -o %t1.truncated
244# RUN: not llvm-readobj --unwind %t1.truncated 2>&1 | FileCheck -DFILE=%t1.truncated %s --check-prefix=TRUNCATED
245# RUN: not llvm-readelf --unwind %t1.truncated 2>&1 | FileCheck -DFILE=%t1.truncated %s --check-prefix=TRUNCATED
246
247# TRUNCATED:      EHFrameHeader {
248# TRUNCATED-NEXT:   Address: 0x4013c0
249# TRUNCATED-NEXT:   Offset: 0xbc
250# TRUNCATED-NEXT:   Size: 0x1
251# TRUNCATED-NEXT:   Corresponding Section: .eh_frame_hdr
252# TRUNCATED-NEXT:   Header {
253# TRUNCATED-NEXT:     version: 1
254# TRUNCATED-NEXT:     eh_frame_ptr_enc: 0x0
255# TRUNCATED-NEXT: error: '[[FILE]]': unexpected encoding eh_frame_ptr_enc
256
257## Check we report an error when the tool is unable to parse .eh_frame section.
258# RUN: yaml2obj --docnum=2 %s -o %t2.exe
259# RUN: not llvm-readobj --unwind %t2.exe 2>&1 | FileCheck %s -DFILE=%t2.exe --check-prefix=NO-CIE-ERR
260
261# NO-CIE-ERR:      .eh_frame section at offset 0x40 address 0x0:
262# NO-CIE-ERR-NEXT: error: '[[FILE]]': parsing FDE data at 0x0 failed due to missing CIE
263# NO-CIE-ERR-NOT:  {{.}}
264
265--- !ELF
266FileHeader:
267  Class:   ELFCLASS64
268  Data:    ELFDATA2LSB
269  Type:    ET_REL
270  Machine: EM_X86_64
271Sections:
272  - Name: .eh_frame
273    Type: SHT_X86_64_UNWIND
274## The content is generated from the following code. It has no CIE.
275## See the DebugInfoX86/eh-frame-cie-id.s test case for more history.
276## .section .eh_frame,"a",@unwind
277## .long .Lend - .LCIEptr  # Length
278## .LCIEptr:
279##   .long 0xffffffff # CIE pointer
280##   .quad 0x1111abcd # Initial location
281##   .quad 0x00010000 # Address range
282## .Lend:
283    Content: 14000000FFFFFFFFCDAB1111000000000000010000000000
284
285## Check we report a error when the .eh_frame section contains truncated data.
286# RUN: yaml2obj --docnum=3 %s -o %t3.exe
287# RUN: not llvm-readobj --unwind %t3.exe 2>&1 | FileCheck %s -DFILE=%t3.exe --check-prefix=TRUNCATED-ERR
288
289# TRUNCATED-ERR:      .eh_frame section at offset 0x34 address 0x0:
290# TRUNCATED-ERR-NEXT: error: '[[FILE]]': unexpected end of data at offset 0x4
291
292--- !ELF
293FileHeader:
294  Class: ELFCLASS32
295  Data:  ELFDATA2LSB
296  Type:  ET_EXEC
297Sections:
298  - Name:    .eh_frame
299    Type:    SHT_PROGBITS
300## Length is set to 0xFF, though the actual section length is 4.
301    Content: "FF000000"
302
303## Check we report an error when we can't read the content of the .eh_frame section.
304
305## Case A: test we report an error when the p_offset of the PT_GNU_EH_FRAME
306##         is invalid (goes past the end of the file).
307
308# RUN: yaml2obj --docnum=4 %s -o %t4 -DOFFSET=0xffff0000 -DSIZE=0x1 -DBITS=32
309# RUN: not llvm-readobj --unwind %t4 2>&1 \
310# RUN:   | FileCheck %s -DFILE=%t4 --check-prefix=BROKEN-CONTENT -DOFFSET=0xffff0000 -DSIZE=0x1
311
312# RUN: yaml2obj --docnum=4 %s -o %t5 -DOFFSET=0x1 -DSIZE=0xffff0000 -DBITS=32
313# RUN: not llvm-readobj --unwind %t5 2>&1 \
314# RUN:   | FileCheck %s -DFILE=%t5 --check-prefix=BROKEN-CONTENT -DOFFSET=0x1 -DSIZE=0xffff0000
315
316# BROKEN-CONTENT:      EHFrameHeader {
317# BROKEN-CONTENT-NEXT:   Address: 0x0
318# BROKEN-CONTENT-NEXT:   Offset:  [[OFFSET]]
319# BROKEN-CONTENT-NEXT:   Size:    [[SIZE]]
320# BROKEN-CONTENT-NEXT:   Corresponding Section:
321# BROKEN-CONTENT-NEXT: error: '[[FILE]]': program header  [index 0] has a p_offset ([[OFFSET]]) + p_filesz ([[SIZE]]) that is greater than the file size (0xe0)
322
323--- !ELF
324FileHeader:
325  Class: ELFCLASS[[BITS]]
326  Data:  ELFDATA2LSB
327  Type:  ET_EXEC
328ProgramHeaders:
329  - Type:     PT_GNU_EH_FRAME
330    MemSize:  [[SIZE]]
331    FileSize: [[SIZE]]
332    Offset:   [[OFFSET]]
333
334## Case B: test we report an error when the file size of the PT_GNU_EH_FRAME
335##         is invalid (goes past the end of the file).
336# RUN: yaml2obj --docnum=4 %s -o %t6 -DOFFSET=0x100 -DSIZE=0xffff0000 -DBITS=32
337# RUN: not llvm-readobj --unwind %t6 2>&1 \
338# RUN:   | FileCheck %s -DFILE=%t6 --check-prefix=BROKEN-CONTENT -DOFFSET=0x100 -DSIZE=0xffff0000
339
340## Case C: test we report an error when the offset + the file size of the PT_GNU_EH_FRAME is so large a
341##         value that it overflows the platform address size type.
342
343# RUN: yaml2obj --docnum=4 %s -o %t7 -DOFFSET=0x1 -DSIZE=0xffffffff -DBITS=32
344# RUN: not llvm-readobj --unwind %t7 2>&1 | FileCheck %s -DFILE=%t7 --check-prefix=BROKEN-CONTENT2 -DOFFSET=0x1 -DSIZE=0xffffffff
345
346# RUN: yaml2obj --docnum=4 %s -o %t8 -DOFFSET=0xffffffff -DSIZE=0x1 -DBITS=32
347# RUN: not llvm-readobj --unwind %t8 2>&1 | FileCheck %s -DFILE=%t8 --check-prefix=BROKEN-CONTENT2 -DOFFSET=0xffffffff -DSIZE=0x1
348
349# RUN: yaml2obj --docnum=4 %s -o %t9 -DOFFSET=0x1 -DSIZE=0xffffffffffffffff -DBITS=64
350# RUN: not llvm-readelf --unwind %t9 2>&1 | FileCheck %s -DFILE=%t9 --check-prefix=BROKEN-CONTENT2 -DOFFSET=0x1 -DSIZE=0xffffffffffffffff
351
352# RUN: yaml2obj --docnum=4 %s -o %t10 -DOFFSET=0xffffffffffffffff -DSIZE=0x1 -DBITS=64
353# RUN: not llvm-readelf --unwind %t10 2>&1 | FileCheck %s -DFILE=%t10 --check-prefix=BROKEN-CONTENT2 -DOFFSET=0xffffffffffffffff -DSIZE=0x1
354
355# BROKEN-CONTENT2:      EHFrameHeader {
356# BROKEN-CONTENT2-NEXT:   Address: 0x0
357# BROKEN-CONTENT2-NEXT:   Offset: [[OFFSET]]
358# BROKEN-CONTENT2-NEXT:   Size:   [[SIZE]]
359# BROKEN-CONTENT2-NEXT:   Corresponding Section:
360# BROKEN-CONTENT2-NEXT: error: '[[FILE]]': program header [index 0] has a p_offset ([[OFFSET]]) + p_filesz ([[SIZE]]) that cannot be represented
361