summaryrefslogtreecommitdiff
path: root/tests/tst-objcopy-runner.sh
diff options
context:
space:
mode:
Diffstat (limited to 'tests/tst-objcopy-runner.sh')
-rwxr-xr-xtests/tst-objcopy-runner.sh160
1 files changed, 160 insertions, 0 deletions
diff --git a/tests/tst-objcopy-runner.sh b/tests/tst-objcopy-runner.sh
new file mode 100755
index 0000000..96b501b
--- /dev/null
+++ b/tests/tst-objcopy-runner.sh
@@ -0,0 +1,160 @@
+#!/bin/sh
+set -eu
+
+: "${PACKAGE_VERSION:?}"
+
+: "${CPU_AS:?}" "${CPU_LD:?}" "${CPU_RUN:?}" "${CPU_READELF:?}"
+: "${CPU_AR:?}" "${CPU_NM:?}" "${CPU_OBJCOPY:?}"
+
+TMP=${TMPDIR:-/tmp}/libmcpu-objcopy-$$
+mkdir -p "$TMP"
+trap 'rm -rf "$TMP"' EXIT HUP INT TERM
+
+cat > "$TMP/main.s" <<'EOS'
+.global _life
+.text
+_start_life:
+ LDI r64@0x00000, 42
+ LDI r32@0x00030, 0
+ EXIT r32@0x00030
+EOS
+
+cat > "$TMP/add-one.s" <<'EOS'
+.global add_one
+.text
+add_one:
+ LDI r64@0x00008, 1
+ IADD r64@0x00000, r64@0x00000, r64@0x00008
+ RET
+EOS
+
+"$CPU_AS" -o "$TMP/main.o" "$TMP/main.s"
+"$CPU_AS" -o "$TMP/add-one.o" "$TMP/add-one.s"
+"$CPU_LD" --stack-size=4096 --no-heap -o "$TMP/main" "$TMP/main.o"
+"$CPU_AR" rcs "$TMP/libadd.a" "$TMP/add-one.o"
+
+# Plain MELF -> MELF copying is byte-for-byte when no edit is requested.
+"$CPU_OBJCOPY" "$TMP/main" "$TMP/main.copy"
+cmp "$TMP/main" "$TMP/main.copy"
+
+printf 'metadata-one\n' > "$TMP/note-one"
+printf 'metadata-two\n' > "$TMP/note-two"
+
+# Add non-ALLOC metadata without touching the executable image.
+"$CPU_OBJCOPY" --add-section=.note.test="$TMP/note-one" \
+ "$TMP/main" "$TMP/main.note"
+"$CPU_READELF" -S "$TMP/main.note" | grep -q '\.note\.test'
+test "$("$CPU_RUN" --int-reg=r64@0x00000 "$TMP/main.note")" = 42
+
+# Dump is read-only and may inspect runtime sections as well as metadata.
+"$CPU_OBJCOPY" --dump-section=.note.test="$TMP/note.dump" \
+ "$TMP/main.note" "$TMP/main.dump-copy"
+cmp "$TMP/note-one" "$TMP/note.dump"
+"$CPU_OBJCOPY" --dump-section=.text="$TMP/text.before" \
+ "$TMP/main" "$TMP/main.text-copy"
+"$CPU_OBJCOPY" --dump-section=.text="$TMP/text.after" \
+ "$TMP/main.note" "$TMP/main.note-copy"
+cmp "$TMP/text.before" "$TMP/text.after"
+
+# Update and rename apply only to safe non-ALLOC PROGBITS metadata.
+"$CPU_OBJCOPY" --update-section=.note.test="$TMP/note-two" \
+ "$TMP/main.note" "$TMP/main.updated"
+"$CPU_OBJCOPY" --dump-section=.note.test="$TMP/updated.dump" \
+ "$TMP/main.updated" "$TMP/main.updated-copy"
+cmp "$TMP/note-two" "$TMP/updated.dump"
+
+"$CPU_OBJCOPY" --rename-section=.note.test=.note.renamed \
+ "$TMP/main.updated" "$TMP/main.renamed"
+"$CPU_READELF" -S "$TMP/main.renamed" | grep -q '\.note\.renamed'
+if "$CPU_READELF" -S "$TMP/main.renamed" | grep -q '\.note\.test'; then
+ echo "old section name survived mcpu-objcopy rename" >&2
+ exit 1
+fi
+
+# Safe metadata can be removed; runtime behavior stays unchanged.
+"$CPU_OBJCOPY" -R .note.renamed "$TMP/main.renamed" "$TMP/main.removed"
+if "$CPU_READELF" -S "$TMP/main.removed" | grep -q '\.note\.renamed'; then
+ echo "removed metadata section survived mcpu-objcopy" >&2
+ exit 1
+fi
+test "$("$CPU_RUN" --int-reg=r64@0x00000 "$TMP/main.removed")" = 42
+
+# Runtime-visible and structural sections are protected.
+if "$CPU_OBJCOPY" -R .text "$TMP/main" "$TMP/bad-remove" >/dev/null 2>&1; then
+ echo "mcpu-objcopy removed .text" >&2
+ exit 1
+fi
+if "$CPU_OBJCOPY" --update-section=.text="$TMP/note-one" \
+ "$TMP/main" "$TMP/bad-update" >/dev/null 2>&1; then
+ echo "mcpu-objcopy updated .text" >&2
+ exit 1
+fi
+if "$CPU_OBJCOPY" --rename-section=.text=.foo \
+ "$TMP/main" "$TMP/bad-rename" >/dev/null 2>&1; then
+ echo "mcpu-objcopy renamed .text" >&2
+ exit 1
+fi
+if "$CPU_OBJCOPY" --add-section=.text="$TMP/note-one" \
+ "$TMP/main" "$TMP/bad-duplicate" >/dev/null 2>&1; then
+ echo "mcpu-objcopy added duplicate .text" >&2
+ exit 1
+fi
+
+# --only-section is strict: an executable cannot lose its runtime image.
+if "$CPU_OBJCOPY" -j .note.test "$TMP/main.note" "$TMP/bad-only" \
+ >/dev/null 2>&1; then
+ echo "mcpu-objcopy created an incomplete ET_EXEC with -j" >&2
+ exit 1
+fi
+
+# ET_REL link semantics are protected, but optional metadata may be filtered.
+"$CPU_OBJCOPY" --add-section=.note.rel="$TMP/note-one" \
+ "$TMP/main.o" "$TMP/main.note.o"
+"$CPU_OBJCOPY" \
+ -j .text -j .symtab -j .strtab -j .mcpu.target -j .shstrtab \
+ "$TMP/main.note.o" "$TMP/main.filtered.o"
+if "$CPU_READELF" -S "$TMP/main.filtered.o" | grep -q '\.note\.rel'; then
+ echo "--only-section failed to remove optional ET_REL metadata" >&2
+ exit 1
+fi
+"$CPU_LD" --stack-size=4096 --no-heap -o "$TMP/main.filtered" \
+ "$TMP/main.filtered.o"
+test "$("$CPU_RUN" --int-reg=r64@0x00000 "$TMP/main.filtered")" = 42
+
+if "$CPU_OBJCOPY" -R .symtab "$TMP/main.o" "$TMP/bad-rel" \
+ >/dev/null 2>&1; then
+ echo "mcpu-objcopy removed ET_REL .symtab" >&2
+ exit 1
+fi
+
+# Archives are transformed member-by-member and retain their symbol index.
+"$CPU_OBJCOPY" --add-section=.note.arc="$TMP/note-one" \
+ "$TMP/libadd.a" "$TMP/libadd.note.a"
+"$CPU_NM" -A "$TMP/libadd.note.a" | grep -q 'add_one'
+mkdir "$TMP/extract"
+(
+ cd "$TMP/extract"
+ "$CPU_AR" x ../libadd.note.a
+ "$CPU_READELF" -S add-one.o | grep -q '\.note\.arc'
+)
+"$CPU_OBJCOPY" -R .note.arc "$TMP/libadd.note.a" "$TMP/libadd.clean.a"
+"$CPU_NM" -A "$TMP/libadd.clean.a" | grep -q 'add_one'
+if "$CPU_OBJCOPY" --dump-section=.text="$TMP/archive.dump" \
+ "$TMP/libadd.a" "$TMP/libadd.dump.a" >/dev/null 2>&1; then
+ echo "mcpu-objcopy accepted ambiguous archive --dump-section" >&2
+ exit 1
+fi
+
+"$CPU_OBJCOPY" --help | grep -q -- '--add-section=NAME=FILE'
+"$CPU_OBJCOPY" --version | grep -Fq "$PACKAGE_VERSION"
+
+if "$CPU_OBJCOPY" "$TMP/main" >/dev/null 2>&1; then
+ echo "mcpu-objcopy unexpectedly accepted a missing output file" >&2
+ exit 1
+fi
+if "$CPU_OBJCOPY" "$TMP/main" "$TMP/main" >/dev/null 2>&1; then
+ echo "mcpu-objcopy unexpectedly accepted in-place operation" >&2
+ exit 1
+fi
+
+exit 0