Skip to content

Commit 1355df3

Browse files
committed
[ELF][CHERI] Rewrite exception-table test in LLVM IR
This avoids one dependency on clang and will hopefully allow removing it entirely soon. Ideally this would be written as an assembly test but adding the right directives for EH tables is tedious, so I went for IR instead.
1 parent d2e741e commit 1355df3

File tree

3 files changed

+217
-105
lines changed

3 files changed

+217
-105
lines changed

lld/test/ELF/cheri/exception-table.cpp

-104
This file was deleted.

lld/test/ELF/cheri/exception-table.ll

+215
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
; RUN: %cheri_purecap_llc --relocation-model=pic < %s -filetype=obj -o %t.o
2+
; RUN: llvm-readobj -r %t.o | FileCheck %s --check-prefix=MIPS-OBJ-RELOCS
3+
; RUN: %riscv64_cheri_purecap_llc --relocation-model=pic < %s -filetype=obj -o %t-riscv64.o
4+
; RUN: llvm-readobj -r %t-riscv64.o | FileCheck %s --check-prefix=RV64-OBJ-RELOCS
5+
;; Should have two relocations against a local alias for _Z4testll
6+
; MIPS-OBJ-RELOCS: Section ({{.+}}) .rela.gcc_except_table {
7+
; MIPS-OBJ-RELOCS-NEXT: R_MIPS_CHERI_CAPABILITY/R_MIPS_NONE/R_MIPS_NONE .L_Z4testll$local 0x80
8+
; MIPS-OBJ-RELOCS-NEXT: R_MIPS_CHERI_CAPABILITY/R_MIPS_NONE/R_MIPS_NONE .L_Z4testll$local 0x60
9+
; MIPS-OBJ-RELOCS-NEXT: R_MIPS_CHERI_CAPABILITY/R_MIPS_NONE/R_MIPS_NONE .L_Z5test2ll$local 0x60
10+
; MIPS-OBJ-RELOCS-NEXT: R_MIPS_PC32/R_MIPS_NONE/R_MIPS_NONE .L_ZTIl.DW.stub 0x0
11+
; MIPS-OBJ-RELOCS-NEXT: }
12+
; RV64-OBJ-RELOCS: Section ({{.+}}) .rela.gcc_except_table {
13+
; RV64-OBJ-RELOCS-NEXT: R_RISCV_ADD32 - 0x0
14+
; RV64-OBJ-RELOCS-NEXT: R_RISCV_SUB32 - 0x0
15+
; RV64-OBJ-RELOCS-NEXT: R_RISCV_ADD32 - 0x0
16+
; RV64-OBJ-RELOCS-NEXT: R_RISCV_SUB32 - 0x0
17+
; RV64-OBJ-RELOCS-NEXT: R_RISCV_CHERI_CAPABILITY .L_Z4testll$local 0x5C
18+
; RV64-OBJ-RELOCS-NEXT: R_RISCV_ADD32 - 0x0
19+
; RV64-OBJ-RELOCS-NEXT: R_RISCV_SUB32 - 0x0
20+
; RV64-OBJ-RELOCS-NEXT: R_RISCV_ADD32 - 0x0
21+
; RV64-OBJ-RELOCS-NEXT: R_RISCV_SUB32 - 0x0
22+
; RV64-OBJ-RELOCS-NEXT: R_RISCV_CHERI_CAPABILITY .L_Z4testll$local 0x48
23+
; RV64-OBJ-RELOCS-NEXT: R_RISCV_ADD32 - 0x0
24+
; RV64-OBJ-RELOCS-NEXT: R_RISCV_SUB32 - 0x0
25+
; RV64-OBJ-RELOCS-NEXT: R_RISCV_ADD32 - 0x0
26+
; RV64-OBJ-RELOCS-NEXT: R_RISCV_SUB32 - 0x0
27+
; RV64-OBJ-RELOCS-NEXT: R_RISCV_ADD32 - 0x0
28+
; RV64-OBJ-RELOCS-NEXT: R_RISCV_SUB32 - 0x0
29+
; RV64-OBJ-RELOCS-NEXT: R_RISCV_ADD32 - 0x0
30+
; RV64-OBJ-RELOCS-NEXT: R_RISCV_SUB32 - 0x0
31+
; RV64-OBJ-RELOCS-NEXT: R_RISCV_CHERI_CAPABILITY .L_Z5test2ll$local 0x48
32+
; RV64-OBJ-RELOCS-NEXT: R_RISCV_ADD32 - 0x0
33+
; RV64-OBJ-RELOCS-NEXT: R_RISCV_SUB32 - 0x0
34+
; RV64-OBJ-RELOCS-NEXT: R_RISCV_ADD32 - 0x0
35+
; RV64-OBJ-RELOCS-NEXT: R_RISCV_SUB32 - 0x0
36+
; RV64-OBJ-RELOCS-NEXT: R_RISCV_32_PCREL .L_ZTIl.DW.stub 0x0
37+
; RV64-OBJ-RELOCS-NEXT: }
38+
39+
;; This should work with both -z text and -z notext
40+
;; Check that .gcc_except_table ends up in the relro section and the relocations are correct
41+
; RUN: ld.lld -shared %t.o -o %t.so -z notext
42+
; RUN: llvm-readelf -r --section-mapping --sections --program-headers --cap-relocs %t.so | FileCheck %s --check-prefixes=HEADERS,MIPS-RELOCS
43+
; RUN: ld.lld -shared %t.o -o %t.so -z text
44+
; RUN: llvm-readelf -r --section-mapping %t.so
45+
; RUN: llvm-readelf -r --section-mapping --sections --program-headers --cap-relocs %t.so | FileCheck %s --check-prefixes=HEADERS,MIPS-RELOCS
46+
47+
; HEADERS-LABEL: There are 10 program headers, starting at
48+
; HEADERS-EMPTY:
49+
; HEADERS-NEXT: Program Headers:
50+
; HEADERS-NEXT: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
51+
; HEADERS-NEXT: PHDR 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} R 0x8
52+
; HEADERS-NEXT: LOAD 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} R 0x10000
53+
; HEADERS-NEXT: LOAD 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} R E 0x10000
54+
; HEADERS-NEXT: LOAD 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} RW 0x10000
55+
; HEADERS-NEXT: LOAD 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} RW 0x10000
56+
; HEADERS-NEXT: DYNAMIC 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} R 0x8
57+
; HEADERS-NEXT: GNU_RELRO 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} R 0x1
58+
; HEADERS-NEXT: GNU_STACK 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} RW 0x0
59+
; HEADERS-NEXT: OPTIONS 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} R 0x8
60+
; HEADERS-NEXT: ABIFLAGS 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} R 0x8
61+
; HEADERS-EMPTY:
62+
; HEADERS-NEXT: Section to Segment mapping:
63+
; HEADERS-NEXT: Segment Sections...
64+
; HEADERS-NEXT: 00
65+
; HEADERS-NEXT: 01 .MIPS.abiflags .MIPS.options .dynsym .hash .dynamic .dynstr .rel.dyn .rel.plt .eh_frame __cap_relocs {{$}}
66+
; HEADERS-NEXT: 02 .text
67+
; HEADERS-NEXT: 03 .gcc_except_table
68+
; HEADERS-NEXT: 04 .data .captable .got
69+
; HEADERS-NEXT: 05 .dynamic
70+
; HEADERS-NEXT: 06 .gcc_except_table
71+
; HEADERS-NEXT: 07
72+
; HEADERS-NEXT: 08 .MIPS.options
73+
; HEADERS-NEXT: 09 .MIPS.abiflags
74+
; HEADERS-NEXT: None .bss .mdebug.abi64 .pdr .comment .symtab .shstrtab .strtab
75+
76+
; MIPS-RELOCS-LABEL: Relocation section '.rel.dyn' {{.+}} contains 2 entries:
77+
; MIPS-RELOCS-NEXT: Offset Info Type Symbol's Value Symbol's Name
78+
; MIPS-RELOCS-NEXT: R_MIPS_CHERI_CAPABILITY/R_MIPS_NONE/R_MIPS_NONE 0000000000000000 _ZTIl
79+
; MIPS-RELOCS-NEXT: R_MIPS_CHERI_CAPABILITY/R_MIPS_NONE/R_MIPS_NONE 0000000000000000 __gxx_personality_v0
80+
; MIPS-RELOCS-EMPTY:
81+
; MIPS-RELOCS-NEXT: Relocation section '.rel.plt' at offset {{.+}} contains 3 entries:
82+
; MIPS-RELOCS-NEXT: Offset Info Type Symbol's Value Symbol's Name
83+
; MIPS-RELOCS-NEXT: R_MIPS_CHERI_CAPABILITY_CALL/R_MIPS_NONE/R_MIPS_NONE 0000000000000000 _Z11external_fnl
84+
; MIPS-RELOCS-NEXT: R_MIPS_CHERI_CAPABILITY_CALL/R_MIPS_NONE/R_MIPS_NONE 0000000000000000 __cxa_begin_catch
85+
; MIPS-RELOCS-NEXT: R_MIPS_CHERI_CAPABILITY_CALL/R_MIPS_NONE/R_MIPS_NONE 0000000000000000 __cxa_end_catch
86+
87+
;; Local relocations for exception handling:
88+
; MIPS-RELOCS-NEXT: CHERI __cap_relocs [
89+
; MIPS-RELOCS-NEXT: 0x02{{.+}} Base: 0x1{{.+}} (.L_Z4testll$local+128) Length: 160 Perms: Function
90+
; MIPS-RELOCS-NEXT: 0x02{{.+}} Base: 0x1{{.+}} (.L_Z4testll$local+96) Length: 160 Perms: Function
91+
; MIPS-RELOCS-NEXT: 0x02{{.+}} Base: 0x1{{.+}} (.L_Z5test2ll$local+96) Length: 168 Perms: Function
92+
; MIPS-RELOCS-NEXT: ]
93+
94+
;; Should also emit __cap_relocs for RISC-V:
95+
; RUN: ld.lld -shared %t-riscv64.o -o %t.so
96+
; RUN: llvm-readelf -r --cap-relocs %t.so | FileCheck %s --check-prefixes=RV64-RELOCS
97+
; RV64-RELOCS: CHERI __cap_relocs [
98+
; RV64-RELOCS-NEXT: 0x002{{.+}} Base: 0x1{{.+}} (.L_Z4testll$local+92) Length: 116 Perms: Function
99+
; RV64-RELOCS-NEXT: 0x002{{.+}} Base: 0x1{{.+}} (.L_Z4testll$local+72) Length: 116 Perms: Function
100+
; RV64-RELOCS-NEXT: 0x002{{.+}} Base: 0x1{{.+}} (.L_Z5test2ll$local+72) Length: 124 Perms: Function
101+
; RV64-RELOCS-NEXT: ]
102+
103+
; IR was generated from the following code:
104+
; long external_fn(long arg);
105+
;
106+
; long test(long arg, long arg2) {
107+
; long a = 0;
108+
; long b = 0;
109+
; try {
110+
; a = external_fn(arg);
111+
; } catch (...) {
112+
; return -1;
113+
; }
114+
; try {
115+
; b = external_fn(arg2);
116+
; } catch (...) {
117+
; return a;
118+
; }
119+
; return a + b;
120+
; }
121+
;
122+
; long test2(long arg, long arg2) {
123+
; try {
124+
; return external_fn(arg) - external_fn(arg2);
125+
; } catch (long &err) {
126+
; return err;
127+
; } catch (...) {
128+
; return -1;
129+
; }
130+
; }
131+
132+
@_ZTIl = external dso_local addrspace(200) constant ptr addrspace(200)
133+
134+
define dso_local noundef i64 @_Z4testll(i64 noundef %arg, i64 noundef %arg2) local_unnamed_addr addrspace(200) uwtable personality ptr addrspace(200) @__gxx_personality_v0 {
135+
entry:
136+
%call = invoke noundef i64 @_Z11external_fnl(i64 noundef %arg)
137+
to label %invoke.cont unwind label %lpad
138+
139+
invoke.cont:
140+
%call3 = invoke noundef i64 @_Z11external_fnl(i64 noundef %arg2)
141+
to label %invoke.cont2 unwind label %lpad1
142+
143+
lpad:
144+
%0 = landingpad { ptr addrspace(200), i32 }
145+
catch ptr addrspace(200) null
146+
%1 = extractvalue { ptr addrspace(200), i32 } %0, 0
147+
%2 = tail call ptr addrspace(200) @__cxa_begin_catch(ptr addrspace(200) %1) nounwind
148+
tail call void @__cxa_end_catch()
149+
br label %cleanup
150+
151+
invoke.cont2:
152+
%add = add nsw i64 %call3, %call
153+
br label %cleanup
154+
155+
lpad1:
156+
%3 = landingpad { ptr addrspace(200), i32 }
157+
catch ptr addrspace(200) null
158+
%4 = extractvalue { ptr addrspace(200), i32 } %3, 0
159+
%5 = tail call ptr addrspace(200) @__cxa_begin_catch(ptr addrspace(200) %4) nounwind
160+
tail call void @__cxa_end_catch()
161+
br label %cleanup
162+
163+
cleanup:
164+
%retval.0 = phi i64 [ %add, %invoke.cont2 ], [ %call, %lpad1 ], [ -1, %lpad ]
165+
ret i64 %retval.0
166+
}
167+
168+
declare dso_local noundef i64 @_Z11external_fnl(i64 noundef) local_unnamed_addr addrspace(200)
169+
170+
declare dso_local i32 @__gxx_personality_v0(...) addrspace(200)
171+
172+
declare dso_local ptr addrspace(200) @__cxa_begin_catch(ptr addrspace(200)) local_unnamed_addr addrspace(200)
173+
174+
declare dso_local void @__cxa_end_catch() local_unnamed_addr addrspace(200)
175+
176+
; Function Attrs: mustprogress uwtable
177+
define dso_local noundef i64 @_Z5test2ll(i64 noundef %arg, i64 noundef %arg2) local_unnamed_addr addrspace(200) #0 personality ptr addrspace(200) @__gxx_personality_v0 {
178+
entry:
179+
%call = invoke noundef i64 @_Z11external_fnl(i64 noundef %arg)
180+
to label %invoke.cont unwind label %lpad
181+
182+
invoke.cont:
183+
%call2 = invoke noundef i64 @_Z11external_fnl(i64 noundef %arg2)
184+
to label %invoke.cont1 unwind label %lpad
185+
186+
invoke.cont1:
187+
%sub = sub nsw i64 %call, %call2
188+
br label %return
189+
190+
lpad:
191+
%0 = landingpad { ptr addrspace(200), i32 }
192+
catch ptr addrspace(200) @_ZTIl
193+
catch ptr addrspace(200) null
194+
%1 = extractvalue { ptr addrspace(200), i32 } %0, 0
195+
%2 = extractvalue { ptr addrspace(200), i32 } %0, 1
196+
%3 = tail call i32 @llvm.eh.typeid.for(ptr addrspacecast (ptr addrspace(200) @_ZTIl to ptr)) nounwind
197+
%matches = icmp eq i32 %2, %3
198+
%4 = tail call ptr addrspace(200) @__cxa_begin_catch(ptr addrspace(200) %1) nounwind
199+
br i1 %matches, label %catch3, label %catch
200+
201+
catch3:
202+
%5 = load i64, ptr addrspace(200) %4, align 8
203+
tail call void @__cxa_end_catch() nounwind
204+
br label %return
205+
206+
catch:
207+
tail call void @__cxa_end_catch()
208+
br label %return
209+
210+
return:
211+
%retval.0 = phi i64 [ %sub, %invoke.cont1 ], [ %5, %catch3 ], [ -1, %catch ]
212+
ret i64 %retval.0
213+
}
214+
215+
declare i32 @llvm.eh.typeid.for(ptr) addrspace(200)

lld/test/ELF/cheri/lit.local.cfg

+2-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ config.lld = lit.util.which('ld.lld', config.llvm_tools_dir)
2626
# These substitutions rely on %clang, etc. so must come before even if clang isn't found
2727
add_sub('%clang_link_purecap ', '%cheri_purecap_clang ' +
2828
'-fuse-ld=' + config.lld + ' -nostdlib -Wl,-melf64btsmip_cheri_fbsd ')
29-
local_llvm_config.add_cheri_tool_substitutions(['llvm-mc'])
29+
local_llvm_config.use_llvm_tool("llc")
30+
local_llvm_config.add_cheri_tool_substitutions(['llvm-mc', 'llc'])
3031
local_llvm_config.use_clang(required=False)
3132
if config.clang:
3233
if lit_config.debug:

0 commit comments

Comments
 (0)