diff --git a/Makefile b/Makefile index 6661e623..615a5dab 100644 --- a/Makefile +++ b/Makefile @@ -53,12 +53,13 @@ BUILTIN_LIBC_HEADER := c.h STAGE0_FLAGS ?= --dump-ir STAGE1_FLAGS ?= DYNLINK ?= 0 +BINDING ?= lazy COMMENTFLOW ?= commentflow SHFMT ?= shfmt ifeq ($(DYNLINK),1) - STAGE0_FLAGS += --dynlink - STAGE1_FLAGS += --dynlink + STAGE0_FLAGS += --dynlink -z $(BINDING) + STAGE1_FLAGS += --dynlink -z $(BINDING) endif SRCS := $(wildcard $(patsubst %,%/main.c, $(SRCDIR))) @@ -183,11 +184,11 @@ uninstall-hooks: check-stage0: $(OUT)/$(STAGE0) tests/driver.sh $(VECHO) " TEST STAGE 0\n" - tests/driver.sh 0 $(DYNLINK) + tests/driver.sh 0 $(DYNLINK) $(BINDING) check-stage2: $(OUT)/$(STAGE2) tests/driver.sh $(VECHO) " TEST STAGE 2\n" - tests/driver.sh 2 $(DYNLINK) + tests/driver.sh 2 $(DYNLINK) $(BINDING) check-sanitizer: $(OUT)/$(STAGE0)-sanitizer tests/driver.sh $(VECHO) " TEST STAGE 0 (with sanitizers)\n" @@ -196,10 +197,10 @@ check-sanitizer: $(OUT)/$(STAGE0)-sanitizer tests/driver.sh $(Q)rm $(OUT)/shecc check-abi-stage0: $(OUT)/$(STAGE0) - tests/$(ARCH)-abi.sh 0 $(DYNLINK); + tests/$(ARCH)-abi.sh 0 $(DYNLINK) $(BINDING); check-abi-stage2: $(OUT)/$(STAGE2) - tests/$(ARCH)-abi.sh 2 $(DYNLINK); + tests/$(ARCH)-abi.sh 2 $(DYNLINK) $(BINDING); # Both prerequisites are order-only, and both exist because "make -j" would # otherwise let a compile start beside the thing it reads. Selecting a target diff --git a/mk/arm64.mk b/mk/arm64.mk index c6b402b2..cb60023d 100644 --- a/mk/arm64.mk +++ b/mk/arm64.mk @@ -25,7 +25,6 @@ ARCH_DEFS = \ \#define PLT_ENT_SIZE 16\n$\ \#define RESERVED_GOT_NUM 3\n$\ \#define R_ARCH_JUMP_SLOT 1026 /* R_AARCH64_JUMP_SLOT */\n$\ - \#define DYN_BIND_NOW 1\n$\ " # An Arm64 Linux host runs this target's output itself, so nothing has to stand diff --git a/mk/x64.mk b/mk/x64.mk index 85ed95a8..cff726ac 100644 --- a/mk/x64.mk +++ b/mk/x64.mk @@ -16,7 +16,6 @@ ARCH_DEFS = \ \#define RESERVED_GOT_NUM 3\n$\ \#define R_ARCH_JUMP_SLOT 7 /* R_X86_64_JUMP_SLOT */\n$\ \#define REG_CNT 11 /* rdi rsi rdx rcx r8 r9 rax rbx r14 r12 r13 */\n$\ - \#define DYN_BIND_NOW 1 /* this PLT has no lazy-resolution path */\n$\ \#define HAVE_COND_MOVE 1 /* CMOVcc */\n$\ \#define CALLEE_SAVED_REGS 4 /* the file ends rbx r14 r12 r13 */\n$\ " diff --git a/src/defs.h b/src/defs.h index 3534f2fe..3580c8a2 100644 --- a/src/defs.h +++ b/src/defs.h @@ -177,13 +177,6 @@ #define ALIGN_UP(val, align) (((val) + (align) - 1) & ~((align) - 1)) #endif -/* Targets whose PLT has no lazy-resolution path ask the loader to bind every - * PLT entry at load time. - */ -#ifndef DYN_BIND_NOW -#define DYN_BIND_NOW 0 -#endif - #define ELF_MACHINE_ARM32 0x28 #define ELF_MACHINE_RV32 0xf3 #define ELF_MACHINE_X86_64 0x3e diff --git a/src/elf.c b/src/elf.c index 66ec0e34..316d8e69 100644 --- a/src/elf.c +++ b/src/elf.c @@ -1086,14 +1086,17 @@ void elf_generate_dynamic_sections(void) elf_write_dyn(dynamic_sections.elf_dynamic, 0x3, dynamic_sections.elf_got_start); elf_write_dyn(dynamic_sections.elf_dynamic, 0x1, 0x1); -#if DYN_BIND_NOW == 1 + /* Resolve every PLT entry at load time. This target's PLT[0] does not * arrange the GOT[1]/GOT[2] hand-off the lazy resolver needs, so the loader * writes the final addresses straight into the GOT instead. */ - elf_write_dyn(dynamic_sections.elf_dynamic, 0x18, 0x0); /* DT_BIND_NOW */ - elf_write_dyn(dynamic_sections.elf_dynamic, 0x1e, 0x8); /* DF_BIND_NOW */ -#endif + if (imm_binding) { + elf_write_dyn(dynamic_sections.elf_dynamic, 0x18, + 0x0); /* DT_BIND_NOW */ + elf_write_dyn(dynamic_sections.elf_dynamic, 0x1e, + 0x8); /* DF_BIND_NOW */ + } elf_write_dyn(dynamic_sections.elf_dynamic, 0x0, 0x0); } diff --git a/src/globals.c b/src/globals.c index dd89767b..147aa133 100644 --- a/src/globals.c +++ b/src/globals.c @@ -101,6 +101,7 @@ dynamic_sections_t dynamic_sections; /* Command line compilation flags */ bool dynlink = false; +bool imm_binding = false; bool libc = true; bool expand_only = false; bool dump_ir = false; diff --git a/src/main.c b/src/main.c index 1ccd5134..84afdcf7 100644 --- a/src/main.c +++ b/src/main.c @@ -117,7 +117,18 @@ int main(int argc, char *argv[]) libc = false; else if (!strcmp(argv[i], "--dynlink")) dynlink = true; - else if (!strcmp(argv[i], "-E")) + else if (!strcmp(argv[i], "-z")) { + if (i + 1 >= argc) + usage_error("-z requires \"lazy\" or \"now\""); + + if (!strcmp(argv[i + 1], "lazy")) + imm_binding = false; + else if (!strcmp(argv[i + 1], "now")) + imm_binding = true; + else + usage_error("-z requires \"lazy\" or \"now\""); + i++; + } else if (!strcmp(argv[i], "-E")) expand_only = true; else if (!strcmp(argv[i], "-o")) { if (i + 1 < argc) { @@ -131,10 +142,21 @@ int main(int argc, char *argv[]) in = argv[i]; } + if (dynlink) { + switch (ELF_MACHINE) { + /* The following 64-bit targets have no lazy-resolution path, so + * immediate binding must be used. + */ + case ELF_MACHINE_X86_64: + case ELF_MACHINE_AARCH64: + imm_binding = true; + } + } + if (!in) { printf( "Usage: shecc [-o output] [+m] [--dot] [--dump-ir] [--no-libc] " - "[--dynlink] [-E] \n"); + "[--dynlink] [-z ] [-E] \n"); usage_error("Missing source file"); } diff --git a/tests/arm-abi.sh b/tests/arm-abi.sh index fd1b2771..cf48ad70 100755 --- a/tests/arm-abi.sh +++ b/tests/arm-abi.sh @@ -41,9 +41,10 @@ fi # Command Line Arguments if [ "$#" -lt 1 ]; then - echo "Usage: $0 []" + echo "Usage: $0 [ []]" echo " stage: 0 (host compiler), 1 (stage1), or 2 (stage2)" echo " dynlink: 0 (static linking), 1 (dynamic linking)" + echo " binding: lazy, now" echo "" echo "Environment Variables:" echo " VERBOSE=1 Enable verbose output" @@ -73,6 +74,7 @@ case "$1" in esac DYNLINK="${2:-0}" +BINDING="${3:-lazy}" # Banner echo -e "${BLUE}${BOLD}========================================${NC}" @@ -144,7 +146,7 @@ run_abi_test() # Compile local compile_cmd="$SHECC" if [[ "$DYNLINK" == "1" ]]; then - compile_cmd="$compile_cmd --dynlink" + compile_cmd="$compile_cmd --dynlink -z $BINDING" fi compile_cmd="$compile_cmd -o /tmp/shecc_abi_test_$$.elf $test_file" diff --git a/tests/arm64-abi.sh b/tests/arm64-abi.sh index 02a552fb..38989e9a 100755 --- a/tests/arm64-abi.sh +++ b/tests/arm64-abi.sh @@ -4,7 +4,7 @@ set -eu if [ "$#" -lt 1 ]; then - echo "Usage: $0 []" >&2 + echo "Usage: $0 [ []]" >&2 exit 2 fi @@ -23,7 +23,7 @@ case "$1" in esac if [ "${2:-0}" = 1 ]; then - shecc+=(--dynlink) + shecc+=(--dynlink -z "${3:-lazy}") link_mode=dynamic else link_mode=static diff --git a/tests/driver.sh b/tests/driver.sh index 0f3afd66..7a0d42d8 100755 --- a/tests/driver.sh +++ b/tests/driver.sh @@ -106,7 +106,7 @@ case "$1" in esac if [ $# -ge 2 ] && [ "$2" = "1" ]; then - readonly SHECC_CFLAGS="--dynlink" + readonly SHECC_CFLAGS="--dynlink ${3:-lazy}" readonly LINK_MODE="dynamic" else readonly SHECC_CFLAGS="" diff --git a/tests/riscv-abi.sh b/tests/riscv-abi.sh index 2ec4b338..98a271f8 100755 --- a/tests/riscv-abi.sh +++ b/tests/riscv-abi.sh @@ -41,9 +41,10 @@ fi # Command Line Arguments if [ "$#" -lt 1 ]; then - echo "Usage: $0 []" + echo "Usage: $0 [ []]" echo " stage: 0 (host compiler), 1 (stage1), or 2 (stage2)" echo " dynlink: 0 (static linking), 1 (dynamic linking)" + echo " binding: lazy, now" echo "" echo "Environment Variables:" echo " VERBOSE=1 Enable verbose output" @@ -73,6 +74,7 @@ case "$1" in esac DYNLINK="${2:-0}" +BINDING="${3:-lazy}" # Banner echo -e "${BLUE}${BOLD}========================================${NC}" @@ -144,7 +146,7 @@ run_abi_test() # Compile local compile_cmd="$SHECC" if [[ "$DYNLINK" == "1" ]]; then - compile_cmd="$compile_cmd --dynlink" + compile_cmd="$compile_cmd --dynlink -z $BINDING" fi compile_cmd="$compile_cmd -o /tmp/shecc_abi_test_$$.elf $test_file" diff --git a/tests/x64-abi.sh b/tests/x64-abi.sh index 9bcbdbbd..da91fbca 100755 --- a/tests/x64-abi.sh +++ b/tests/x64-abi.sh @@ -42,9 +42,10 @@ fi # Command Line Arguments if [ "$#" -lt 1 ]; then - echo "Usage: $0 []" + echo "Usage: $0 [ []]" echo " stage: 0 (host compiler), 1 (stage1), or 2 (stage2)" echo " dynlink: 0 (static linking), 1 (dynamic linking)" + echo " binding: lazy, now" echo "" echo "Environment Variables:" echo " VERBOSE=1 Enable verbose output" @@ -74,6 +75,7 @@ case "$1" in esac DYNLINK="${2:-0}" +BINDING="${3:-lazy}" # Banner echo -e "${BLUE}${BOLD}========================================${NC}" @@ -149,7 +151,7 @@ run_abi_test() # Compile local compile_cmd="$SHECC" if [[ "$DYNLINK" == "1" ]]; then - compile_cmd="$compile_cmd --dynlink" + compile_cmd="$compile_cmd --dynlink -z $BINDING" fi compile_cmd="$compile_cmd -o /tmp/shecc_abi_test_$$.elf $test_file"