1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
|
QEMU crashes when executing a RISC-V compressed instruction with C extension disabled.
Description of problem:
When binaries are built with compressed instructions, but QEMU is launched with C extension disabled we get a crash instead of a trap that can be handled by the fault handler. It is quite possible that this only asserts if the compressed instruction is the first instruction after a new translation block due to the unconditional trap generated by:
```
if (!has_ext(ctx, RVC)) {
gen_exception_illegal(ctx);
} else {
```
Although I would not expect the TB to be empty. Unfortunately it appears to crash before `-d op` prints any output.
Steps to reproduce:
1. Compile the following assembly code to an ELF32 binary: `clang --target=riscv32-none-elf -nostdlib -o crash.elf ./crash.S -Wl,--section-start=.text=0x80000000`
```asm
.text
.global _start
.type _start,@function
_start:
# .4byte 0x300022f3 # csrr t0,mstatus
# NB: compressed instruction, if we start qemu with c=false,
# this results in the following error:
# qemu-system-riscv32: ../../upstream-qemu/accel/tcg/translate-all.c:762: int setjmp_gen_code(CPUArchState *, TranslationBlock *, target_ulong, void *, int *, int64_t *): Assertion `tb->size != 0' failed.
bne t0, t1, .Lfoo # This instruction is not strictly necessary, but it makes the debug output a bit more useful
.Lfoo:
.2byte 0x6309 # lui t1,0x2
j _start
```
2. `qemu-system-riscv32 -monitor none -serial none -machine virt,accel=tcg -cpu rv32,i=true,c=false -kernel crash.elf -nographic -bios none -d in_asm,op,op_opt,unimp`
3. Assertion failure: `qemu-system-riscv32: ../../upstream-qemu/accel/tcg/translate-all.c:762: int setjmp_gen_code(CPUArchState *, TranslationBlock *, target_ulong, void *, int *, int64_t *): Assertion `tb->size != 0' failed.`
Additional information:
Here is the output of `-d in_asm,op,op_opt,unimp,nochain`:
```
----------------
IN:
Priv: 3; Virt: 0
0x00001000: 00000297 auipc t0,0 # 0x1000
0x00001004: 02828613 addi a2,t0,40
0x00001008: f1402573 csrrs a0,mhartid,zero
OP:
ld_i32 tmp1,env,$0xfffffffffffffff0
brcond_i32 tmp1,$0x0,lt,$L0
---- 00001000 00000000
mov_i32 x5/t0,$0x1000
---- 00001004 00000000
add_i32 x12/a2,x5/t0,$0x28
---- 00001008 f1402573
call csrr,$0x0,$1,x10/a0,env,$0xf14
mov_i32 pc,$0x100c
exit_tb $0x0
set_label $L0
exit_tb $0x7f5824000043
OP after optimization and liveness analysis:
ld_i32 tmp1,env,$0xfffffffffffffff0 pref=0xffff
brcond_i32 tmp1,$0x0,lt,$L0 dead: 0 1
---- 00001000 00000000
mov_i32 x5/t0,$0x1000 sync: 0 dead: 0 1 pref=0xffff
---- 00001004 00000000
mov_i32 x12/a2,$0x1028 sync: 0 dead: 0 1 pref=0xffff
---- 00001008 f1402573
call csrr,$0x0,$1,x10/a0,env,$0xf14 sync: 0 dead: 0 1 2 pref=none
mov_i32 pc,$0x100c sync: 0 dead: 0 1 pref=0xffff
exit_tb $0x0
set_label $L0
exit_tb $0x7f5824000043
----------------
IN:
Priv: 3; Virt: 0
0x0000100c: 0202a583 lw a1,32(t0)
0x00001010: 0182a283 lw t0,24(t0)
0x00001014: 00028067 jr t0
OP:
ld_i32 tmp1,env,$0xfffffffffffffff0
brcond_i32 tmp1,$0x0,lt,$L0
---- 0000100c 00000000
add_i32 tmp1,x5/t0,$0x20
qemu_ld_i32 x11/a1,tmp1,leul,3
---- 00001010 00000000
add_i32 tmp1,x5/t0,$0x18
qemu_ld_i32 x5/t0,tmp1,leul,3
---- 00001014 00000000
mov_i32 pc,x5/t0
and_i32 pc,pc,$0xfffffffe
and_i32 tmp1,pc,$0x2
brcond_i32 tmp1,$0x0,ne,$L1
call lookup_tb_ptr,$0x6,$1,tmp6,env
goto_ptr tmp6
set_label $L1
st_i32 pc,env,$0x1228
mov_i32 pc,$0x1014
call raise_exception,$0x8,$0,env,$0x0
set_label $L0
exit_tb $0x7f5824000183
OP after optimization and liveness analysis:
ld_i32 tmp1,env,$0xfffffffffffffff0 pref=0xffff
brcond_i32 tmp1,$0x0,lt,$L0 dead: 0
---- 0000100c 00000000
add_i32 tmp1,x5/t0,$0x20 dead: 2 pref=0xff3f
qemu_ld_i32 x11/a1,tmp1,leul,3 sync: 0 dead: 0 1 pref=0xffff
---- 00001010 00000000
add_i32 tmp1,x5/t0,$0x18 dead: 1 2 pref=0xff3f
qemu_ld_i32 x5/t0,tmp1,leul,3 sync: 0 dead: 1 pref=0xffff
---- 00001014 00000000
mov_i32 pc,x5/t0 dead: 1 pref=0xffff
and_i32 pc,pc,$0xfffffffe sync: 0 dead: 1 2 pref=0xffff
and_i32 tmp1,pc,$0x2 dead: 1 2 pref=0xffff
brcond_i32 tmp1,$0x0,ne,$L1 dead: 0 1
call lookup_tb_ptr,$0x6,$1,tmp6,env dead: 1 pref=none
goto_ptr tmp6 dead: 0
set_label $L1
st_i32 pc,env,$0x1228 dead: 0
mov_i32 pc,$0x1014 sync: 0 dead: 0 1 pref=0xffff
call raise_exception,$0x8,$0,env,$0x0 dead: 0 1
set_label $L0
exit_tb $0x7f5824000183
----------------
IN:
Priv: 3; Virt: 0
0x80000000: 00629263 bne t0,t1,4 # 0x80000004
OP:
ld_i32 tmp1,env,$0xfffffffffffffff0
brcond_i32 tmp1,$0x0,lt,$L0
---- 80000000 00000000
mov_i32 tmp1,x5/t0
mov_i32 tmp2,x6/t1
brcond_i32 tmp1,tmp2,ne,$L1
mov_i32 pc,$0x80000004
call lookup_tb_ptr,$0x6,$1,tmp4,env
goto_ptr tmp4
set_label $L1
mov_i32 pc,$0x80000004
call lookup_tb_ptr,$0x6,$1,tmp4,env
goto_ptr tmp4
set_label $L0
exit_tb $0x7f5824000383
OP after optimization and liveness analysis:
ld_i32 tmp1,env,$0xfffffffffffffff0 pref=0xffff
brcond_i32 tmp1,$0x0,lt,$L0 dead: 0 1
---- 80000000 00000000
brcond_i32 x5/t0,x6/t1,ne,$L1 dead: 0 1
mov_i32 pc,$0x80000004 sync: 0 dead: 0 1 pref=0xffff
call lookup_tb_ptr,$0x6,$1,tmp4,env dead: 1 pref=none
goto_ptr tmp4 dead: 0
set_label $L1
mov_i32 pc,$0x80000004 sync: 0 dead: 0 1 pref=0xffff
call lookup_tb_ptr,$0x6,$1,tmp4,env dead: 1 pref=none
goto_ptr tmp4 dead: 0
set_label $L0
exit_tb $0x7f5824000383
----------------
IN:
Priv: 3; Virt: 0
qemu-system-riscv32: ../../upstream-qemu/accel/tcg/translate-all.c:762: int setjmp_gen_code(CPUArchState *, TranslationBlock *, target_ulong, void *, int *, int64_t *): Assertion `tb->size != 0' failed.
```
|