Skip to content

Support PIC and PIE for AArch64, RISC-V and x86-64 #551

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,5 @@ jobs:
run: tools/runner.sh test1
- name: Test alternate configuration
run: tools/runner.sh test2
- name: Test alternate configuration 2
run: tools/runner.sh test3
5 changes: 3 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ latexdoc:
@chmod a-w $*.v

compcert.ini: Makefile.config
(echo "stdlib_path=$(LIBDIR)"; \
(echo "stdlib_path=$(RELLIBDIR)"; \
echo "prepro=$(CPREPRO)"; \
echo "linker=$(CLINKER)"; \
echo "asm=$(CASM)"; \
Expand All @@ -330,7 +330,8 @@ compcert.ini: Makefile.config
echo "has_runtime_lib=$(HAS_RUNTIME_LIB)"; \
echo "has_standard_headers=$(HAS_STANDARD_HEADERS)"; \
echo "asm_supports_cfi=$(ASM_SUPPORTS_CFI)"; \
echo "response_file_style=$(RESPONSEFILE)";) \
echo "response_file_style=$(RESPONSEFILE)"; \
echo "pic_supported=$(PIC_SUPPORTED)") \
> compcert.ini

compcert.config: Makefile.config
Expand Down
2 changes: 1 addition & 1 deletion aarch64/extractionMachdep.v
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Extract Constant Archi.abi =>
Extract Constant SelectOp.symbol_is_relocatable =>
"match Configuration.system with
| ""macos"" -> C2C.atom_is_external
| _ -> (fun _ -> false)".
| _ -> C2C.atom_needs_GOT_access".

(* Asm *)

Expand Down
19 changes: 18 additions & 1 deletion cfrontend/C2C.ml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,10 @@ let atom_is_static a =
with Not_found ->
false

(* Is it possible for symbol [a] to be defined in a DLL? *)
(* Is it possible for symbol [a] to be defined in a DLL?
Yes, unless [a] is defined in the current compilation unit, or is static.
(This criterion is appropriate for macOS and for Cygwin; for ELF,
see [atom_needs_GOT_access] below.) *)
let atom_is_external a =
match Hashtbl.find decl_atom a with
| { a_defined = true } -> false
Expand All @@ -61,6 +64,20 @@ let atom_is_external a =
| _ -> true
| exception Not_found -> true

(* In ELF PIC code, all non-static symbols must be accessed through
the GOT, even if they are defined in the current compilation unit.
(This is to allow symbol interposition by the dynamic loader.)
In ELF PIE code, there is no interposition, so locally-defined
symbols do not need GOT access.
In non-PIC, non-PIE mode, the GOT is unused. *)
let atom_needs_GOT_access a =
if !Clflags.option_fpic then
not (atom_is_static a)
else if !Clflags.option_fpie then
atom_is_external a
else
false

let atom_alignof a =
try
(Hashtbl.find decl_atom a).a_alignment
Expand Down
46 changes: 45 additions & 1 deletion configure
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ cprepro_options="-E"
archiver="${toolprefix}ar rcs"
libmath="-lm"
responsefile="gnu"
pic_supported=false

#
# ARM Target Configuration
Expand Down Expand Up @@ -313,9 +314,13 @@ if test "$arch" = "x86" -a "$bitsize" = "32"; then
case "$target" in
bsd)
abi="standard"
cc="${toolprefix}cc"
cc_options="-m32"
casm="${toolprefix}cc"
casm_options="-m32 -c"
clinker="${toolprefix}cc"
clinker_options="-m32"
cprepro="${toolprefix}cc"
cprepro_options="-m32 -U__GNUC__ -E"
system="bsd"
;;
Expand All @@ -342,19 +347,27 @@ if test "$arch" = "x86" -a "$bitsize" = "64"; then
case "$target" in
bsd)
abi="standard"
cc="${toolprefix}cc"
cc_options="-m64"
casm="${toolprefix}cc"
casm_options="-m64 -c"
clinker="${toolprefix}cc"
clinker_options="-m64"
clinker_needs_no_pie=false
cprepro="${toolprefix}cc"
cprepro_options="-m64 -U__GNUC__ -U__SIZEOF_INT128__ -E"
system="bsd"
pic_supported=true
;;
linux)
abi="standard"
cc_options="-m64"
casm_options="-m64 -c"
clinker_options="-m64"
clinker_needs_no_pie=false
cprepro_options="-m64 -U__GNUC__ -U__SIZEOF_INT128__ -E"
system="linux"
pic_supported=true
;;
macos|macosx)
abi="macos"
Expand All @@ -365,6 +378,7 @@ if test "$arch" = "x86" -a "$bitsize" = "64"; then
cprepro_options="-arch x86_64 -U__GNUC__ -U__SIZEOF_INT128__ -U__clang__ -U__BLOCKS__ '-D__attribute__(x)=' '-D__asm(x)=' '-D_Nullable=' '-D_Nonnull=' '-D__DARWIN_OS_INLINE=static inline' -Wno-\\#warnings -E"
libmath=""
system="macos"
pic_supported=true
;;
cygwin)
abi="standard"
Expand Down Expand Up @@ -395,8 +409,10 @@ if test "$arch" = "riscV"; then
cc_options="$model_options"
casm_options="$model_options -c"
clinker_options="$model_options"
clinker_needs_no_pie=false
cprepro_options="$model_options -U__GNUC__ -E"
system="linux"
pic_supported=true
fi

#
Expand All @@ -407,7 +423,9 @@ if test "$arch" = "aarch64"; then
linux)
abi="standard"
cprepro_options="-U__GNUC__ -E"
system="linux";;
system="linux"
pic_supported=true
;;
macos|macosx)
abi="apple"
casm="${toolprefix}cc"
Expand All @@ -419,6 +437,7 @@ if test "$arch" = "aarch64"; then
cprepro_options="-arch arm64 -U__GNUC__ -U__clang__ -U__BLOCKS__ '-D__attribute__(x)=' '-D__asm(x)=' '-D_Nullable=' '-D_Nonnull=' '-D__DARWIN_OS_INLINE=static inline' -Wno-\\#warnings -E"
libmath=""
system="macos"
pic_supported=true
;;
*)
echo "Error: invalid eabi/system '$target' for architecture AArch64." 1>&2
Expand Down Expand Up @@ -638,6 +657,15 @@ else
fi
fi

#
# See if $libdir can be accessed with a relative path from $sharedir
#
if test "$(dirname "$sharedir")/lib/compcert" = "$libdir"; then
rellibdir="../lib/compcert"
else
rellibdir="$libdir"
fi

#
# Generate Makefile.config
#
Expand All @@ -647,6 +675,7 @@ cat > Makefile.config <<EOF
PREFIX=$prefix
BINDIR=$bindir
LIBDIR=$libdir
RELLIBDIR=$rellibdir
MANDIR=$mandir
SHAREDIR=$sharedir
COQDEVDIR=$coqdevdir
Expand Down Expand Up @@ -678,6 +707,7 @@ HAS_STANDARD_HEADERS=$has_standard_headers
INSTALL_COQDEV=$install_coqdev
LIBMATH=$libmath
MODEL=$model
PIC_SUPPORTED=$pic_supported
SYSTEM=$system
RESPONSEFILE=$responsefile
LIBRARY_FLOCQ=$library_Flocq
Expand Down Expand Up @@ -741,6 +771,10 @@ ENDIANNESS=
# SYSTEM=cygwin
SYSTEM=

# Are we able to produce position-independent code (with the `-fpic` option)?
#PIC_SUPPORTED=true
PIC_SUPPORTED=false

# C compiler (for testing only)
CC=cc

Expand Down Expand Up @@ -839,6 +873,7 @@ CompCert configuration:
Hardware model................ $model
Application binary interface.. $abi
Endianness.................... $endianness
PIC generation supported...... $pic_supported
OS and development env........ $system
C compiler.................... $cc $cc_options
C preprocessor................ $cprepro $cprepro_options
Expand All @@ -856,6 +891,15 @@ CompCert configuration:
Shared config installed in.... $(expandprefix $sharedir)
Runtime library provided...... $has_runtime_lib
Library files installed in.... $(expandprefix $libdir)
EOF

if test "$rellibdir" = "$libdir"; then :; else
cat <<EOF
($rellibdir relative to compcert.ini)
EOF
fi

cat <<EOF
Man pages installed in........ $(expandprefix $mandir)
Standard headers provided..... $has_standard_headers
Standard headers installed in. $(expandprefix $libdir)/include
Expand Down
2 changes: 2 additions & 0 deletions driver/Clflags.ml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ let option_funprototyped = ref true
let option_fpacked_structs = ref false
let option_funstructured_switch = ref false
let option_ffpu = ref true
let option_fpic = ref false
let option_fpie = ref Configuration.pic_supported
let option_ffloatconstprop = ref 2
let option_ftailcalls = ref true
let option_fconstprop = ref true
Expand Down
1 change: 1 addition & 0 deletions driver/Configuration.ml
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ let stdlib_path =
else
""
let asm_supports_cfi = get_bool_config "asm_supports_cfi"
let pic_supported = get_bool_config "pic_supported"

type response_file_style =
| Gnu (* responsefiles in gnu compatible syntax *)
Expand Down
3 changes: 3 additions & 0 deletions driver/Configuration.mli
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,6 @@ val gnu_toolchain: bool

val elf_target: bool
(** Is the target binary format ELF? *)

val pic_supported: bool
(** Are we able to generate PIC and PIE code? *)
22 changes: 21 additions & 1 deletion driver/Driver.ml
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,8 @@ Processing options:
single caller [on]
-fif-conversion Perform if-conversion (generation of conditional moves) [on]
Code generation options: (use -fno-<opt> to turn off -f<opt>)
-fpic / -fPIC Generate position-independent code [off]
-fpie / -fPIE Generate position-independent executables [on if supported]
-ffpu Use FP registers for some integer operations [on]
-fsmall-data <n> Set maximal size <n> for allocation in small data area
-fsmall-const <n> Set maximal size <n> for allocation in small constant area
Expand Down Expand Up @@ -266,6 +268,16 @@ let cmdline_actions =
if n <= 0 || ((n land (n - 1)) <> 0) then
error no_loc "requested alignment %d is not a power of 2" n
in
let set_pic_mode () =
if Configuration.pic_supported
then option_fpic := true
else warning no_loc Unnamed
"option -fpic not supported on this platform, ignored" in
let set_pie_mode () =
if Configuration.pic_supported
then option_fpie := true
else warning no_loc Unnamed
"option -fpie not supported on this platform, ignored" in
[
(* Getting help *)
Exact "-help", Unit print_usage_and_exit;
Expand Down Expand Up @@ -301,7 +313,15 @@ let cmdline_actions =
Exact "-ffloat-const-prop", Integer(fun n -> option_ffloatconstprop := n);
Exact "-falign-functions", Integer(fun n -> check_align n; option_falignfunctions := Some n);
Exact "-falign-branch-targets", Integer(fun n -> check_align n; option_falignbranchtargets := n);
Exact "-falign-cond-branches", Integer(fun n -> check_align n; option_faligncondbranchs := n);] @
Exact "-falign-cond-branches", Integer(fun n -> check_align n; option_faligncondbranchs := n);
Exact "-fpic", Unit set_pic_mode;
Exact "-fPIC", Unit set_pic_mode;
Exact "-fno-pic", Unset option_fpic;
Exact "-fno-PIC", Unset option_fpic;
Exact "-fpie", Unit set_pie_mode;
Exact "-fPIE", Unit set_pie_mode;
Exact "-fno-pie", Unset option_fpie;
Exact "-fno-PIE", Unset option_fpie ] @
f_opt "common" option_fcommon @
(* Target processor options *)
(if Configuration.arch = "arm" then
Expand Down
8 changes: 7 additions & 1 deletion driver/Linker.ml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ let gnu_linker_help =
linking
-nostdlib Do not use the standard system startup files or
libraries when linking
-no-pie Do not produce a position-independent executable
-pie Produce a position-independent executable
-shared Produce a shared library instead of an executable
|}

let linker_help =
Expand Down Expand Up @@ -71,7 +74,10 @@ let linker_actions =
] @
(if Configuration.gnu_toolchain then
[ Exact "-nodefaultlibs", Self push_linker_arg;
Exact "-nostdlib", Self push_linker_arg;]
Exact "-nostdlib", Self push_linker_arg;
Exact "-pie", Self push_linker_arg;
Exact "-no-pie", Self push_linker_arg;
Exact "-shared", Self push_linker_arg]
else []) @
[ Exact "-s", Self push_linker_arg;
Exact "-static", Self push_linker_arg;
Expand Down
4 changes: 0 additions & 4 deletions riscV/Archi.v
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,3 @@ Global Opaque ptr64 big_endian splitlong
fma_order fma_invalid_mul_is_nan
float_of_single_preserves_sNaN
float_conversion_default_nan.

(** Whether to generate position-independent code or not *)

Parameter pic_code: unit -> bool.
3 changes: 2 additions & 1 deletion riscV/Asmgen.v
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Require Archi.
Require Import Coqlib Errors.
Require Import AST Integers Floats Memdata.
Require Import Op Locations Mach Asm.
Require SelectOp.

Local Open Scope string_scope.
Local Open Scope error_monad_scope.
Expand Down Expand Up @@ -419,7 +420,7 @@ Definition transl_op
else Ploadsi rd f :: k)
| Oaddrsymbol s ofs, nil =>
do rd <- ireg_of res;
OK (if Archi.pic_code tt && negb (Ptrofs.eq ofs Ptrofs.zero)
OK (if SelectOp.symbol_is_relocatable s && negb (Ptrofs.eq ofs Ptrofs.zero)
then Ploadsymbol rd s Ptrofs.zero :: addptrofs rd rd ofs k
else Ploadsymbol rd s ofs :: k)
| Oaddrstack n, nil =>
Expand Down
2 changes: 1 addition & 1 deletion riscV/Asmgenproof.v
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ Opaque Int.eq.
- destruct (preg_of r); try discriminate; destruct (preg_of m); inv H; TailNoLabel.
- destruct (Float.eq_dec n Float.zero); TailNoLabel.
- destruct (Float32.eq_dec n Float32.zero); TailNoLabel.
- destruct (Archi.pic_code tt && negb (Ptrofs.eq ofs Ptrofs.zero)).
- destruct (SelectOp.symbol_is_relocatable id && negb (Ptrofs.eq ofs Ptrofs.zero)).
+ eapply tail_nolabel_trans; [|apply addptrofs_label]. TailNoLabel.
+ TailNoLabel.
- apply opimm32_label; intros; exact I.
Expand Down
2 changes: 1 addition & 1 deletion riscV/Asmgenproof1.v
Original file line number Diff line number Diff line change
Expand Up @@ -989,7 +989,7 @@ Opaque Int.eq.
apply exec_straight_one. simpl; eauto. auto.
split; intros; Simpl.
- (* addrsymbol *)
destruct (Archi.pic_code tt && negb (Ptrofs.eq ofs Ptrofs.zero)).
destruct (SelectOp.symbol_is_relocatable id && negb (Ptrofs.eq ofs Ptrofs.zero)).
+ set (rs1 := nextinstr (rs#x <- (Genv.symbol_address ge id Ptrofs.zero))).
exploit (addptrofs_correct x x ofs k rs1 m); eauto with asmgen.
intros (rs2 & A & B & C).
Expand Down
3 changes: 2 additions & 1 deletion riscV/ConstpropOp.vp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ Require Import Coqlib Compopts.
Require Import AST Integers Floats.
Require Import Op Registers.
Require Import ValueDomain.
Require SelectOp.

(** * Converting known values to constants *)

Expand Down Expand Up @@ -298,7 +299,7 @@ Nondetfunction addr_strength_reduction
(addr: addressing) (args: list reg) (vl: list aval) :=
match addr, args, vl with
| Aindexed n, r1 :: nil, Ptr(Gl symb n1) :: nil =>
if Archi.pic_code tt
if SelectOp.symbol_is_relocatable symb
then (addr, args)
else (Aglobal symb (Ptrofs.add n1 n), nil)
| Aindexed n, r1 :: nil, Ptr(Stk n1) :: nil =>
Expand Down
2 changes: 1 addition & 1 deletion riscV/ConstpropOpproof.v
Original file line number Diff line number Diff line change
Expand Up @@ -734,7 +734,7 @@ Proof.
intros until res. unfold addr_strength_reduction.
destruct (addr_strength_reduction_match addr args vl); simpl;
intros VL EA; InvApproxRegs; SimplVM; try (inv EA).
- destruct (Archi.pic_code tt).
- destruct (SelectOp.symbol_is_relocatable symb).
+ exists (Val.offset_ptr e#r1 n); auto.
+ simpl. rewrite Genv.shift_symbol_address. econstructor; split; eauto.
inv H0; simpl; auto.
Expand Down
10 changes: 9 additions & 1 deletion riscV/SelectOp.vp
Original file line number Diff line number Diff line change
Expand Up @@ -450,10 +450,18 @@ Definition select (ty: typ) (cond: condition) (args: exprlist) (e1 e2: expr) :=

(** ** Recognition of addressing modes for load and store operations *)

(** Some symbols are relocatable (e.g. global symbols in PIC mode)
and cannot be used with [Aglobal] addressing mode. *)

Parameter symbol_is_relocatable: ident -> bool.

Nondetfunction addressing (chunk: memory_chunk) (e: expr) :=
match e with
| Eop (Oaddrstack n) Enil => (Ainstack n, Enil)
| Eop (Oaddrsymbol id ofs) Enil => if Archi.pic_code tt then (Aindexed Ptrofs.zero, e:::Enil) else (Aglobal id ofs, Enil)
| Eop (Oaddrsymbol id ofs) Enil =>
if symbol_is_relocatable id
then (Aindexed Ptrofs.zero, e:::Enil)
else (Aglobal id ofs, Enil)
| Eop (Oaddimm n) (e1:::Enil) => (Aindexed (Ptrofs.of_int n), e1:::Enil)
| Eop (Oaddlimm n) (e1:::Enil) => (Aindexed (Ptrofs.of_int64 n), e1:::Enil)
| _ => (Aindexed Ptrofs.zero, e:::Enil)
Expand Down
Loading