Skip to content

Commit

Permalink
Fix issue with -Os compilation
Browse files Browse the repository at this point in the history
You get the following problem when using `-Os`:

          = note: rust-lld: error: undefined symbol: __gnu_thumb1_case_uhi
                  >>> referenced by DAP.c:1653 (CMSIS_5/CMSIS/DAP/Firmware/Source/DAP.c:1653)
                  >>>               DAP.o:(DAP_ProcessCommand) in archive /tmp/rustctmyFes/librp2040_selfdebug-254aa1d1b314f83f
        .rlib

                  rust-lld: error: undefined symbol: __gnu_thumb1_case_uqi
                  >>> referenced by DAP.c:90 (CMSIS_5/CMSIS/DAP/Firmware/Source/DAP.c:90)
                  >>>               DAP.o:(DAP_ProcessCommand) in archive /tmp/rustctmyFes/librp2040_selfdebug-254aa1d1b314f83f
        .rlib

                  rust-lld: error: undefined symbol: strcpy
                  >>> referenced by DAP_config.h:201 (CMSIS_Config/DAP_config.h:201)
                  >>>               DAP.o:(DAP_ProcessCommand) in archive /tmp/rustctmyFes/librp2040_selfdebug-254aa1d1b314f83f
        .rlib
                  >>> referenced by DAP_config.h:218 (CMSIS_Config/DAP_config.h:218)
                  >>>               DAP.o:(DAP_ProcessCommand) in archive /tmp/rustctmyFes/librp2040_selfdebug-254aa1d1b314f83f
        .rlib
                  >>> referenced by DAP_config.h:235 (CMSIS_Config/DAP_config.h:235)
                  >>>               DAP.o:(DAP_ProcessCommand) in archive /tmp/rustctmyFes/librp2040_selfdebug-254aa1d1b314f83f
        .rlib
                  >>> referenced 1 more times

- This fixes the issue of `strcpy` by just using `memcpy`
- This fixes the issue of __gnu_thumb1_case_uhi/__gnu_thumb1_case_uqi
  which are defined in `libgcc.a` by adding the libgcc path to the
  linker search path, you might optionally need to add

          "-C", "link-args=-lgcc"

  to your .cargo/config.toml

  - We are not using `cargo:rustc-link-lib=static:+verbatim={}`
    as that had problems with libgcc being doubly-linked so there being
    duplicate symbols.
  • Loading branch information
KoviRobi committed Dec 26, 2023
1 parent 34959d9 commit af78547
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 15 deletions.
16 changes: 8 additions & 8 deletions CMSIS_Config/DAP_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -198,8 +198,8 @@ __STATIC_INLINE uint8_t DAP_GetTargetDeviceVendorString (char *str) {
#if TARGET_FIXED != 0
uint8_t len;

strcpy(str, TargetDeviceVendor);
len = (uint8_t)(strlen(TargetDeviceVendor) + 1U);
len = (uint8_t)sizeof(TargetDeviceVendor);
memcpy(str, TargetDeviceVendor, len);
return (len);
#else
(void)str;
Expand All @@ -215,8 +215,8 @@ __STATIC_INLINE uint8_t DAP_GetTargetDeviceNameString (char *str) {
#if TARGET_FIXED != 0
uint8_t len;

strcpy(str, TargetDeviceName);
len = (uint8_t)(strlen(TargetDeviceName) + 1U);
len = (uint8_t)sizeof(TargetDeviceName);
memcpy(str, TargetDeviceName, len);
return (len);
#else
(void)str;
Expand All @@ -232,8 +232,8 @@ __STATIC_INLINE uint8_t DAP_GetTargetBoardVendorString (char *str) {
#if TARGET_FIXED != 0
uint8_t len;

strcpy(str, TargetBoardVendor);
len = (uint8_t)(strlen(TargetBoardVendor) + 1U);
len = (uint8_t)sizeof(TargetBoardVendor);
memcpy(str, TargetBoardVendor, len);
return (len);
#else
(void)str;
Expand All @@ -249,8 +249,8 @@ __STATIC_INLINE uint8_t DAP_GetTargetBoardNameString (char *str) {
#if TARGET_FIXED != 0
uint8_t len;

strcpy(str, TargetBoardName);
len = (uint8_t)(strlen(TargetBoardName) + 1U);
len = (uint8_t)sizeof(TargetBoardName);
memcpy(str, TargetBoardName, len);
return (len);
#else
(void)str;
Expand Down
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,32 @@ If you want to configure something else (see the file
[CMSIS_Config/DAP_config.h](CMSIS_Config/DAP_config.h) for more configuration
options), feel free to make a PR, or just use this repository as an example.

## Known problems
### `rust-lld: error: undefined symbol: __gnu_thumb1_case_uhi`
The issue here is that with the `-Os` optimisation GCC is using a "compact
switch" which requires helper functions/tables
(https://chromium.googlesource.com/chromiumos/platform/ec/+/refs/heads/master/core/cortex-m0/thumb_case.S),
but `libgcc.a` isn't getting linked. To combat this, the `libgcc.a` directory
is added to the linker search paths (see [build.rs](build.rs)) but you have to
add `-lgcc` to your linker, e.g. put the following into `.cargo/config.toml`

```diff
@@ -1,11 +1,12 @@
[target.'cfg(all(target_arch = "arm", target_os = "none"))']
# runner = "elf2uf2-rs -d"
runner = "probe-rs run --chip RP2040 --probe 2E8A:000C"

rustflags = [
"-C", "link-arg=-Tlink.x",
"-C", "link-arg=-Tdefmt.x",
+ "-C", "link-args=-lgcc"
]

[build]
target = "thumbv6m-none-eabi"
```


## TODOs
- Test flashing core-1 apps. This might require compiling two separate
binaries, the CMSIS-DAP one first, and then the core 1 application, linked
Expand Down
29 changes: 22 additions & 7 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use std::env;
use std::fs::File;
use std::io::Write;
use std::path::PathBuf;
use std::process::Command;

fn main() {
// Put `memory.x` in our output directory and ensure it's
Expand All @@ -36,9 +37,9 @@ fn main() {
// -- This value is used to calculate the SWD/JTAG clock speed.
// -- (Specifies the CPU Clock in Hz.)
let cpu_clock = match env::var("CARGO_CFG_CMSIS_DAP_CPU_CLOCK") {
Ok(s) => s
.parse()
.expect("Rustc cfg CMSIS_DAP_CPU_CLOCK cannot be parsed as a u32 integer"),
Ok(s) => s.parse().expect(
"Rustc cfg CMSIS_DAP_CPU_CLOCK cannot be parsed as a u32 integer",
),
Err(env::VarError::NotPresent) => 120_000_000u32,
Err(env::VarError::NotUnicode(os_str)) => {
panic!("Rustc cfg CMSIS_DAP_CPU_CLOCK not unicode: {:?}", os_str)
Expand Down Expand Up @@ -95,7 +96,8 @@ fn main() {
}

// - Building the CMSIS DAP library
cc::Build::new()
let mut cmsis_dap_build = cc::Build::new();
cmsis_dap_build
.compiler("arm-none-eabi-gcc")
.file("CMSIS_5/CMSIS/DAP/Firmware/Source/DAP.c")
.file("CMSIS_5/CMSIS/DAP/Firmware/Source/SW_DP.c")
Expand All @@ -105,8 +107,21 @@ fn main() {
dap_default_swj_clock.to_string().as_ref(),
)
.define("DAP_PACKET_COUNT", dap_packet_count.to_string().as_ref())
.includes(includes)
.compile("cmsis_dap");
.includes(includes);
cmsis_dap_build.compile("cmsis_dap");

println!("cargo:rustc-link-lib=cmsis_dap");
if cmsis_dap_build.get_compiler().is_like_gnu() {
let libgcc_file_name_out =
Command::new(cmsis_dap_build.get_compiler().path())
.args(["-print-libgcc-file-name"])
.output()
.unwrap();
let libgcc_file_name =
String::from_utf8(libgcc_file_name_out.stdout).unwrap();
let path = PathBuf::from(&libgcc_file_name);
println!(
"cargo:rustc-link-search={}",
path.parent().unwrap().to_str().unwrap()
)
}
}

0 comments on commit af78547

Please sign in to comment.