Skip to content
Merged
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
10 changes: 10 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -112,3 +112,13 @@ else()

set(CTSHELL_DEFINITIONS ${CTSHELL_DEFINITIONS} CACHE INTERNAL "ctshell definitions")
endif()

# --- Linker options for section-based command registration ---
# GCC (ld.bfd) handles __start_/__stop_ symbols for orphan sections automatically.
# LLVM lld requires -z nostart-stop-gc to prevent these symbols from being
# discarded when --gc-sections is enabled.
set(CTSHELL_LINK_OPTIONS "")
if(CMAKE_LINKER MATCHES "lld" OR CMAKE_C_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
list(APPEND CTSHELL_LINK_OPTIONS "-z" "nostart-stop-gc")
Comment on lines +121 to +122
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

cache_file="$(fd -HI '^CMakeCache.txt$' | head -n1 || true)"
if [[ -z "${cache_file}" ]]; then
  echo "No CMakeCache.txt found. Run CMake configure first."
  exit 1
fi

linker="$(rg -n '^CMAKE_LINKER:FILEPATH=' "$cache_file" | sed 's/^[^=]*=//' | head -n1)"
echo "Resolved linker: $linker"

if [[ ! -x "$linker" ]]; then
  echo "Linker binary is not executable: $linker"
  exit 1
fi

"$linker" --help 2>&1 | rg -n 'nostart-stop-gc|start-stop-gc'

Repository: MDLZCOOL/ctshell

Length of output: 111


🏁 Script executed:

cat -n CMakeLists.txt | sed -n '110,135p'

Repository: MDLZCOOL/ctshell

Length of output: 857


🏁 Script executed:

rg -n "CMAKE_LINKER|CMAKE_C_COMPILER_ID|CMAKE_CXX_COMPILER_ID|lld|nostart-stop-gc" CMakeLists.txt

Repository: MDLZCOOL/ctshell

Length of output: 371


Narrow linker detection to prevent passing -z nostart-stop-gc to unsupported linkers.

The condition on line 121 uses OR with Clang compiler checks, which means the flag is appended whenever Clang is used as the compiler, regardless of the actual linker. This causes -z nostart-stop-gc (an ELF-specific flag for LLVM lld) to be passed to incompatible linkers like Apple's ld64 or GNU ld, resulting in link failures.

The fix should check only if CMAKE_LINKER actually resolves to the ld.lld binary:

🔧 Proposed fix
 set(CTSHELL_LINK_OPTIONS "")
-if(CMAKE_LINKER MATCHES "lld" OR CMAKE_C_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
+if(CMAKE_LINKER MATCHES [[(^|.*/)ld\.lld(\.exe)?$]])
     list(APPEND CTSHELL_LINK_OPTIONS "-z" "nostart-stop-gc")
 endif()
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if(CMAKE_LINKER MATCHES "lld" OR CMAKE_C_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
list(APPEND CTSHELL_LINK_OPTIONS "-z" "nostart-stop-gc")
if(CMAKE_LINKER MATCHES [[(^|.*/)ld\.lld(\.exe)?$]])
list(APPEND CTSHELL_LINK_OPTIONS "-z" "nostart-stop-gc")
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@CMakeLists.txt` around lines 121 - 122, The current conditional uses compiler
IDs and causes the ELF-only flag "-z nostart-stop-gc" to be appended whenever
Clang is used; change the check to detect the actual linker binary
(CMAKE_LINKER) and only append to CTSHELL_LINK_OPTIONS when CMAKE_LINKER
resolves to the LLVM lld binary (e.g., matches "ld.lld" or ends with "ld.lld");
update the if(...) that references CMAKE_LINKER so it no longer tests
CMAKE_C_COMPILER_ID or CMAKE_CXX_COMPILER_ID but instead tests CMAKE_LINKER
MATCHES ".*ld.lld$" (or equivalent exact-path check) before appending "-z"
"nostart-stop-gc" to CTSHELL_LINK_OPTIONS.

endif()
set(CTSHELL_LINK_OPTIONS ${CTSHELL_LINK_OPTIONS} CACHE INTERNAL "ctshell linker options")
12 changes: 10 additions & 2 deletions docs/en/quickstart/porting.rst
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,17 @@ RTOS Environment: It is recommended to create a dedicated task to run the Shell.

6. Linker Script Modification

gcc: No need to modify.
**GCC (ld.bfd):** No need to modify the linker script.

MDK-ARM(v5 and v6): Add in scatter file, example:
**LLVM/Clang (ld.lld):** If you are using an LLVM-based toolchain (e.g., ST's STM32CubeCLT with arm-clang), the linker script does not need modification either. Simply append the following to the end of your ``CMakeLists.txt``:

.. code-block:: cmake

target_link_options(${CMAKE_PROJECT_NAME} PRIVATE ${CTSHELL_LINK_OPTIONS})

``${CTSHELL_LINK_OPTIONS}`` is exported by ctshell and automatically adds ``-z nostart-stop-gc`` when an LLVM linker is detected, preventing ``__start_ctshell_cmd_section`` and ``__stop_ctshell_cmd_section`` symbols from being discarded under ``--gc-sections``.

**MDK-ARM (v5 and v6):** Add in scatter file, example:

.. code-block:: c

Expand Down
12 changes: 10 additions & 2 deletions docs/zh/quickstart/porting.rst
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,17 @@ RTOS 环境: 建议创建一个独立的任务来运行 Shell。

6. 链接脚本修改

gcc:无需修改
**GCC (ld.bfd):** 无需修改链接脚本

MDK-ARM(v5 and v6):在scatter file中添加示例如下:
**LLVM/Clang (ld.lld):** 如果你使用的是基于 LLVM 的工具链(如 ST 的 STM32CubeCLT arm-clang),则无需修改链接脚本,只需将以下内容追加到你的 ``CMakeLists.txt`` 末尾即可:

.. code-block:: cmake

target_link_options(${CMAKE_PROJECT_NAME} PRIVATE ${CTSHELL_LINK_OPTIONS})

``${CTSHELL_LINK_OPTIONS}`` 由 ctshell 导出,会在检测到 LLVM 链接器时自动添加 ``-z nostart-stop-gc``,防止 ``__start_ctshell_cmd_section`` 和 ``__stop_ctshell_cmd_section`` 符号在 ``--gc-sections`` 下被回收。

**MDK-ARM(v5 and v6):** 在scatter file中添加示例如下:

.. code-block:: c

Expand Down
Loading