Skip to content

Commit a320361

Browse files
bschommerxavierleroy
authored andcommitted
Protect against overflows in leaq (all forms)
leaq's offsets can overflow (not fit in 32 bits) in other cases than those fixed in 4daebb7, e.g. in the expansion of __builtin_memcpy_aligned. This commit implements full normalization of the `leaq` instructions produced in Asmexpand, following the same method used in Asmgen.
1 parent 4daebb7 commit a320361

File tree

1 file changed

+27
-22
lines changed

1 file changed

+27
-22
lines changed

x86/Asmexpand.ml

+27-22
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,6 @@ let _16z = Z.of_sint 16
3939

4040
let stack_alignment () = 16
4141

42-
(* Pseudo instructions for 32/64 bit compatibility *)
43-
44-
let _Plea (r, addr) =
45-
if Archi.ptr64 then Pleaq (r, addr) else Pleal (r, addr)
46-
4742
(* SP adjustment to allocate or free a stack frame. *)
4843

4944
let align n a =
@@ -109,14 +104,20 @@ let offset_addressing (Addrmode(base, ofs, cst)) delta =
109104
let linear_addr reg ofs = Addrmode(Some reg, None, Coq_inl ofs)
110105
let global_addr id ofs = Addrmode(None, None, Coq_inr(id, ofs))
111106

112-
(* Emit a 64-bit immediate add [dst <- src + imm]. *)
107+
(* A "leaq" instruction that does not overflow *)
113108

114-
let emit_addimm64 dst src imm =
115-
if Op.offset_in_range imm then
116-
emit (Pleaq(dst, linear_addr src imm))
117-
else begin
118-
emit (Pmov_rr(dst, src)); emit (Paddq_ri(dst, Integers.Int64.repr imm))
119-
end
109+
let emit_leaq r addr =
110+
match Asmgen.normalize_addrmode_64 addr with
111+
| (addr, None) ->
112+
emit (Pleaq (r, addr))
113+
| (addr, Some delta) ->
114+
emit (Pleaq (r, addr));
115+
emit (Paddq_ri (r, delta))
116+
117+
(* Pseudo "lea" instruction for 32/64 bit compatibility *)
118+
119+
let emit_lea r addr =
120+
if Archi.ptr64 then emit_leaq r addr else emit (Pleal (r, addr))
120121

121122
(* Translate a builtin argument into an addressing mode *)
122123

@@ -159,8 +160,8 @@ let expand_builtin_memcpy_small sz al src dst =
159160
copy (addressing_of_builtin_arg src) (addressing_of_builtin_arg dst) sz
160161

161162
let expand_builtin_memcpy_big sz al src dst =
162-
if src <> BA (IR RSI) then emit (_Plea (RSI, addressing_of_builtin_arg src));
163-
if dst <> BA (IR RDI) then emit (_Plea (RDI, addressing_of_builtin_arg dst));
163+
if src <> BA (IR RSI) then emit_lea RSI (addressing_of_builtin_arg src);
164+
if dst <> BA (IR RDI) then emit_lea RDI (addressing_of_builtin_arg dst);
164165
(* TODO: movsq? *)
165166
emit (Pmovl_ri (RCX,coqint_of_camlint (Int32.of_int (sz / 4))));
166167
emit Prep_movsl;
@@ -298,9 +299,9 @@ let expand_builtin_va_start_elf64 r =
298299
emit (Pmovl_mr (linear_addr r _0z, RAX));
299300
emit (Pmovl_ri (RAX, coqint_of_camlint fp_offset));
300301
emit (Pmovl_mr (linear_addr r _4z, RAX));
301-
emit_addimm64 RAX RSP (Z.of_uint64 overflow_arg_area);
302+
emit_leaq RAX (linear_addr RSP (Z.of_uint64 overflow_arg_area));
302303
emit (Pmovq_mr (linear_addr r _8z, RAX));
303-
emit_addimm64 RAX RSP (Z.of_uint64 reg_save_area);
304+
emit_leaq RAX (linear_addr RSP (Z.of_uint64 reg_save_area));
304305
emit (Pmovq_mr (linear_addr r _16z, RAX))
305306

306307
let expand_builtin_va_start_win64 r =
@@ -311,7 +312,7 @@ let expand_builtin_va_start_win64 r =
311312
let ofs =
312313
Int64.(add !current_function_stacksize
313314
(mul 8L (of_int num_args))) in
314-
emit_addimm64 RAX RSP (Z.of_uint64 ofs);
315+
emit_leaq RAX (linear_addr RSP (Z.of_uint64 ofs));
315316
emit (Pmovq_mr (linear_addr r _0z, RAX))
316317

317318
(* FMA operations *)
@@ -559,8 +560,10 @@ let expand_instruction instr =
559560
emit (Psubl_ri (RSP, sz'));
560561
emit (Pcfi_adjust sz');
561562
(* Stack chaining *)
562-
emit_addimm64 RAX RSP (Z.of_uint (sz + 8));
563-
emit (Pmovq_mr (linear_addr RSP ofs_link, RAX));
563+
let addr1 = linear_addr RSP (Z.of_uint (sz + 8)) in
564+
let addr2 = linear_addr RSP ofs_link in
565+
emit_leaq RAX addr1;
566+
emit (Pmovq_mr (addr2, RAX));
564567
current_function_stacksize := Int64.of_int (sz + 8)
565568
end else if Archi.ptr64 then begin
566569
let (sz, save_regs) = sp_adjustment_elf64 sz in
@@ -570,14 +573,16 @@ let expand_instruction instr =
570573
emit (Pcfi_adjust sz');
571574
if save_regs >= 0 then begin
572575
(* Save the registers *)
573-
emit_addimm64 R10 RSP (Z.of_uint save_regs);
576+
emit_leaq R10 (linear_addr RSP (Z.of_uint save_regs));
574577
emit (Pcall_s (intern_string "__compcert_va_saveregs",
575578
{sig_args = []; sig_res = Tvoid; sig_cc = cc_default}))
576579
end;
577580
(* Stack chaining *)
578581
let fullsz = sz + 8 in
579-
emit_addimm64 RAX RSP (Z.of_uint fullsz);
580-
emit (Pmovq_mr (linear_addr RSP ofs_link, RAX));
582+
let addr1 = linear_addr RSP (Z.of_uint fullsz) in
583+
let addr2 = linear_addr RSP ofs_link in
584+
emit_leaq RAX addr1;
585+
emit (Pmovq_mr (addr2, RAX));
581586
current_function_stacksize := Int64.of_int fullsz
582587
end else begin
583588
let sz = sp_adjustment_32 sz in

0 commit comments

Comments
 (0)