summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrédéric Desbiens <[email protected]>2026-08-28 09:26:12 -0400
committerGitHub <[email protected]>2026-08-28 09:26:12 -0400
commit5b94bad6a207ebb6d8135d719efff0de86e712e6 (patch)
tree03a832bac922c666917c3bcf6210e08bdb48be25
parent9c32abb17d8facca0bc74dcd30bea0ed67635cc6 (diff)
Fixed the AArch64 samples, none of which had ever linked with GCC (#673)
Every AArch64 gnu example build failed at the sample link, all 27 of them -- 13 under ports/ and 14 under ports_smp/: libg.a(libc_a-init.o): in function `__libc_init_array': undefined reference to `_init' relocation truncated to fit: R_AARCH64_CALL26 against undefined symbol `_init' libg.a(libc_a-fini.o): in function `__libc_fini_array': undefined reference to `_fini' build_threadx_sample.sh links with -nostartfiles, which is correct for a port carrying its own reset path, and that drops crti.o and crtn.o along with everything else. startup.S calls __libc_init_array by design, and newlib's implementation calls _init, which crti.o is what defines. The AArch32 scripts are unaffected: they use nosys.specs and never reach __libc_init_array. The fix links crti.o and crtn.o explicitly, bracketing the object list -- the first must precede every .init contribution and the second must follow all of them, so their position is load-bearing rather than stylistic. Both paths come from the compiler's own -print-file-name, so nothing here hard-codes a toolchain layout. The atfe branch sets both to empty, deliberately: picolibc's __libc_init_array does not call _init, those 27 images link today, and adding crti.o would change a working link for no reason. That is also why check_clang.sh is green on these and does not list them as expected to fail -- the LLVM path never reached the gap, so nothing has ever linked them and failed. Fixed in ports_arch/ARMv8-A/threadx/ports/gnu/example_build, which is the single source for both the ports/ and ports_smp/ copies, then regenerated with update.sh --port-sets tx,tx_smp. The 27 generated copies are in this commit because ports_arch_check compares them. Verified: all 27 link with arm-gnu-toolchain 14.3.rel1 aarch64-none-elf, where 0 of 27 did before; _init and _fini disassemble to the expected crti prologue and crtn epilogue over a ret; check_clang.sh with ATfE 22.1.0 is still green on all five stages, including the 42 script-driven example builds; check_ports.sh is green including the reproducibility check. No regression test: these are link-only example images that no host test executes. What guards them is check_clang.sh's example stage today, and check_gcc.sh's, which is the next change and is the reason this was found. Assisted-by: Claude Code (Opus 5) <[email protected]>
-rwxr-xr-xports/cortex_a34/gnu/example_build/build_threadx_sample.sh24
-rwxr-xr-xports/cortex_a35/gnu/example_build/build_threadx_sample.sh24
-rwxr-xr-xports/cortex_a53/gnu/example_build/build_threadx_sample.sh24
-rwxr-xr-xports/cortex_a55/gnu/example_build/build_threadx_sample.sh24
-rwxr-xr-xports/cortex_a57/gnu/example_build/build_threadx_sample.sh24
-rwxr-xr-xports/cortex_a65/gnu/example_build/build_threadx_sample.sh24
-rwxr-xr-xports/cortex_a65ae/gnu/example_build/build_threadx_sample.sh24
-rwxr-xr-xports/cortex_a72/gnu/example_build/build_threadx_sample.sh24
-rwxr-xr-xports/cortex_a73/gnu/example_build/build_threadx_sample.sh24
-rwxr-xr-xports/cortex_a75/gnu/example_build/build_threadx_sample.sh24
-rwxr-xr-xports/cortex_a76/gnu/example_build/build_threadx_sample.sh24
-rwxr-xr-xports/cortex_a76ae/gnu/example_build/build_threadx_sample.sh24
-rwxr-xr-xports/cortex_a77/gnu/example_build/build_threadx_sample.sh24
-rwxr-xr-xports_arch/ARMv8-A/threadx/ports/gnu/example_build/build_threadx_sample.sh24
-rwxr-xr-xports_smp/cortex_a34_smp/gnu/example_build/build_threadx_sample.sh24
-rwxr-xr-xports_smp/cortex_a35_smp/gnu/example_build/build_threadx_sample.sh24
-rwxr-xr-xports_smp/cortex_a53_smp/gnu/example_build/build_threadx_sample.sh24
-rwxr-xr-xports_smp/cortex_a55_smp/gnu/example_build/build_threadx_sample.sh24
-rwxr-xr-xports_smp/cortex_a57_smp/gnu/example_build/build_threadx_sample.sh24
-rwxr-xr-xports_smp/cortex_a65_smp/gnu/example_build/build_threadx_sample.sh24
-rwxr-xr-xports_smp/cortex_a65ae_smp/gnu/example_build/build_threadx_sample.sh24
-rwxr-xr-xports_smp/cortex_a72_smp/gnu/example_build/build_threadx_sample.sh24
-rwxr-xr-xports_smp/cortex_a73_smp/gnu/example_build/build_threadx_sample.sh24
-rwxr-xr-xports_smp/cortex_a75_smp/gnu/example_build/build_threadx_sample.sh24
-rwxr-xr-xports_smp/cortex_a76_smp/gnu/example_build/build_threadx_sample.sh24
-rwxr-xr-xports_smp/cortex_a76ae_smp/gnu/example_build/build_threadx_sample.sh24
-rwxr-xr-xports_smp/cortex_a77_smp/gnu/example_build/build_threadx_sample.sh24
-rwxr-xr-xports_smp/cortex_a78_smp/gnu/example_build/build_threadx_sample.sh24
28 files changed, 644 insertions, 28 deletions
diff --git a/ports/cortex_a34/gnu/example_build/build_threadx_sample.sh b/ports/cortex_a34/gnu/example_build/build_threadx_sample.sh
index fa5b92ec..94248a88 100755
--- a/ports/cortex_a34/gnu/example_build/build_threadx_sample.sh
+++ b/ports/cortex_a34/gnu/example_build/build_threadx_sample.sh
@@ -44,6 +44,23 @@ case "${TOOLCHAIN}" in
# initialise_monitor_handles that startup.S calls.
SYSCALL_LIB="--specs=rdimon.specs"
SEMIHOST_STUB=""
+ # crti.o defines _init and _fini; crtn.o closes them. The link below
+ # passes -nostartfiles, which is right for a port with its own reset
+ # path but also drops these two, and startup.S calls
+ # __libc_init_array, whose newlib implementation calls _init. Without
+ # them every AArch64 sample failed to link:
+ #
+ # libg.a(libc_a-init.o): in function `__libc_init_array':
+ # undefined reference to `_init'
+ # relocation truncated to fit: R_AARCH64_CALL26 against undefined
+ # symbol `_init'
+ #
+ # crti.o must precede every other .init contribution and crtn.o must
+ # follow all of them, which is why they bracket the object list rather
+ # than sitting with the other flags. The AArch32 scripts need none of
+ # this: they use nosys.specs and never reach __libc_init_array.
+ CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)"
+ CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)"
;;
atfe)
CC="${ATFE_CLANG:-clang}"
@@ -52,6 +69,11 @@ case "${TOOLCHAIN}" in
# picolibc has no initialise_monitor_handles, and neither does the
# toolchain's semihosting library, so the weak stub stands in for it.
SEMIHOST_STUB="sample_threadx/semihost_stub.S"
+ # Deliberately empty. picolibc's __libc_init_array does not call _init,
+ # so these images link today and adding crti.o would change a working
+ # link for no reason.
+ CRT_BEGIN=""
+ CRT_END=""
;;
*)
echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2
@@ -80,7 +102,7 @@ done
"${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \
-T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \
-o sample_threadx.out -Wl,-Map=sample_threadx.map \
- ${objects} tx.a
+ ${CRT_BEGIN} ${objects} tx.a ${CRT_END}
rm -f ${objects}
diff --git a/ports/cortex_a35/gnu/example_build/build_threadx_sample.sh b/ports/cortex_a35/gnu/example_build/build_threadx_sample.sh
index fa5b92ec..94248a88 100755
--- a/ports/cortex_a35/gnu/example_build/build_threadx_sample.sh
+++ b/ports/cortex_a35/gnu/example_build/build_threadx_sample.sh
@@ -44,6 +44,23 @@ case "${TOOLCHAIN}" in
# initialise_monitor_handles that startup.S calls.
SYSCALL_LIB="--specs=rdimon.specs"
SEMIHOST_STUB=""
+ # crti.o defines _init and _fini; crtn.o closes them. The link below
+ # passes -nostartfiles, which is right for a port with its own reset
+ # path but also drops these two, and startup.S calls
+ # __libc_init_array, whose newlib implementation calls _init. Without
+ # them every AArch64 sample failed to link:
+ #
+ # libg.a(libc_a-init.o): in function `__libc_init_array':
+ # undefined reference to `_init'
+ # relocation truncated to fit: R_AARCH64_CALL26 against undefined
+ # symbol `_init'
+ #
+ # crti.o must precede every other .init contribution and crtn.o must
+ # follow all of them, which is why they bracket the object list rather
+ # than sitting with the other flags. The AArch32 scripts need none of
+ # this: they use nosys.specs and never reach __libc_init_array.
+ CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)"
+ CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)"
;;
atfe)
CC="${ATFE_CLANG:-clang}"
@@ -52,6 +69,11 @@ case "${TOOLCHAIN}" in
# picolibc has no initialise_monitor_handles, and neither does the
# toolchain's semihosting library, so the weak stub stands in for it.
SEMIHOST_STUB="sample_threadx/semihost_stub.S"
+ # Deliberately empty. picolibc's __libc_init_array does not call _init,
+ # so these images link today and adding crti.o would change a working
+ # link for no reason.
+ CRT_BEGIN=""
+ CRT_END=""
;;
*)
echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2
@@ -80,7 +102,7 @@ done
"${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \
-T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \
-o sample_threadx.out -Wl,-Map=sample_threadx.map \
- ${objects} tx.a
+ ${CRT_BEGIN} ${objects} tx.a ${CRT_END}
rm -f ${objects}
diff --git a/ports/cortex_a53/gnu/example_build/build_threadx_sample.sh b/ports/cortex_a53/gnu/example_build/build_threadx_sample.sh
index fa5b92ec..94248a88 100755
--- a/ports/cortex_a53/gnu/example_build/build_threadx_sample.sh
+++ b/ports/cortex_a53/gnu/example_build/build_threadx_sample.sh
@@ -44,6 +44,23 @@ case "${TOOLCHAIN}" in
# initialise_monitor_handles that startup.S calls.
SYSCALL_LIB="--specs=rdimon.specs"
SEMIHOST_STUB=""
+ # crti.o defines _init and _fini; crtn.o closes them. The link below
+ # passes -nostartfiles, which is right for a port with its own reset
+ # path but also drops these two, and startup.S calls
+ # __libc_init_array, whose newlib implementation calls _init. Without
+ # them every AArch64 sample failed to link:
+ #
+ # libg.a(libc_a-init.o): in function `__libc_init_array':
+ # undefined reference to `_init'
+ # relocation truncated to fit: R_AARCH64_CALL26 against undefined
+ # symbol `_init'
+ #
+ # crti.o must precede every other .init contribution and crtn.o must
+ # follow all of them, which is why they bracket the object list rather
+ # than sitting with the other flags. The AArch32 scripts need none of
+ # this: they use nosys.specs and never reach __libc_init_array.
+ CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)"
+ CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)"
;;
atfe)
CC="${ATFE_CLANG:-clang}"
@@ -52,6 +69,11 @@ case "${TOOLCHAIN}" in
# picolibc has no initialise_monitor_handles, and neither does the
# toolchain's semihosting library, so the weak stub stands in for it.
SEMIHOST_STUB="sample_threadx/semihost_stub.S"
+ # Deliberately empty. picolibc's __libc_init_array does not call _init,
+ # so these images link today and adding crti.o would change a working
+ # link for no reason.
+ CRT_BEGIN=""
+ CRT_END=""
;;
*)
echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2
@@ -80,7 +102,7 @@ done
"${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \
-T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \
-o sample_threadx.out -Wl,-Map=sample_threadx.map \
- ${objects} tx.a
+ ${CRT_BEGIN} ${objects} tx.a ${CRT_END}
rm -f ${objects}
diff --git a/ports/cortex_a55/gnu/example_build/build_threadx_sample.sh b/ports/cortex_a55/gnu/example_build/build_threadx_sample.sh
index fa5b92ec..94248a88 100755
--- a/ports/cortex_a55/gnu/example_build/build_threadx_sample.sh
+++ b/ports/cortex_a55/gnu/example_build/build_threadx_sample.sh
@@ -44,6 +44,23 @@ case "${TOOLCHAIN}" in
# initialise_monitor_handles that startup.S calls.
SYSCALL_LIB="--specs=rdimon.specs"
SEMIHOST_STUB=""
+ # crti.o defines _init and _fini; crtn.o closes them. The link below
+ # passes -nostartfiles, which is right for a port with its own reset
+ # path but also drops these two, and startup.S calls
+ # __libc_init_array, whose newlib implementation calls _init. Without
+ # them every AArch64 sample failed to link:
+ #
+ # libg.a(libc_a-init.o): in function `__libc_init_array':
+ # undefined reference to `_init'
+ # relocation truncated to fit: R_AARCH64_CALL26 against undefined
+ # symbol `_init'
+ #
+ # crti.o must precede every other .init contribution and crtn.o must
+ # follow all of them, which is why they bracket the object list rather
+ # than sitting with the other flags. The AArch32 scripts need none of
+ # this: they use nosys.specs and never reach __libc_init_array.
+ CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)"
+ CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)"
;;
atfe)
CC="${ATFE_CLANG:-clang}"
@@ -52,6 +69,11 @@ case "${TOOLCHAIN}" in
# picolibc has no initialise_monitor_handles, and neither does the
# toolchain's semihosting library, so the weak stub stands in for it.
SEMIHOST_STUB="sample_threadx/semihost_stub.S"
+ # Deliberately empty. picolibc's __libc_init_array does not call _init,
+ # so these images link today and adding crti.o would change a working
+ # link for no reason.
+ CRT_BEGIN=""
+ CRT_END=""
;;
*)
echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2
@@ -80,7 +102,7 @@ done
"${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \
-T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \
-o sample_threadx.out -Wl,-Map=sample_threadx.map \
- ${objects} tx.a
+ ${CRT_BEGIN} ${objects} tx.a ${CRT_END}
rm -f ${objects}
diff --git a/ports/cortex_a57/gnu/example_build/build_threadx_sample.sh b/ports/cortex_a57/gnu/example_build/build_threadx_sample.sh
index fa5b92ec..94248a88 100755
--- a/ports/cortex_a57/gnu/example_build/build_threadx_sample.sh
+++ b/ports/cortex_a57/gnu/example_build/build_threadx_sample.sh
@@ -44,6 +44,23 @@ case "${TOOLCHAIN}" in
# initialise_monitor_handles that startup.S calls.
SYSCALL_LIB="--specs=rdimon.specs"
SEMIHOST_STUB=""
+ # crti.o defines _init and _fini; crtn.o closes them. The link below
+ # passes -nostartfiles, which is right for a port with its own reset
+ # path but also drops these two, and startup.S calls
+ # __libc_init_array, whose newlib implementation calls _init. Without
+ # them every AArch64 sample failed to link:
+ #
+ # libg.a(libc_a-init.o): in function `__libc_init_array':
+ # undefined reference to `_init'
+ # relocation truncated to fit: R_AARCH64_CALL26 against undefined
+ # symbol `_init'
+ #
+ # crti.o must precede every other .init contribution and crtn.o must
+ # follow all of them, which is why they bracket the object list rather
+ # than sitting with the other flags. The AArch32 scripts need none of
+ # this: they use nosys.specs and never reach __libc_init_array.
+ CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)"
+ CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)"
;;
atfe)
CC="${ATFE_CLANG:-clang}"
@@ -52,6 +69,11 @@ case "${TOOLCHAIN}" in
# picolibc has no initialise_monitor_handles, and neither does the
# toolchain's semihosting library, so the weak stub stands in for it.
SEMIHOST_STUB="sample_threadx/semihost_stub.S"
+ # Deliberately empty. picolibc's __libc_init_array does not call _init,
+ # so these images link today and adding crti.o would change a working
+ # link for no reason.
+ CRT_BEGIN=""
+ CRT_END=""
;;
*)
echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2
@@ -80,7 +102,7 @@ done
"${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \
-T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \
-o sample_threadx.out -Wl,-Map=sample_threadx.map \
- ${objects} tx.a
+ ${CRT_BEGIN} ${objects} tx.a ${CRT_END}
rm -f ${objects}
diff --git a/ports/cortex_a65/gnu/example_build/build_threadx_sample.sh b/ports/cortex_a65/gnu/example_build/build_threadx_sample.sh
index fa5b92ec..94248a88 100755
--- a/ports/cortex_a65/gnu/example_build/build_threadx_sample.sh
+++ b/ports/cortex_a65/gnu/example_build/build_threadx_sample.sh
@@ -44,6 +44,23 @@ case "${TOOLCHAIN}" in
# initialise_monitor_handles that startup.S calls.
SYSCALL_LIB="--specs=rdimon.specs"
SEMIHOST_STUB=""
+ # crti.o defines _init and _fini; crtn.o closes them. The link below
+ # passes -nostartfiles, which is right for a port with its own reset
+ # path but also drops these two, and startup.S calls
+ # __libc_init_array, whose newlib implementation calls _init. Without
+ # them every AArch64 sample failed to link:
+ #
+ # libg.a(libc_a-init.o): in function `__libc_init_array':
+ # undefined reference to `_init'
+ # relocation truncated to fit: R_AARCH64_CALL26 against undefined
+ # symbol `_init'
+ #
+ # crti.o must precede every other .init contribution and crtn.o must
+ # follow all of them, which is why they bracket the object list rather
+ # than sitting with the other flags. The AArch32 scripts need none of
+ # this: they use nosys.specs and never reach __libc_init_array.
+ CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)"
+ CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)"
;;
atfe)
CC="${ATFE_CLANG:-clang}"
@@ -52,6 +69,11 @@ case "${TOOLCHAIN}" in
# picolibc has no initialise_monitor_handles, and neither does the
# toolchain's semihosting library, so the weak stub stands in for it.
SEMIHOST_STUB="sample_threadx/semihost_stub.S"
+ # Deliberately empty. picolibc's __libc_init_array does not call _init,
+ # so these images link today and adding crti.o would change a working
+ # link for no reason.
+ CRT_BEGIN=""
+ CRT_END=""
;;
*)
echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2
@@ -80,7 +102,7 @@ done
"${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \
-T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \
-o sample_threadx.out -Wl,-Map=sample_threadx.map \
- ${objects} tx.a
+ ${CRT_BEGIN} ${objects} tx.a ${CRT_END}
rm -f ${objects}
diff --git a/ports/cortex_a65ae/gnu/example_build/build_threadx_sample.sh b/ports/cortex_a65ae/gnu/example_build/build_threadx_sample.sh
index fa5b92ec..94248a88 100755
--- a/ports/cortex_a65ae/gnu/example_build/build_threadx_sample.sh
+++ b/ports/cortex_a65ae/gnu/example_build/build_threadx_sample.sh
@@ -44,6 +44,23 @@ case "${TOOLCHAIN}" in
# initialise_monitor_handles that startup.S calls.
SYSCALL_LIB="--specs=rdimon.specs"
SEMIHOST_STUB=""
+ # crti.o defines _init and _fini; crtn.o closes them. The link below
+ # passes -nostartfiles, which is right for a port with its own reset
+ # path but also drops these two, and startup.S calls
+ # __libc_init_array, whose newlib implementation calls _init. Without
+ # them every AArch64 sample failed to link:
+ #
+ # libg.a(libc_a-init.o): in function `__libc_init_array':
+ # undefined reference to `_init'
+ # relocation truncated to fit: R_AARCH64_CALL26 against undefined
+ # symbol `_init'
+ #
+ # crti.o must precede every other .init contribution and crtn.o must
+ # follow all of them, which is why they bracket the object list rather
+ # than sitting with the other flags. The AArch32 scripts need none of
+ # this: they use nosys.specs and never reach __libc_init_array.
+ CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)"
+ CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)"
;;
atfe)
CC="${ATFE_CLANG:-clang}"
@@ -52,6 +69,11 @@ case "${TOOLCHAIN}" in
# picolibc has no initialise_monitor_handles, and neither does the
# toolchain's semihosting library, so the weak stub stands in for it.
SEMIHOST_STUB="sample_threadx/semihost_stub.S"
+ # Deliberately empty. picolibc's __libc_init_array does not call _init,
+ # so these images link today and adding crti.o would change a working
+ # link for no reason.
+ CRT_BEGIN=""
+ CRT_END=""
;;
*)
echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2
@@ -80,7 +102,7 @@ done
"${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \
-T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \
-o sample_threadx.out -Wl,-Map=sample_threadx.map \
- ${objects} tx.a
+ ${CRT_BEGIN} ${objects} tx.a ${CRT_END}
rm -f ${objects}
diff --git a/ports/cortex_a72/gnu/example_build/build_threadx_sample.sh b/ports/cortex_a72/gnu/example_build/build_threadx_sample.sh
index fa5b92ec..94248a88 100755
--- a/ports/cortex_a72/gnu/example_build/build_threadx_sample.sh
+++ b/ports/cortex_a72/gnu/example_build/build_threadx_sample.sh
@@ -44,6 +44,23 @@ case "${TOOLCHAIN}" in
# initialise_monitor_handles that startup.S calls.
SYSCALL_LIB="--specs=rdimon.specs"
SEMIHOST_STUB=""
+ # crti.o defines _init and _fini; crtn.o closes them. The link below
+ # passes -nostartfiles, which is right for a port with its own reset
+ # path but also drops these two, and startup.S calls
+ # __libc_init_array, whose newlib implementation calls _init. Without
+ # them every AArch64 sample failed to link:
+ #
+ # libg.a(libc_a-init.o): in function `__libc_init_array':
+ # undefined reference to `_init'
+ # relocation truncated to fit: R_AARCH64_CALL26 against undefined
+ # symbol `_init'
+ #
+ # crti.o must precede every other .init contribution and crtn.o must
+ # follow all of them, which is why they bracket the object list rather
+ # than sitting with the other flags. The AArch32 scripts need none of
+ # this: they use nosys.specs and never reach __libc_init_array.
+ CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)"
+ CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)"
;;
atfe)
CC="${ATFE_CLANG:-clang}"
@@ -52,6 +69,11 @@ case "${TOOLCHAIN}" in
# picolibc has no initialise_monitor_handles, and neither does the
# toolchain's semihosting library, so the weak stub stands in for it.
SEMIHOST_STUB="sample_threadx/semihost_stub.S"
+ # Deliberately empty. picolibc's __libc_init_array does not call _init,
+ # so these images link today and adding crti.o would change a working
+ # link for no reason.
+ CRT_BEGIN=""
+ CRT_END=""
;;
*)
echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2
@@ -80,7 +102,7 @@ done
"${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \
-T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \
-o sample_threadx.out -Wl,-Map=sample_threadx.map \
- ${objects} tx.a
+ ${CRT_BEGIN} ${objects} tx.a ${CRT_END}
rm -f ${objects}
diff --git a/ports/cortex_a73/gnu/example_build/build_threadx_sample.sh b/ports/cortex_a73/gnu/example_build/build_threadx_sample.sh
index fa5b92ec..94248a88 100755
--- a/ports/cortex_a73/gnu/example_build/build_threadx_sample.sh
+++ b/ports/cortex_a73/gnu/example_build/build_threadx_sample.sh
@@ -44,6 +44,23 @@ case "${TOOLCHAIN}" in
# initialise_monitor_handles that startup.S calls.
SYSCALL_LIB="--specs=rdimon.specs"
SEMIHOST_STUB=""
+ # crti.o defines _init and _fini; crtn.o closes them. The link below
+ # passes -nostartfiles, which is right for a port with its own reset
+ # path but also drops these two, and startup.S calls
+ # __libc_init_array, whose newlib implementation calls _init. Without
+ # them every AArch64 sample failed to link:
+ #
+ # libg.a(libc_a-init.o): in function `__libc_init_array':
+ # undefined reference to `_init'
+ # relocation truncated to fit: R_AARCH64_CALL26 against undefined
+ # symbol `_init'
+ #
+ # crti.o must precede every other .init contribution and crtn.o must
+ # follow all of them, which is why they bracket the object list rather
+ # than sitting with the other flags. The AArch32 scripts need none of
+ # this: they use nosys.specs and never reach __libc_init_array.
+ CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)"
+ CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)"
;;
atfe)
CC="${ATFE_CLANG:-clang}"
@@ -52,6 +69,11 @@ case "${TOOLCHAIN}" in
# picolibc has no initialise_monitor_handles, and neither does the
# toolchain's semihosting library, so the weak stub stands in for it.
SEMIHOST_STUB="sample_threadx/semihost_stub.S"
+ # Deliberately empty. picolibc's __libc_init_array does not call _init,
+ # so these images link today and adding crti.o would change a working
+ # link for no reason.
+ CRT_BEGIN=""
+ CRT_END=""
;;
*)
echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2
@@ -80,7 +102,7 @@ done
"${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \
-T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \
-o sample_threadx.out -Wl,-Map=sample_threadx.map \
- ${objects} tx.a
+ ${CRT_BEGIN} ${objects} tx.a ${CRT_END}
rm -f ${objects}
diff --git a/ports/cortex_a75/gnu/example_build/build_threadx_sample.sh b/ports/cortex_a75/gnu/example_build/build_threadx_sample.sh
index fa5b92ec..94248a88 100755
--- a/ports/cortex_a75/gnu/example_build/build_threadx_sample.sh
+++ b/ports/cortex_a75/gnu/example_build/build_threadx_sample.sh
@@ -44,6 +44,23 @@ case "${TOOLCHAIN}" in
# initialise_monitor_handles that startup.S calls.
SYSCALL_LIB="--specs=rdimon.specs"
SEMIHOST_STUB=""
+ # crti.o defines _init and _fini; crtn.o closes them. The link below
+ # passes -nostartfiles, which is right for a port with its own reset
+ # path but also drops these two, and startup.S calls
+ # __libc_init_array, whose newlib implementation calls _init. Without
+ # them every AArch64 sample failed to link:
+ #
+ # libg.a(libc_a-init.o): in function `__libc_init_array':
+ # undefined reference to `_init'
+ # relocation truncated to fit: R_AARCH64_CALL26 against undefined
+ # symbol `_init'
+ #
+ # crti.o must precede every other .init contribution and crtn.o must
+ # follow all of them, which is why they bracket the object list rather
+ # than sitting with the other flags. The AArch32 scripts need none of
+ # this: they use nosys.specs and never reach __libc_init_array.
+ CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)"
+ CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)"
;;
atfe)
CC="${ATFE_CLANG:-clang}"
@@ -52,6 +69,11 @@ case "${TOOLCHAIN}" in
# picolibc has no initialise_monitor_handles, and neither does the
# toolchain's semihosting library, so the weak stub stands in for it.
SEMIHOST_STUB="sample_threadx/semihost_stub.S"
+ # Deliberately empty. picolibc's __libc_init_array does not call _init,
+ # so these images link today and adding crti.o would change a working
+ # link for no reason.
+ CRT_BEGIN=""
+ CRT_END=""
;;
*)
echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2
@@ -80,7 +102,7 @@ done
"${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \
-T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \
-o sample_threadx.out -Wl,-Map=sample_threadx.map \
- ${objects} tx.a
+ ${CRT_BEGIN} ${objects} tx.a ${CRT_END}
rm -f ${objects}
diff --git a/ports/cortex_a76/gnu/example_build/build_threadx_sample.sh b/ports/cortex_a76/gnu/example_build/build_threadx_sample.sh
index fa5b92ec..94248a88 100755
--- a/ports/cortex_a76/gnu/example_build/build_threadx_sample.sh
+++ b/ports/cortex_a76/gnu/example_build/build_threadx_sample.sh
@@ -44,6 +44,23 @@ case "${TOOLCHAIN}" in
# initialise_monitor_handles that startup.S calls.
SYSCALL_LIB="--specs=rdimon.specs"
SEMIHOST_STUB=""
+ # crti.o defines _init and _fini; crtn.o closes them. The link below
+ # passes -nostartfiles, which is right for a port with its own reset
+ # path but also drops these two, and startup.S calls
+ # __libc_init_array, whose newlib implementation calls _init. Without
+ # them every AArch64 sample failed to link:
+ #
+ # libg.a(libc_a-init.o): in function `__libc_init_array':
+ # undefined reference to `_init'
+ # relocation truncated to fit: R_AARCH64_CALL26 against undefined
+ # symbol `_init'
+ #
+ # crti.o must precede every other .init contribution and crtn.o must
+ # follow all of them, which is why they bracket the object list rather
+ # than sitting with the other flags. The AArch32 scripts need none of
+ # this: they use nosys.specs and never reach __libc_init_array.
+ CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)"
+ CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)"
;;
atfe)
CC="${ATFE_CLANG:-clang}"
@@ -52,6 +69,11 @@ case "${TOOLCHAIN}" in
# picolibc has no initialise_monitor_handles, and neither does the
# toolchain's semihosting library, so the weak stub stands in for it.
SEMIHOST_STUB="sample_threadx/semihost_stub.S"
+ # Deliberately empty. picolibc's __libc_init_array does not call _init,
+ # so these images link today and adding crti.o would change a working
+ # link for no reason.
+ CRT_BEGIN=""
+ CRT_END=""
;;
*)
echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2
@@ -80,7 +102,7 @@ done
"${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \
-T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \
-o sample_threadx.out -Wl,-Map=sample_threadx.map \
- ${objects} tx.a
+ ${CRT_BEGIN} ${objects} tx.a ${CRT_END}
rm -f ${objects}
diff --git a/ports/cortex_a76ae/gnu/example_build/build_threadx_sample.sh b/ports/cortex_a76ae/gnu/example_build/build_threadx_sample.sh
index fa5b92ec..94248a88 100755
--- a/ports/cortex_a76ae/gnu/example_build/build_threadx_sample.sh
+++ b/ports/cortex_a76ae/gnu/example_build/build_threadx_sample.sh
@@ -44,6 +44,23 @@ case "${TOOLCHAIN}" in
# initialise_monitor_handles that startup.S calls.
SYSCALL_LIB="--specs=rdimon.specs"
SEMIHOST_STUB=""
+ # crti.o defines _init and _fini; crtn.o closes them. The link below
+ # passes -nostartfiles, which is right for a port with its own reset
+ # path but also drops these two, and startup.S calls
+ # __libc_init_array, whose newlib implementation calls _init. Without
+ # them every AArch64 sample failed to link:
+ #
+ # libg.a(libc_a-init.o): in function `__libc_init_array':
+ # undefined reference to `_init'
+ # relocation truncated to fit: R_AARCH64_CALL26 against undefined
+ # symbol `_init'
+ #
+ # crti.o must precede every other .init contribution and crtn.o must
+ # follow all of them, which is why they bracket the object list rather
+ # than sitting with the other flags. The AArch32 scripts need none of
+ # this: they use nosys.specs and never reach __libc_init_array.
+ CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)"
+ CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)"
;;
atfe)
CC="${ATFE_CLANG:-clang}"
@@ -52,6 +69,11 @@ case "${TOOLCHAIN}" in
# picolibc has no initialise_monitor_handles, and neither does the
# toolchain's semihosting library, so the weak stub stands in for it.
SEMIHOST_STUB="sample_threadx/semihost_stub.S"
+ # Deliberately empty. picolibc's __libc_init_array does not call _init,
+ # so these images link today and adding crti.o would change a working
+ # link for no reason.
+ CRT_BEGIN=""
+ CRT_END=""
;;
*)
echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2
@@ -80,7 +102,7 @@ done
"${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \
-T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \
-o sample_threadx.out -Wl,-Map=sample_threadx.map \
- ${objects} tx.a
+ ${CRT_BEGIN} ${objects} tx.a ${CRT_END}
rm -f ${objects}
diff --git a/ports/cortex_a77/gnu/example_build/build_threadx_sample.sh b/ports/cortex_a77/gnu/example_build/build_threadx_sample.sh
index fa5b92ec..94248a88 100755
--- a/ports/cortex_a77/gnu/example_build/build_threadx_sample.sh
+++ b/ports/cortex_a77/gnu/example_build/build_threadx_sample.sh
@@ -44,6 +44,23 @@ case "${TOOLCHAIN}" in
# initialise_monitor_handles that startup.S calls.
SYSCALL_LIB="--specs=rdimon.specs"
SEMIHOST_STUB=""
+ # crti.o defines _init and _fini; crtn.o closes them. The link below
+ # passes -nostartfiles, which is right for a port with its own reset
+ # path but also drops these two, and startup.S calls
+ # __libc_init_array, whose newlib implementation calls _init. Without
+ # them every AArch64 sample failed to link:
+ #
+ # libg.a(libc_a-init.o): in function `__libc_init_array':
+ # undefined reference to `_init'
+ # relocation truncated to fit: R_AARCH64_CALL26 against undefined
+ # symbol `_init'
+ #
+ # crti.o must precede every other .init contribution and crtn.o must
+ # follow all of them, which is why they bracket the object list rather
+ # than sitting with the other flags. The AArch32 scripts need none of
+ # this: they use nosys.specs and never reach __libc_init_array.
+ CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)"
+ CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)"
;;
atfe)
CC="${ATFE_CLANG:-clang}"
@@ -52,6 +69,11 @@ case "${TOOLCHAIN}" in
# picolibc has no initialise_monitor_handles, and neither does the
# toolchain's semihosting library, so the weak stub stands in for it.
SEMIHOST_STUB="sample_threadx/semihost_stub.S"
+ # Deliberately empty. picolibc's __libc_init_array does not call _init,
+ # so these images link today and adding crti.o would change a working
+ # link for no reason.
+ CRT_BEGIN=""
+ CRT_END=""
;;
*)
echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2
@@ -80,7 +102,7 @@ done
"${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \
-T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \
-o sample_threadx.out -Wl,-Map=sample_threadx.map \
- ${objects} tx.a
+ ${CRT_BEGIN} ${objects} tx.a ${CRT_END}
rm -f ${objects}
diff --git a/ports_arch/ARMv8-A/threadx/ports/gnu/example_build/build_threadx_sample.sh b/ports_arch/ARMv8-A/threadx/ports/gnu/example_build/build_threadx_sample.sh
index fa5b92ec..94248a88 100755
--- a/ports_arch/ARMv8-A/threadx/ports/gnu/example_build/build_threadx_sample.sh
+++ b/ports_arch/ARMv8-A/threadx/ports/gnu/example_build/build_threadx_sample.sh
@@ -44,6 +44,23 @@ case "${TOOLCHAIN}" in
# initialise_monitor_handles that startup.S calls.
SYSCALL_LIB="--specs=rdimon.specs"
SEMIHOST_STUB=""
+ # crti.o defines _init and _fini; crtn.o closes them. The link below
+ # passes -nostartfiles, which is right for a port with its own reset
+ # path but also drops these two, and startup.S calls
+ # __libc_init_array, whose newlib implementation calls _init. Without
+ # them every AArch64 sample failed to link:
+ #
+ # libg.a(libc_a-init.o): in function `__libc_init_array':
+ # undefined reference to `_init'
+ # relocation truncated to fit: R_AARCH64_CALL26 against undefined
+ # symbol `_init'
+ #
+ # crti.o must precede every other .init contribution and crtn.o must
+ # follow all of them, which is why they bracket the object list rather
+ # than sitting with the other flags. The AArch32 scripts need none of
+ # this: they use nosys.specs and never reach __libc_init_array.
+ CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)"
+ CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)"
;;
atfe)
CC="${ATFE_CLANG:-clang}"
@@ -52,6 +69,11 @@ case "${TOOLCHAIN}" in
# picolibc has no initialise_monitor_handles, and neither does the
# toolchain's semihosting library, so the weak stub stands in for it.
SEMIHOST_STUB="sample_threadx/semihost_stub.S"
+ # Deliberately empty. picolibc's __libc_init_array does not call _init,
+ # so these images link today and adding crti.o would change a working
+ # link for no reason.
+ CRT_BEGIN=""
+ CRT_END=""
;;
*)
echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2
@@ -80,7 +102,7 @@ done
"${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \
-T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \
-o sample_threadx.out -Wl,-Map=sample_threadx.map \
- ${objects} tx.a
+ ${CRT_BEGIN} ${objects} tx.a ${CRT_END}
rm -f ${objects}
diff --git a/ports_smp/cortex_a34_smp/gnu/example_build/build_threadx_sample.sh b/ports_smp/cortex_a34_smp/gnu/example_build/build_threadx_sample.sh
index fa5b92ec..94248a88 100755
--- a/ports_smp/cortex_a34_smp/gnu/example_build/build_threadx_sample.sh
+++ b/ports_smp/cortex_a34_smp/gnu/example_build/build_threadx_sample.sh
@@ -44,6 +44,23 @@ case "${TOOLCHAIN}" in
# initialise_monitor_handles that startup.S calls.
SYSCALL_LIB="--specs=rdimon.specs"
SEMIHOST_STUB=""
+ # crti.o defines _init and _fini; crtn.o closes them. The link below
+ # passes -nostartfiles, which is right for a port with its own reset
+ # path but also drops these two, and startup.S calls
+ # __libc_init_array, whose newlib implementation calls _init. Without
+ # them every AArch64 sample failed to link:
+ #
+ # libg.a(libc_a-init.o): in function `__libc_init_array':
+ # undefined reference to `_init'
+ # relocation truncated to fit: R_AARCH64_CALL26 against undefined
+ # symbol `_init'
+ #
+ # crti.o must precede every other .init contribution and crtn.o must
+ # follow all of them, which is why they bracket the object list rather
+ # than sitting with the other flags. The AArch32 scripts need none of
+ # this: they use nosys.specs and never reach __libc_init_array.
+ CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)"
+ CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)"
;;
atfe)
CC="${ATFE_CLANG:-clang}"
@@ -52,6 +69,11 @@ case "${TOOLCHAIN}" in
# picolibc has no initialise_monitor_handles, and neither does the
# toolchain's semihosting library, so the weak stub stands in for it.
SEMIHOST_STUB="sample_threadx/semihost_stub.S"
+ # Deliberately empty. picolibc's __libc_init_array does not call _init,
+ # so these images link today and adding crti.o would change a working
+ # link for no reason.
+ CRT_BEGIN=""
+ CRT_END=""
;;
*)
echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2
@@ -80,7 +102,7 @@ done
"${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \
-T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \
-o sample_threadx.out -Wl,-Map=sample_threadx.map \
- ${objects} tx.a
+ ${CRT_BEGIN} ${objects} tx.a ${CRT_END}
rm -f ${objects}
diff --git a/ports_smp/cortex_a35_smp/gnu/example_build/build_threadx_sample.sh b/ports_smp/cortex_a35_smp/gnu/example_build/build_threadx_sample.sh
index fa5b92ec..94248a88 100755
--- a/ports_smp/cortex_a35_smp/gnu/example_build/build_threadx_sample.sh
+++ b/ports_smp/cortex_a35_smp/gnu/example_build/build_threadx_sample.sh
@@ -44,6 +44,23 @@ case "${TOOLCHAIN}" in
# initialise_monitor_handles that startup.S calls.
SYSCALL_LIB="--specs=rdimon.specs"
SEMIHOST_STUB=""
+ # crti.o defines _init and _fini; crtn.o closes them. The link below
+ # passes -nostartfiles, which is right for a port with its own reset
+ # path but also drops these two, and startup.S calls
+ # __libc_init_array, whose newlib implementation calls _init. Without
+ # them every AArch64 sample failed to link:
+ #
+ # libg.a(libc_a-init.o): in function `__libc_init_array':
+ # undefined reference to `_init'
+ # relocation truncated to fit: R_AARCH64_CALL26 against undefined
+ # symbol `_init'
+ #
+ # crti.o must precede every other .init contribution and crtn.o must
+ # follow all of them, which is why they bracket the object list rather
+ # than sitting with the other flags. The AArch32 scripts need none of
+ # this: they use nosys.specs and never reach __libc_init_array.
+ CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)"
+ CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)"
;;
atfe)
CC="${ATFE_CLANG:-clang}"
@@ -52,6 +69,11 @@ case "${TOOLCHAIN}" in
# picolibc has no initialise_monitor_handles, and neither does the
# toolchain's semihosting library, so the weak stub stands in for it.
SEMIHOST_STUB="sample_threadx/semihost_stub.S"
+ # Deliberately empty. picolibc's __libc_init_array does not call _init,
+ # so these images link today and adding crti.o would change a working
+ # link for no reason.
+ CRT_BEGIN=""
+ CRT_END=""
;;
*)
echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2
@@ -80,7 +102,7 @@ done
"${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \
-T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \
-o sample_threadx.out -Wl,-Map=sample_threadx.map \
- ${objects} tx.a
+ ${CRT_BEGIN} ${objects} tx.a ${CRT_END}
rm -f ${objects}
diff --git a/ports_smp/cortex_a53_smp/gnu/example_build/build_threadx_sample.sh b/ports_smp/cortex_a53_smp/gnu/example_build/build_threadx_sample.sh
index fa5b92ec..94248a88 100755
--- a/ports_smp/cortex_a53_smp/gnu/example_build/build_threadx_sample.sh
+++ b/ports_smp/cortex_a53_smp/gnu/example_build/build_threadx_sample.sh
@@ -44,6 +44,23 @@ case "${TOOLCHAIN}" in
# initialise_monitor_handles that startup.S calls.
SYSCALL_LIB="--specs=rdimon.specs"
SEMIHOST_STUB=""
+ # crti.o defines _init and _fini; crtn.o closes them. The link below
+ # passes -nostartfiles, which is right for a port with its own reset
+ # path but also drops these two, and startup.S calls
+ # __libc_init_array, whose newlib implementation calls _init. Without
+ # them every AArch64 sample failed to link:
+ #
+ # libg.a(libc_a-init.o): in function `__libc_init_array':
+ # undefined reference to `_init'
+ # relocation truncated to fit: R_AARCH64_CALL26 against undefined
+ # symbol `_init'
+ #
+ # crti.o must precede every other .init contribution and crtn.o must
+ # follow all of them, which is why they bracket the object list rather
+ # than sitting with the other flags. The AArch32 scripts need none of
+ # this: they use nosys.specs and never reach __libc_init_array.
+ CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)"
+ CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)"
;;
atfe)
CC="${ATFE_CLANG:-clang}"
@@ -52,6 +69,11 @@ case "${TOOLCHAIN}" in
# picolibc has no initialise_monitor_handles, and neither does the
# toolchain's semihosting library, so the weak stub stands in for it.
SEMIHOST_STUB="sample_threadx/semihost_stub.S"
+ # Deliberately empty. picolibc's __libc_init_array does not call _init,
+ # so these images link today and adding crti.o would change a working
+ # link for no reason.
+ CRT_BEGIN=""
+ CRT_END=""
;;
*)
echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2
@@ -80,7 +102,7 @@ done
"${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \
-T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \
-o sample_threadx.out -Wl,-Map=sample_threadx.map \
- ${objects} tx.a
+ ${CRT_BEGIN} ${objects} tx.a ${CRT_END}
rm -f ${objects}
diff --git a/ports_smp/cortex_a55_smp/gnu/example_build/build_threadx_sample.sh b/ports_smp/cortex_a55_smp/gnu/example_build/build_threadx_sample.sh
index fa5b92ec..94248a88 100755
--- a/ports_smp/cortex_a55_smp/gnu/example_build/build_threadx_sample.sh
+++ b/ports_smp/cortex_a55_smp/gnu/example_build/build_threadx_sample.sh
@@ -44,6 +44,23 @@ case "${TOOLCHAIN}" in
# initialise_monitor_handles that startup.S calls.
SYSCALL_LIB="--specs=rdimon.specs"
SEMIHOST_STUB=""
+ # crti.o defines _init and _fini; crtn.o closes them. The link below
+ # passes -nostartfiles, which is right for a port with its own reset
+ # path but also drops these two, and startup.S calls
+ # __libc_init_array, whose newlib implementation calls _init. Without
+ # them every AArch64 sample failed to link:
+ #
+ # libg.a(libc_a-init.o): in function `__libc_init_array':
+ # undefined reference to `_init'
+ # relocation truncated to fit: R_AARCH64_CALL26 against undefined
+ # symbol `_init'
+ #
+ # crti.o must precede every other .init contribution and crtn.o must
+ # follow all of them, which is why they bracket the object list rather
+ # than sitting with the other flags. The AArch32 scripts need none of
+ # this: they use nosys.specs and never reach __libc_init_array.
+ CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)"
+ CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)"
;;
atfe)
CC="${ATFE_CLANG:-clang}"
@@ -52,6 +69,11 @@ case "${TOOLCHAIN}" in
# picolibc has no initialise_monitor_handles, and neither does the
# toolchain's semihosting library, so the weak stub stands in for it.
SEMIHOST_STUB="sample_threadx/semihost_stub.S"
+ # Deliberately empty. picolibc's __libc_init_array does not call _init,
+ # so these images link today and adding crti.o would change a working
+ # link for no reason.
+ CRT_BEGIN=""
+ CRT_END=""
;;
*)
echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2
@@ -80,7 +102,7 @@ done
"${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \
-T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \
-o sample_threadx.out -Wl,-Map=sample_threadx.map \
- ${objects} tx.a
+ ${CRT_BEGIN} ${objects} tx.a ${CRT_END}
rm -f ${objects}
diff --git a/ports_smp/cortex_a57_smp/gnu/example_build/build_threadx_sample.sh b/ports_smp/cortex_a57_smp/gnu/example_build/build_threadx_sample.sh
index fa5b92ec..94248a88 100755
--- a/ports_smp/cortex_a57_smp/gnu/example_build/build_threadx_sample.sh
+++ b/ports_smp/cortex_a57_smp/gnu/example_build/build_threadx_sample.sh
@@ -44,6 +44,23 @@ case "${TOOLCHAIN}" in
# initialise_monitor_handles that startup.S calls.
SYSCALL_LIB="--specs=rdimon.specs"
SEMIHOST_STUB=""
+ # crti.o defines _init and _fini; crtn.o closes them. The link below
+ # passes -nostartfiles, which is right for a port with its own reset
+ # path but also drops these two, and startup.S calls
+ # __libc_init_array, whose newlib implementation calls _init. Without
+ # them every AArch64 sample failed to link:
+ #
+ # libg.a(libc_a-init.o): in function `__libc_init_array':
+ # undefined reference to `_init'
+ # relocation truncated to fit: R_AARCH64_CALL26 against undefined
+ # symbol `_init'
+ #
+ # crti.o must precede every other .init contribution and crtn.o must
+ # follow all of them, which is why they bracket the object list rather
+ # than sitting with the other flags. The AArch32 scripts need none of
+ # this: they use nosys.specs and never reach __libc_init_array.
+ CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)"
+ CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)"
;;
atfe)
CC="${ATFE_CLANG:-clang}"
@@ -52,6 +69,11 @@ case "${TOOLCHAIN}" in
# picolibc has no initialise_monitor_handles, and neither does the
# toolchain's semihosting library, so the weak stub stands in for it.
SEMIHOST_STUB="sample_threadx/semihost_stub.S"
+ # Deliberately empty. picolibc's __libc_init_array does not call _init,
+ # so these images link today and adding crti.o would change a working
+ # link for no reason.
+ CRT_BEGIN=""
+ CRT_END=""
;;
*)
echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2
@@ -80,7 +102,7 @@ done
"${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \
-T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \
-o sample_threadx.out -Wl,-Map=sample_threadx.map \
- ${objects} tx.a
+ ${CRT_BEGIN} ${objects} tx.a ${CRT_END}
rm -f ${objects}
diff --git a/ports_smp/cortex_a65_smp/gnu/example_build/build_threadx_sample.sh b/ports_smp/cortex_a65_smp/gnu/example_build/build_threadx_sample.sh
index fa5b92ec..94248a88 100755
--- a/ports_smp/cortex_a65_smp/gnu/example_build/build_threadx_sample.sh
+++ b/ports_smp/cortex_a65_smp/gnu/example_build/build_threadx_sample.sh
@@ -44,6 +44,23 @@ case "${TOOLCHAIN}" in
# initialise_monitor_handles that startup.S calls.
SYSCALL_LIB="--specs=rdimon.specs"
SEMIHOST_STUB=""
+ # crti.o defines _init and _fini; crtn.o closes them. The link below
+ # passes -nostartfiles, which is right for a port with its own reset
+ # path but also drops these two, and startup.S calls
+ # __libc_init_array, whose newlib implementation calls _init. Without
+ # them every AArch64 sample failed to link:
+ #
+ # libg.a(libc_a-init.o): in function `__libc_init_array':
+ # undefined reference to `_init'
+ # relocation truncated to fit: R_AARCH64_CALL26 against undefined
+ # symbol `_init'
+ #
+ # crti.o must precede every other .init contribution and crtn.o must
+ # follow all of them, which is why they bracket the object list rather
+ # than sitting with the other flags. The AArch32 scripts need none of
+ # this: they use nosys.specs and never reach __libc_init_array.
+ CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)"
+ CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)"
;;
atfe)
CC="${ATFE_CLANG:-clang}"
@@ -52,6 +69,11 @@ case "${TOOLCHAIN}" in
# picolibc has no initialise_monitor_handles, and neither does the
# toolchain's semihosting library, so the weak stub stands in for it.
SEMIHOST_STUB="sample_threadx/semihost_stub.S"
+ # Deliberately empty. picolibc's __libc_init_array does not call _init,
+ # so these images link today and adding crti.o would change a working
+ # link for no reason.
+ CRT_BEGIN=""
+ CRT_END=""
;;
*)
echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2
@@ -80,7 +102,7 @@ done
"${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \
-T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \
-o sample_threadx.out -Wl,-Map=sample_threadx.map \
- ${objects} tx.a
+ ${CRT_BEGIN} ${objects} tx.a ${CRT_END}
rm -f ${objects}
diff --git a/ports_smp/cortex_a65ae_smp/gnu/example_build/build_threadx_sample.sh b/ports_smp/cortex_a65ae_smp/gnu/example_build/build_threadx_sample.sh
index fa5b92ec..94248a88 100755
--- a/ports_smp/cortex_a65ae_smp/gnu/example_build/build_threadx_sample.sh
+++ b/ports_smp/cortex_a65ae_smp/gnu/example_build/build_threadx_sample.sh
@@ -44,6 +44,23 @@ case "${TOOLCHAIN}" in
# initialise_monitor_handles that startup.S calls.
SYSCALL_LIB="--specs=rdimon.specs"
SEMIHOST_STUB=""
+ # crti.o defines _init and _fini; crtn.o closes them. The link below
+ # passes -nostartfiles, which is right for a port with its own reset
+ # path but also drops these two, and startup.S calls
+ # __libc_init_array, whose newlib implementation calls _init. Without
+ # them every AArch64 sample failed to link:
+ #
+ # libg.a(libc_a-init.o): in function `__libc_init_array':
+ # undefined reference to `_init'
+ # relocation truncated to fit: R_AARCH64_CALL26 against undefined
+ # symbol `_init'
+ #
+ # crti.o must precede every other .init contribution and crtn.o must
+ # follow all of them, which is why they bracket the object list rather
+ # than sitting with the other flags. The AArch32 scripts need none of
+ # this: they use nosys.specs and never reach __libc_init_array.
+ CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)"
+ CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)"
;;
atfe)
CC="${ATFE_CLANG:-clang}"
@@ -52,6 +69,11 @@ case "${TOOLCHAIN}" in
# picolibc has no initialise_monitor_handles, and neither does the
# toolchain's semihosting library, so the weak stub stands in for it.
SEMIHOST_STUB="sample_threadx/semihost_stub.S"
+ # Deliberately empty. picolibc's __libc_init_array does not call _init,
+ # so these images link today and adding crti.o would change a working
+ # link for no reason.
+ CRT_BEGIN=""
+ CRT_END=""
;;
*)
echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2
@@ -80,7 +102,7 @@ done
"${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \
-T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \
-o sample_threadx.out -Wl,-Map=sample_threadx.map \
- ${objects} tx.a
+ ${CRT_BEGIN} ${objects} tx.a ${CRT_END}
rm -f ${objects}
diff --git a/ports_smp/cortex_a72_smp/gnu/example_build/build_threadx_sample.sh b/ports_smp/cortex_a72_smp/gnu/example_build/build_threadx_sample.sh
index fa5b92ec..94248a88 100755
--- a/ports_smp/cortex_a72_smp/gnu/example_build/build_threadx_sample.sh
+++ b/ports_smp/cortex_a72_smp/gnu/example_build/build_threadx_sample.sh
@@ -44,6 +44,23 @@ case "${TOOLCHAIN}" in
# initialise_monitor_handles that startup.S calls.
SYSCALL_LIB="--specs=rdimon.specs"
SEMIHOST_STUB=""
+ # crti.o defines _init and _fini; crtn.o closes them. The link below
+ # passes -nostartfiles, which is right for a port with its own reset
+ # path but also drops these two, and startup.S calls
+ # __libc_init_array, whose newlib implementation calls _init. Without
+ # them every AArch64 sample failed to link:
+ #
+ # libg.a(libc_a-init.o): in function `__libc_init_array':
+ # undefined reference to `_init'
+ # relocation truncated to fit: R_AARCH64_CALL26 against undefined
+ # symbol `_init'
+ #
+ # crti.o must precede every other .init contribution and crtn.o must
+ # follow all of them, which is why they bracket the object list rather
+ # than sitting with the other flags. The AArch32 scripts need none of
+ # this: they use nosys.specs and never reach __libc_init_array.
+ CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)"
+ CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)"
;;
atfe)
CC="${ATFE_CLANG:-clang}"
@@ -52,6 +69,11 @@ case "${TOOLCHAIN}" in
# picolibc has no initialise_monitor_handles, and neither does the
# toolchain's semihosting library, so the weak stub stands in for it.
SEMIHOST_STUB="sample_threadx/semihost_stub.S"
+ # Deliberately empty. picolibc's __libc_init_array does not call _init,
+ # so these images link today and adding crti.o would change a working
+ # link for no reason.
+ CRT_BEGIN=""
+ CRT_END=""
;;
*)
echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2
@@ -80,7 +102,7 @@ done
"${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \
-T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \
-o sample_threadx.out -Wl,-Map=sample_threadx.map \
- ${objects} tx.a
+ ${CRT_BEGIN} ${objects} tx.a ${CRT_END}
rm -f ${objects}
diff --git a/ports_smp/cortex_a73_smp/gnu/example_build/build_threadx_sample.sh b/ports_smp/cortex_a73_smp/gnu/example_build/build_threadx_sample.sh
index fa5b92ec..94248a88 100755
--- a/ports_smp/cortex_a73_smp/gnu/example_build/build_threadx_sample.sh
+++ b/ports_smp/cortex_a73_smp/gnu/example_build/build_threadx_sample.sh
@@ -44,6 +44,23 @@ case "${TOOLCHAIN}" in
# initialise_monitor_handles that startup.S calls.
SYSCALL_LIB="--specs=rdimon.specs"
SEMIHOST_STUB=""
+ # crti.o defines _init and _fini; crtn.o closes them. The link below
+ # passes -nostartfiles, which is right for a port with its own reset
+ # path but also drops these two, and startup.S calls
+ # __libc_init_array, whose newlib implementation calls _init. Without
+ # them every AArch64 sample failed to link:
+ #
+ # libg.a(libc_a-init.o): in function `__libc_init_array':
+ # undefined reference to `_init'
+ # relocation truncated to fit: R_AARCH64_CALL26 against undefined
+ # symbol `_init'
+ #
+ # crti.o must precede every other .init contribution and crtn.o must
+ # follow all of them, which is why they bracket the object list rather
+ # than sitting with the other flags. The AArch32 scripts need none of
+ # this: they use nosys.specs and never reach __libc_init_array.
+ CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)"
+ CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)"
;;
atfe)
CC="${ATFE_CLANG:-clang}"
@@ -52,6 +69,11 @@ case "${TOOLCHAIN}" in
# picolibc has no initialise_monitor_handles, and neither does the
# toolchain's semihosting library, so the weak stub stands in for it.
SEMIHOST_STUB="sample_threadx/semihost_stub.S"
+ # Deliberately empty. picolibc's __libc_init_array does not call _init,
+ # so these images link today and adding crti.o would change a working
+ # link for no reason.
+ CRT_BEGIN=""
+ CRT_END=""
;;
*)
echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2
@@ -80,7 +102,7 @@ done
"${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \
-T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \
-o sample_threadx.out -Wl,-Map=sample_threadx.map \
- ${objects} tx.a
+ ${CRT_BEGIN} ${objects} tx.a ${CRT_END}
rm -f ${objects}
diff --git a/ports_smp/cortex_a75_smp/gnu/example_build/build_threadx_sample.sh b/ports_smp/cortex_a75_smp/gnu/example_build/build_threadx_sample.sh
index fa5b92ec..94248a88 100755
--- a/ports_smp/cortex_a75_smp/gnu/example_build/build_threadx_sample.sh
+++ b/ports_smp/cortex_a75_smp/gnu/example_build/build_threadx_sample.sh
@@ -44,6 +44,23 @@ case "${TOOLCHAIN}" in
# initialise_monitor_handles that startup.S calls.
SYSCALL_LIB="--specs=rdimon.specs"
SEMIHOST_STUB=""
+ # crti.o defines _init and _fini; crtn.o closes them. The link below
+ # passes -nostartfiles, which is right for a port with its own reset
+ # path but also drops these two, and startup.S calls
+ # __libc_init_array, whose newlib implementation calls _init. Without
+ # them every AArch64 sample failed to link:
+ #
+ # libg.a(libc_a-init.o): in function `__libc_init_array':
+ # undefined reference to `_init'
+ # relocation truncated to fit: R_AARCH64_CALL26 against undefined
+ # symbol `_init'
+ #
+ # crti.o must precede every other .init contribution and crtn.o must
+ # follow all of them, which is why they bracket the object list rather
+ # than sitting with the other flags. The AArch32 scripts need none of
+ # this: they use nosys.specs and never reach __libc_init_array.
+ CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)"
+ CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)"
;;
atfe)
CC="${ATFE_CLANG:-clang}"
@@ -52,6 +69,11 @@ case "${TOOLCHAIN}" in
# picolibc has no initialise_monitor_handles, and neither does the
# toolchain's semihosting library, so the weak stub stands in for it.
SEMIHOST_STUB="sample_threadx/semihost_stub.S"
+ # Deliberately empty. picolibc's __libc_init_array does not call _init,
+ # so these images link today and adding crti.o would change a working
+ # link for no reason.
+ CRT_BEGIN=""
+ CRT_END=""
;;
*)
echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2
@@ -80,7 +102,7 @@ done
"${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \
-T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \
-o sample_threadx.out -Wl,-Map=sample_threadx.map \
- ${objects} tx.a
+ ${CRT_BEGIN} ${objects} tx.a ${CRT_END}
rm -f ${objects}
diff --git a/ports_smp/cortex_a76_smp/gnu/example_build/build_threadx_sample.sh b/ports_smp/cortex_a76_smp/gnu/example_build/build_threadx_sample.sh
index fa5b92ec..94248a88 100755
--- a/ports_smp/cortex_a76_smp/gnu/example_build/build_threadx_sample.sh
+++ b/ports_smp/cortex_a76_smp/gnu/example_build/build_threadx_sample.sh
@@ -44,6 +44,23 @@ case "${TOOLCHAIN}" in
# initialise_monitor_handles that startup.S calls.
SYSCALL_LIB="--specs=rdimon.specs"
SEMIHOST_STUB=""
+ # crti.o defines _init and _fini; crtn.o closes them. The link below
+ # passes -nostartfiles, which is right for a port with its own reset
+ # path but also drops these two, and startup.S calls
+ # __libc_init_array, whose newlib implementation calls _init. Without
+ # them every AArch64 sample failed to link:
+ #
+ # libg.a(libc_a-init.o): in function `__libc_init_array':
+ # undefined reference to `_init'
+ # relocation truncated to fit: R_AARCH64_CALL26 against undefined
+ # symbol `_init'
+ #
+ # crti.o must precede every other .init contribution and crtn.o must
+ # follow all of them, which is why they bracket the object list rather
+ # than sitting with the other flags. The AArch32 scripts need none of
+ # this: they use nosys.specs and never reach __libc_init_array.
+ CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)"
+ CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)"
;;
atfe)
CC="${ATFE_CLANG:-clang}"
@@ -52,6 +69,11 @@ case "${TOOLCHAIN}" in
# picolibc has no initialise_monitor_handles, and neither does the
# toolchain's semihosting library, so the weak stub stands in for it.
SEMIHOST_STUB="sample_threadx/semihost_stub.S"
+ # Deliberately empty. picolibc's __libc_init_array does not call _init,
+ # so these images link today and adding crti.o would change a working
+ # link for no reason.
+ CRT_BEGIN=""
+ CRT_END=""
;;
*)
echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2
@@ -80,7 +102,7 @@ done
"${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \
-T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \
-o sample_threadx.out -Wl,-Map=sample_threadx.map \
- ${objects} tx.a
+ ${CRT_BEGIN} ${objects} tx.a ${CRT_END}
rm -f ${objects}
diff --git a/ports_smp/cortex_a76ae_smp/gnu/example_build/build_threadx_sample.sh b/ports_smp/cortex_a76ae_smp/gnu/example_build/build_threadx_sample.sh
index fa5b92ec..94248a88 100755
--- a/ports_smp/cortex_a76ae_smp/gnu/example_build/build_threadx_sample.sh
+++ b/ports_smp/cortex_a76ae_smp/gnu/example_build/build_threadx_sample.sh
@@ -44,6 +44,23 @@ case "${TOOLCHAIN}" in
# initialise_monitor_handles that startup.S calls.
SYSCALL_LIB="--specs=rdimon.specs"
SEMIHOST_STUB=""
+ # crti.o defines _init and _fini; crtn.o closes them. The link below
+ # passes -nostartfiles, which is right for a port with its own reset
+ # path but also drops these two, and startup.S calls
+ # __libc_init_array, whose newlib implementation calls _init. Without
+ # them every AArch64 sample failed to link:
+ #
+ # libg.a(libc_a-init.o): in function `__libc_init_array':
+ # undefined reference to `_init'
+ # relocation truncated to fit: R_AARCH64_CALL26 against undefined
+ # symbol `_init'
+ #
+ # crti.o must precede every other .init contribution and crtn.o must
+ # follow all of them, which is why they bracket the object list rather
+ # than sitting with the other flags. The AArch32 scripts need none of
+ # this: they use nosys.specs and never reach __libc_init_array.
+ CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)"
+ CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)"
;;
atfe)
CC="${ATFE_CLANG:-clang}"
@@ -52,6 +69,11 @@ case "${TOOLCHAIN}" in
# picolibc has no initialise_monitor_handles, and neither does the
# toolchain's semihosting library, so the weak stub stands in for it.
SEMIHOST_STUB="sample_threadx/semihost_stub.S"
+ # Deliberately empty. picolibc's __libc_init_array does not call _init,
+ # so these images link today and adding crti.o would change a working
+ # link for no reason.
+ CRT_BEGIN=""
+ CRT_END=""
;;
*)
echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2
@@ -80,7 +102,7 @@ done
"${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \
-T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \
-o sample_threadx.out -Wl,-Map=sample_threadx.map \
- ${objects} tx.a
+ ${CRT_BEGIN} ${objects} tx.a ${CRT_END}
rm -f ${objects}
diff --git a/ports_smp/cortex_a77_smp/gnu/example_build/build_threadx_sample.sh b/ports_smp/cortex_a77_smp/gnu/example_build/build_threadx_sample.sh
index fa5b92ec..94248a88 100755
--- a/ports_smp/cortex_a77_smp/gnu/example_build/build_threadx_sample.sh
+++ b/ports_smp/cortex_a77_smp/gnu/example_build/build_threadx_sample.sh
@@ -44,6 +44,23 @@ case "${TOOLCHAIN}" in
# initialise_monitor_handles that startup.S calls.
SYSCALL_LIB="--specs=rdimon.specs"
SEMIHOST_STUB=""
+ # crti.o defines _init and _fini; crtn.o closes them. The link below
+ # passes -nostartfiles, which is right for a port with its own reset
+ # path but also drops these two, and startup.S calls
+ # __libc_init_array, whose newlib implementation calls _init. Without
+ # them every AArch64 sample failed to link:
+ #
+ # libg.a(libc_a-init.o): in function `__libc_init_array':
+ # undefined reference to `_init'
+ # relocation truncated to fit: R_AARCH64_CALL26 against undefined
+ # symbol `_init'
+ #
+ # crti.o must precede every other .init contribution and crtn.o must
+ # follow all of them, which is why they bracket the object list rather
+ # than sitting with the other flags. The AArch32 scripts need none of
+ # this: they use nosys.specs and never reach __libc_init_array.
+ CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)"
+ CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)"
;;
atfe)
CC="${ATFE_CLANG:-clang}"
@@ -52,6 +69,11 @@ case "${TOOLCHAIN}" in
# picolibc has no initialise_monitor_handles, and neither does the
# toolchain's semihosting library, so the weak stub stands in for it.
SEMIHOST_STUB="sample_threadx/semihost_stub.S"
+ # Deliberately empty. picolibc's __libc_init_array does not call _init,
+ # so these images link today and adding crti.o would change a working
+ # link for no reason.
+ CRT_BEGIN=""
+ CRT_END=""
;;
*)
echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2
@@ -80,7 +102,7 @@ done
"${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \
-T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \
-o sample_threadx.out -Wl,-Map=sample_threadx.map \
- ${objects} tx.a
+ ${CRT_BEGIN} ${objects} tx.a ${CRT_END}
rm -f ${objects}
diff --git a/ports_smp/cortex_a78_smp/gnu/example_build/build_threadx_sample.sh b/ports_smp/cortex_a78_smp/gnu/example_build/build_threadx_sample.sh
index fa5b92ec..94248a88 100755
--- a/ports_smp/cortex_a78_smp/gnu/example_build/build_threadx_sample.sh
+++ b/ports_smp/cortex_a78_smp/gnu/example_build/build_threadx_sample.sh
@@ -44,6 +44,23 @@ case "${TOOLCHAIN}" in
# initialise_monitor_handles that startup.S calls.
SYSCALL_LIB="--specs=rdimon.specs"
SEMIHOST_STUB=""
+ # crti.o defines _init and _fini; crtn.o closes them. The link below
+ # passes -nostartfiles, which is right for a port with its own reset
+ # path but also drops these two, and startup.S calls
+ # __libc_init_array, whose newlib implementation calls _init. Without
+ # them every AArch64 sample failed to link:
+ #
+ # libg.a(libc_a-init.o): in function `__libc_init_array':
+ # undefined reference to `_init'
+ # relocation truncated to fit: R_AARCH64_CALL26 against undefined
+ # symbol `_init'
+ #
+ # crti.o must precede every other .init contribution and crtn.o must
+ # follow all of them, which is why they bracket the object list rather
+ # than sitting with the other flags. The AArch32 scripts need none of
+ # this: they use nosys.specs and never reach __libc_init_array.
+ CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)"
+ CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)"
;;
atfe)
CC="${ATFE_CLANG:-clang}"
@@ -52,6 +69,11 @@ case "${TOOLCHAIN}" in
# picolibc has no initialise_monitor_handles, and neither does the
# toolchain's semihosting library, so the weak stub stands in for it.
SEMIHOST_STUB="sample_threadx/semihost_stub.S"
+ # Deliberately empty. picolibc's __libc_init_array does not call _init,
+ # so these images link today and adding crti.o would change a working
+ # link for no reason.
+ CRT_BEGIN=""
+ CRT_END=""
;;
*)
echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2
@@ -80,7 +102,7 @@ done
"${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \
-T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \
-o sample_threadx.out -Wl,-Map=sample_threadx.map \
- ${objects} tx.a
+ ${CRT_BEGIN} ${objects} tx.a ${CRT_END}
rm -f ${objects}