link.sh (5732B)
1 #!/usr/bin/env bash 2 set -eu 3 4 ROOT="$(cd "$(dirname "$0")/../../.." && pwd)" 5 . "$ROOT/test/tier1/objlink/common.sh" 6 7 ARCH="${KIT_TEST_ARCH:-aa64}" 8 TRIPLE="$(t1_clang_triple "$ARCH")" 9 KITCHEN="$ROOT/test/tier1/kitchen/objlink/link" 10 WORK="$(t1_work_dir "$ROOT" link)" 11 LOG_DIR="$(t1_log_dir "$ROOT")" 12 READELF_BIN="$(command -v llvm-readelf 2>/dev/null || command -v readelf 2>/dev/null || true)" 13 KIT="${KIT:-$ROOT/build/kit}" 14 15 mkdir -p "$WORK" "$LOG_DIR" 16 t1_require_exe "$KIT" 'run: make bin' 17 [ -n "$READELF_BIN" ] || { echo "llvm-readelf/readelf not found" >&2; exit 2; } 18 command -v clang >/dev/null 2>&1 || { echo "clang not found" >&2; exit 2; } 19 20 CFLAGS=( 21 --target="$TRIPLE" -O1 -ffreestanding -fno-stack-protector 22 -fno-PIC -fno-pie -fcommon -ffunction-sections -fdata-sections 23 ) 24 PIC_CFLAGS=( 25 --target="$TRIPLE" -O1 -ffreestanding -fno-stack-protector 26 -fPIC -ffunction-sections -fdata-sections 27 ) 28 29 dynamic_linker() { 30 case "$ARCH" in 31 aa64|aarch64|arm64) printf '%s\n' /lib/ld-linux-aarch64.so.1 ;; 32 x64|x86_64|amd64) printf '%s\n' /lib64/ld-linux-x86-64.so.2 ;; 33 rv64|riscv64) printf '%s\n' /lib/ld-linux-riscv64-lp64d.so.1 ;; 34 *) printf '%s\n' /lib/ld.so ;; 35 esac 36 } 37 38 echo "tier1 link: compile $ARCH objects" 39 t1_run "$LOG_DIR/link-main-clang.log" \ 40 clang "${CFLAGS[@]}" -c "$KITCHEN/main.c" -o "$WORK/main.o" 41 t1_run "$LOG_DIR/link-helper-clang.log" \ 42 clang "${CFLAGS[@]}" -c "$KITCHEN/helper.c" -o "$WORK/helper.o" 43 t1_run "$LOG_DIR/link-archive-clang.log" \ 44 clang "${CFLAGS[@]}" -c "$KITCHEN/archive_member.c" -o "$WORK/archive_member.o" 45 t1_run "$LOG_DIR/link-start-clang.log" \ 46 clang "${CFLAGS[@]}" -c "$ROOT/test/link/harness/start.c" -o "$WORK/start.o" 47 48 echo "tier1 link: archive" 49 t1_run "$LOG_DIR/link-ar.log" "$KIT" ar rcs "$WORK/libtier1.a" "$WORK/archive_member.o" 50 51 echo "tier1 link: link executable" 52 KIT_TEST_ARCH="$ARCH" t1_run "$LOG_DIR/link-exe.log" \ 53 "$KIT" ld --gc-sections -e _start -o "$WORK/tier1.exe" \ 54 "$WORK/main.o" "$WORK/helper.o" "$WORK/start.o" "$WORK/libtier1.a" 55 56 echo "tier1 link: inspect executable" 57 "$READELF_BIN" -aW "$WORK/tier1.exe" >"$WORK/tier1.readelf" 2>"$LOG_DIR/link-readelf.log" 58 grep -Eq 'Type:[[:space:]]+EXEC|Type:[[:space:]]+DYN' "$WORK/tier1.readelf" 59 grep -Eq 'Entry point address:[[:space:]]+0x[0-9a-fA-F]+' "$WORK/tier1.readelf" 60 t1_assert_grep "link/archive-member-pulled" \ 61 '[[:space:]]tier1_archive_value($|[[:space:]])' "$WORK/tier1.readelf" 62 t1_assert_grep "link/helper-symbol" \ 63 '[[:space:]]tier1_helper_value($|[[:space:]])' "$WORK/tier1.readelf" 64 t1_assert_grep "link/live-data-relocated" \ 65 '[[:space:]]tier1_live_data($|[[:space:]])' "$WORK/tier1.readelf" 66 t1_assert_not_grep "link/gc-dead-archive-function" \ 67 '[[:space:]]\.text\.tier1_archive_dead_value[[:space:]]+PROGBITS' \ 68 "$WORK/tier1.readelf" 69 t1_assert_not_grep "link/gc-dead-local-function" \ 70 '[[:space:]]\.text\.tier1_dead_local[[:space:]]+PROGBITS' \ 71 "$WORK/tier1.readelf" 72 73 echo "tier1 link: ELF DSO creation" 74 t1_run "$LOG_DIR/link-dso-dep-cc.log" \ 75 "$KIT" cc -target "$TRIPLE" -O1 -fPIC -ffreestanding -nostdlib \ 76 -c "$KITCHEN/dso_dep.c" -o "$WORK/dso_dep.o" 77 KIT_TEST_ARCH="$ARCH" t1_run "$LOG_DIR/link-dso-so.log" \ 78 env KIT_TEST_ARCH="$ARCH" "$KIT" ld -target "$TRIPLE" \ 79 -shared -soname libtier1dep.so \ 80 "$WORK/dso_dep.o" -o "$WORK/libtier1dep.so" 81 82 "$READELF_BIN" -h "$WORK/libtier1dep.so" >"$WORK/libtier1dep.hdr" \ 83 2>"$LOG_DIR/link-dso-hdr.log" 84 "$READELF_BIN" -l "$WORK/libtier1dep.so" >"$WORK/libtier1dep.phdr" \ 85 2>"$LOG_DIR/link-dso-phdr.log" 86 "$READELF_BIN" -d "$WORK/libtier1dep.so" >"$WORK/libtier1dep.dynamic" \ 87 2>"$LOG_DIR/link-dso-dynamic.log" 88 "$READELF_BIN" --dyn-syms "$WORK/libtier1dep.so" >"$WORK/libtier1dep.dynsym" \ 89 2>"$LOG_DIR/link-dso-dynsym.log" 90 91 t1_assert_grep "link/dso-type" 'Type:[[:space:]]+DYN' "$WORK/libtier1dep.hdr" 92 t1_assert_not_grep "link/dso-no-interp" 'INTERP' "$WORK/libtier1dep.phdr" 93 t1_assert_grep "link/dso-has-dynamic" 'DYNAMIC' "$WORK/libtier1dep.phdr" 94 t1_assert_grep "link/dso-soname" 'SONAME.*libtier1dep\.so' \ 95 "$WORK/libtier1dep.dynamic" 96 t1_assert_grep "link/dso-export-func" \ 97 'GLOBAL[[:space:]]+DEFAULT.*tier1_dso_value' "$WORK/libtier1dep.dynsym" 98 t1_assert_grep "link/dso-export-data" \ 99 'GLOBAL[[:space:]]+DEFAULT.*tier1_dso_data' "$WORK/libtier1dep.dynsym" 100 t1_assert_not_grep "link/dso-hidden-not-exported" \ 101 'GLOBAL[[:space:]]+DEFAULT.*tier1_dso_hidden' "$WORK/libtier1dep.dynsym" 102 103 echo "tier1 link: ELF executable against DSO" 104 t1_run "$LOG_DIR/link-dso-main-cc.log" \ 105 clang "${PIC_CFLAGS[@]}" -c "$KITCHEN/dso_main.c" -o "$WORK/dso_main.o" 106 KIT_TEST_ARCH="$ARCH" t1_run "$LOG_DIR/link-dso-exe.log" \ 107 env KIT_TEST_ARCH="$ARCH" "$KIT" ld -target "$TRIPLE" -pie -e _start \ 108 -dynamic-linker "$(dynamic_linker)" \ 109 "$WORK/dso_main.o" "$WORK/libtier1dep.so" \ 110 -o "$WORK/dso_consumer.exe" 111 112 "$READELF_BIN" -d "$WORK/dso_consumer.exe" >"$WORK/dso_consumer.dynamic" \ 113 2>"$LOG_DIR/link-dso-consumer-dynamic.log" 114 "$READELF_BIN" --dyn-syms "$WORK/dso_consumer.exe" \ 115 >"$WORK/dso_consumer.dynsym" \ 116 2>"$LOG_DIR/link-dso-consumer-dynsym.log" 117 "$READELF_BIN" -r "$WORK/dso_consumer.exe" >"$WORK/dso_consumer.relocs" \ 118 2>"$LOG_DIR/link-dso-consumer-relocs.log" 119 120 t1_assert_grep "link/dso-consumer-needed" 'NEEDED.*libtier1dep\.so' \ 121 "$WORK/dso_consumer.dynamic" 122 t1_assert_grep "link/dso-consumer-import-func" \ 123 'UND.*tier1_dso_value' "$WORK/dso_consumer.dynsym" 124 t1_assert_grep "link/dso-consumer-import-data" \ 125 'UND.*tier1_dso_data' "$WORK/dso_consumer.dynsym" 126 t1_assert_grep "link/dso-consumer-dynrelocs" \ 127 'JUMP_SLOT|GLOB_DAT|RELATIVE' "$WORK/dso_consumer.relocs" 128 129 echo "tier1 link: ok"