@@ -141,14 +141,17 @@ static inline void emit_addr_mov_i64(const int reg, const u64 val,
141
141
}
142
142
}
143
143
144
- static inline int bpf2a64_offset (int bpf_to , int bpf_from ,
144
+ static inline int bpf2a64_offset (int bpf_insn , int off ,
145
145
const struct jit_ctx * ctx )
146
146
{
147
- int to = ctx -> offset [bpf_to ];
148
- /* -1 to account for the Branch instruction */
149
- int from = ctx -> offset [bpf_from ] - 1 ;
150
-
151
- return to - from ;
147
+ /* BPF JMP offset is relative to the next instruction */
148
+ bpf_insn ++ ;
149
+ /*
150
+ * Whereas arm64 branch instructions encode the offset
151
+ * from the branch itself, so we must subtract 1 from the
152
+ * instruction offset.
153
+ */
154
+ return ctx -> offset [bpf_insn + off ] - (ctx -> offset [bpf_insn ] - 1 );
152
155
}
153
156
154
157
static void jit_fill_hole (void * area , unsigned int size )
@@ -578,7 +581,7 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
578
581
579
582
/* JUMP off */
580
583
case BPF_JMP | BPF_JA :
581
- jmp_offset = bpf2a64_offset (i + off , i , ctx );
584
+ jmp_offset = bpf2a64_offset (i , off , ctx );
582
585
check_imm26 (jmp_offset );
583
586
emit (A64_B (jmp_offset ), ctx );
584
587
break ;
@@ -605,7 +608,7 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
605
608
case BPF_JMP32 | BPF_JSLE | BPF_X :
606
609
emit (A64_CMP (is64 , dst , src ), ctx );
607
610
emit_cond_jmp :
608
- jmp_offset = bpf2a64_offset (i + off , i , ctx );
611
+ jmp_offset = bpf2a64_offset (i , off , ctx );
609
612
check_imm19 (jmp_offset );
610
613
switch (BPF_OP (code )) {
611
614
case BPF_JEQ :
@@ -837,22 +840,38 @@ static int build_body(struct jit_ctx *ctx, bool extra_pass)
837
840
const struct bpf_prog * prog = ctx -> prog ;
838
841
int i ;
839
842
843
+ /*
844
+ * - offset[0] offset of the end of prologue,
845
+ * start of the 1st instruction.
846
+ * - offset[1] - offset of the end of 1st instruction,
847
+ * start of the 2nd instruction
848
+ * [....]
849
+ * - offset[3] - offset of the end of 3rd instruction,
850
+ * start of 4th instruction
851
+ */
840
852
for (i = 0 ; i < prog -> len ; i ++ ) {
841
853
const struct bpf_insn * insn = & prog -> insnsi [i ];
842
854
int ret ;
843
855
856
+ if (ctx -> image == NULL )
857
+ ctx -> offset [i ] = ctx -> idx ;
844
858
ret = build_insn (insn , ctx , extra_pass );
845
859
if (ret > 0 ) {
846
860
i ++ ;
847
861
if (ctx -> image == NULL )
848
862
ctx -> offset [i ] = ctx -> idx ;
849
863
continue ;
850
864
}
851
- if (ctx -> image == NULL )
852
- ctx -> offset [i ] = ctx -> idx ;
853
865
if (ret )
854
866
return ret ;
855
867
}
868
+ /*
869
+ * offset is allocated with prog->len + 1 so fill in
870
+ * the last element with the offset after the last
871
+ * instruction (end of program)
872
+ */
873
+ if (ctx -> image == NULL )
874
+ ctx -> offset [i ] = ctx -> idx ;
856
875
857
876
return 0 ;
858
877
}
@@ -928,7 +947,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
928
947
memset (& ctx , 0 , sizeof (ctx ));
929
948
ctx .prog = prog ;
930
949
931
- ctx .offset = kcalloc (prog -> len , sizeof (int ), GFP_KERNEL );
950
+ ctx .offset = kcalloc (prog -> len + 1 , sizeof (int ), GFP_KERNEL );
932
951
if (ctx .offset == NULL ) {
933
952
prog = orig_prog ;
934
953
goto out_off ;
@@ -1008,7 +1027,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
1008
1027
prog -> jited_len = image_size ;
1009
1028
1010
1029
if (!prog -> is_func || extra_pass ) {
1011
- bpf_prog_fill_jited_linfo (prog , ctx .offset );
1030
+ bpf_prog_fill_jited_linfo (prog , ctx .offset + 1 );
1012
1031
out_off :
1013
1032
kfree (ctx .offset );
1014
1033
kfree (jit_data );
0 commit comments