From e7fdaf008e047c445fd7a6acf9362d8b5940bf4b Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Tue, 5 Sep 2017 16:28:56 +0100 Subject: [PATCH 12/12] arm64: Emit hidden alias for each global symbol. MPR#7585 PR#1268 binutils 2.29 arm64 linker is more strict about when to perform pc-relative relocations for global symbols. Specifically, they must be marked as .hidden. ocaml arm64 codegen does not do this, so tests/lib-dynlink-native/ fails as some symbols were not relocated. This patch fixes that by emitting a hidden alias for each global symbol and using the hidden alias in (non-GOT) adrp instructions. The aliases appear in the asm output as: .L1234: .hidden .L1234$hidden .set .L1234$hidden,.L1234 camlFoo__bar: .hidden camlFoo__bar$hidden .set camlFoo__bar$hidden,camlFoo__bar --- asmcomp/arm64/emit.mlp | 52 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 38 insertions(+), 14 deletions(-) diff --git a/asmcomp/arm64/emit.mlp b/asmcomp/arm64/emit.mlp index f75646e12..01f5dddef 100644 --- a/asmcomp/arm64/emit.mlp +++ b/asmcomp/arm64/emit.mlp @@ -49,6 +49,16 @@ let emit_label lbl = let emit_symbol s = Emitaux.emit_symbol '$' s +(* Every global label and symbol has a hidden equivalent (alias). + * See: https://github.com/ocaml/ocaml/pull/1268 + *) + +let emit_label_hidden lbl = + emit_string ".L"; emit_int lbl; emit_string "$hidden" + +let emit_symbol_hidden s = + Emitaux.emit_symbol '$' s; emit_string "$hidden" + (* Output a pseudo-register *) let emit_reg = function @@ -103,8 +113,8 @@ let emit_stack r = (* Output an addressing mode *) -let emit_symbol_offset s ofs = - emit_symbol s; +let emit_symbol_hidden_offset s ofs = + emit_symbol_hidden s; if ofs > 0 then `+{emit_int ofs}` else if ofs < 0 then `-{emit_int (-ofs)}` else () @@ -114,7 +124,7 @@ let emit_addressing addr r = | Iindexed ofs -> `[{emit_reg r}, #{emit_int ofs}]` | Ibased(s, ofs) -> - `[{emit_reg r}, #:lo12:{emit_symbol_offset s ofs}]` + `[{emit_reg r}, #:lo12:{emit_symbol_hidden_offset s ofs}]` (* Record live pointers at call points *) @@ -315,7 +325,10 @@ let emit_literals() = ` .align 3\n`; List.iter (fun (f, lbl) -> - `{emit_label lbl}:`; emit_float64_directive ".quad" f) + `{emit_label lbl}:\n`; + ` .hidden {emit_label_hidden lbl}\n`; + ` .set {emit_label_hidden lbl},{emit_label lbl}\n`; + ` `; emit_float64_directive ".quad" f) !float_literals; float_literals := [] end @@ -323,9 +336,10 @@ let emit_literals() = (* Emit code to load the address of a symbol *) let emit_load_symbol_addr dst s = - if (not !Clflags.dlcode) || Compilenv.symbol_in_current_unit s then begin - ` adrp {emit_reg dst}, {emit_symbol s}\n`; - ` add {emit_reg dst}, {emit_reg dst}, #:lo12:{emit_symbol s}\n` + if (not !Clflags.dlcode || Compilenv.symbol_in_current_unit s) && + not !Clflags.make_package (* not using -pack *) then begin + ` adrp {emit_reg dst}, {emit_symbol_hidden s}\n`; + ` add {emit_reg dst}, {emit_reg dst}, #:lo12:{emit_symbol_hidden s}\n` end else begin ` adrp {emit_reg dst}, :got:{emit_symbol s}\n`; ` ldr {emit_reg dst}, [{emit_reg dst}, #:got_lo12:{emit_symbol s}]\n` @@ -575,8 +589,8 @@ let emit_instr i = ` fmov {emit_reg i.res.(0)}, #{emit_printf "0x%Lx" f}\n` else begin let lbl = float_literal f in - ` adrp {emit_reg reg_tmp1}, {emit_label lbl}\n`; - ` ldr {emit_reg i.res.(0)}, [{emit_reg reg_tmp1}, #:lo12:{emit_label lbl}]\n` + ` adrp {emit_reg reg_tmp1}, {emit_label_hidden lbl}\n`; + ` ldr {emit_reg i.res.(0)}, [{emit_reg reg_tmp1}, #:lo12:{emit_label_hidden lbl}]\n` end | Lop(Iconst_symbol s) -> emit_load_symbol_addr i.res.(0) s @@ -609,7 +623,7 @@ let emit_instr i = match addr with | Iindexed _ -> i.arg.(0) | Ibased(s, ofs) -> - ` adrp {emit_reg reg_tmp1}, {emit_symbol_offset s ofs}\n`; + ` adrp {emit_reg reg_tmp1}, {emit_symbol_hidden_offset s ofs}\n`; reg_tmp1 in begin match size with | Byte_unsigned -> @@ -636,7 +650,7 @@ let emit_instr i = match addr with | Iindexed _ -> i.arg.(1) | Ibased(s, ofs) -> - ` adrp {emit_reg reg_tmp1}, {emit_symbol_offset s ofs}\n`; + ` adrp {emit_reg reg_tmp1}, {emit_symbol_hidden_offset s ofs}\n`; reg_tmp1 in begin match size with | Byte_unsigned | Byte_signed -> @@ -763,7 +777,9 @@ let emit_instr i = | Lreturn -> output_epilogue (fun () -> ` ret\n`) | Llabel lbl -> - `{emit_label lbl}:\n` + `{emit_label lbl}:\n`; + ` .hidden {emit_label_hidden lbl}\n`; + ` .set {emit_label_hidden lbl},{emit_label lbl}\n` | Lbranch lbl -> ` b {emit_label lbl}\n` | Lcondbranch(tst, lbl) -> @@ -891,6 +907,8 @@ let fundecl fundecl = ` .globl {emit_symbol fundecl.fun_name}\n`; ` .type {emit_symbol fundecl.fun_name}, %function\n`; `{emit_symbol fundecl.fun_name}:\n`; + ` .hidden {emit_symbol_hidden fundecl.fun_name}\n`; + ` .set {emit_symbol_hidden fundecl.fun_name},{emit_symbol fundecl.fun_name}\n`; emit_debug_info fundecl.fun_dbg; cfi_startproc(); if !Clflags.gprofile then emit_profile(); @@ -924,7 +942,10 @@ let fundecl fundecl = let emit_item = function | Cglobal_symbol s -> ` .globl {emit_symbol s}\n`; - | Cdefine_symbol s -> `{emit_symbol s}:\n` + | Cdefine_symbol s -> + `{emit_symbol s}:\n`; + ` .hidden {emit_symbol_hidden s}\n`; + ` .set {emit_symbol_hidden s},{emit_symbol s}\n` | Cint8 n -> ` .byte {emit_int n}\n` | Cint16 n -> ` .short {emit_int n}\n` | Cint32 n -> ` .long {emit_nativeint n}\n` @@ -981,7 +1002,10 @@ let end_assembly () = efa_align = (fun n -> ` .align {emit_int(Misc.log2 n)}\n`); efa_label_rel = (fun lbl ofs -> ` .long {emit_label lbl} - . + {emit_int32 ofs}\n`); - efa_def_label = (fun lbl -> `{emit_label lbl}:\n`); + efa_def_label = (fun lbl -> + `{emit_label lbl}:\n`; + ` .hidden {emit_label_hidden lbl}\n`; + ` .set {emit_label_hidden lbl},{emit_label lbl}\n`); efa_string = (fun s -> emit_string_directive " .asciz " s) }; ` .type {emit_symbol lbl}, %object\n`; ` .size {emit_symbol lbl}, .-{emit_symbol lbl}\n`; -- 2.14.0