@@ -715,7 +715,8 @@ static int add_exception_handler(const struct bpf_insn *insn,
715
715
/* First pass */
716
716
return 0 ;
717
717
718
- if (BPF_MODE (insn -> code ) != BPF_PROBE_MEM )
718
+ if (BPF_MODE (insn -> code ) != BPF_PROBE_MEM &&
719
+ BPF_MODE (insn -> code ) != BPF_PROBE_MEMSX )
719
720
return 0 ;
720
721
721
722
if (!ctx -> prog -> aux -> extable ||
@@ -779,6 +780,7 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
779
780
u8 dst_adj ;
780
781
int off_adj ;
781
782
int ret ;
783
+ bool sign_extend ;
782
784
783
785
switch (code ) {
784
786
/* dst = src */
@@ -1122,7 +1124,7 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
1122
1124
return 1 ;
1123
1125
}
1124
1126
1125
- /* LDX: dst = *( size *)(src + off) */
1127
+ /* LDX: dst = (u64)*(unsigned size *)(src + off) */
1126
1128
case BPF_LDX | BPF_MEM | BPF_W :
1127
1129
case BPF_LDX | BPF_MEM | BPF_H :
1128
1130
case BPF_LDX | BPF_MEM | BPF_B :
@@ -1131,36 +1133,63 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
1131
1133
case BPF_LDX | BPF_PROBE_MEM | BPF_W :
1132
1134
case BPF_LDX | BPF_PROBE_MEM | BPF_H :
1133
1135
case BPF_LDX | BPF_PROBE_MEM | BPF_B :
1136
+ /* LDXS: dst_reg = (s64)*(signed size *)(src_reg + off) */
1137
+ case BPF_LDX | BPF_MEMSX | BPF_B :
1138
+ case BPF_LDX | BPF_MEMSX | BPF_H :
1139
+ case BPF_LDX | BPF_MEMSX | BPF_W :
1140
+ case BPF_LDX | BPF_PROBE_MEMSX | BPF_B :
1141
+ case BPF_LDX | BPF_PROBE_MEMSX | BPF_H :
1142
+ case BPF_LDX | BPF_PROBE_MEMSX | BPF_W :
1134
1143
if (ctx -> fpb_offset > 0 && src == fp ) {
1135
1144
src_adj = fpb ;
1136
1145
off_adj = off + ctx -> fpb_offset ;
1137
1146
} else {
1138
1147
src_adj = src ;
1139
1148
off_adj = off ;
1140
1149
}
1150
+ sign_extend = (BPF_MODE (insn -> code ) == BPF_MEMSX ||
1151
+ BPF_MODE (insn -> code ) == BPF_PROBE_MEMSX );
1141
1152
switch (BPF_SIZE (code )) {
1142
1153
case BPF_W :
1143
1154
if (is_lsi_offset (off_adj , 2 )) {
1144
- emit (A64_LDR32I (dst , src_adj , off_adj ), ctx );
1155
+ if (sign_extend )
1156
+ emit (A64_LDRSWI (dst , src_adj , off_adj ), ctx );
1157
+ else
1158
+ emit (A64_LDR32I (dst , src_adj , off_adj ), ctx );
1145
1159
} else {
1146
1160
emit_a64_mov_i (1 , tmp , off , ctx );
1147
- emit (A64_LDR32 (dst , src , tmp ), ctx );
1161
+ if (sign_extend )
1162
+ emit (A64_LDRSW (dst , src_adj , off_adj ), ctx );
1163
+ else
1164
+ emit (A64_LDR32 (dst , src , tmp ), ctx );
1148
1165
}
1149
1166
break ;
1150
1167
case BPF_H :
1151
1168
if (is_lsi_offset (off_adj , 1 )) {
1152
- emit (A64_LDRHI (dst , src_adj , off_adj ), ctx );
1169
+ if (sign_extend )
1170
+ emit (A64_LDRSHI (dst , src_adj , off_adj ), ctx );
1171
+ else
1172
+ emit (A64_LDRHI (dst , src_adj , off_adj ), ctx );
1153
1173
} else {
1154
1174
emit_a64_mov_i (1 , tmp , off , ctx );
1155
- emit (A64_LDRH (dst , src , tmp ), ctx );
1175
+ if (sign_extend )
1176
+ emit (A64_LDRSH (dst , src , tmp ), ctx );
1177
+ else
1178
+ emit (A64_LDRH (dst , src , tmp ), ctx );
1156
1179
}
1157
1180
break ;
1158
1181
case BPF_B :
1159
1182
if (is_lsi_offset (off_adj , 0 )) {
1160
- emit (A64_LDRBI (dst , src_adj , off_adj ), ctx );
1183
+ if (sign_extend )
1184
+ emit (A64_LDRSBI (dst , src_adj , off_adj ), ctx );
1185
+ else
1186
+ emit (A64_LDRBI (dst , src_adj , off_adj ), ctx );
1161
1187
} else {
1162
1188
emit_a64_mov_i (1 , tmp , off , ctx );
1163
- emit (A64_LDRB (dst , src , tmp ), ctx );
1189
+ if (sign_extend )
1190
+ emit (A64_LDRSB (dst , src , tmp ), ctx );
1191
+ else
1192
+ emit (A64_LDRB (dst , src , tmp ), ctx );
1164
1193
}
1165
1194
break ;
1166
1195
case BPF_DW :
0 commit comments