Sysprogs forums › Forums › VisualGDB › Multi Project Linker Silent Failure
Tagged: stm32 linker
- This topic has 11 replies, 2 voices, and was last updated 4 years, 9 months ago by codex653.
-
AuthorPosts
-
January 22, 2020 at 04:51 #27188codex653Participant
Hello! I have been recently revamping my personal tooling workflow to allow compiling various VisualGDB solutions into static libraries, then linking them all together in a large project to produce a flashable binary for an STM32F4 device. I have commonly used subsystems that I was tired of regenerating the build tooling for on each new project, so I wanted standalone solutions I could include in larger VisualGDB projects as a component.
I’ve been following the examples shown in https://visualgdb.com/tutorials/porting/multiplatform/ to help create a platform in Visual Studio for my chip. I’ve got everything compiling and linking successfully, but when I start debugging, I find that the chip has jumped off into the weeds and gotten completely lost. I have a feeling that somehow the isr vector table got messed up in the linking process and is not placed at the correct location in the binary. I cannot hit the breakpoint inside of the Reset_Handler function. Each sub component project is using the same linker script that comes default with my chip in VisualGDB (STM32F446RE_flash.lds).
Any thoughts on what I might be doing wrong here? Disassembly output did not show the expected isr jump table at the reset address (0x08000000), but rather a function that I did not recognize. My understanding of the STM32F4 resets is likely flawed though.
Edit: I should mention I am compiling 3 sub-projects as static libraries and linking them into one larger project.
- This topic was modified 4 years, 9 months ago by codex653.
January 22, 2020 at 05:14 #27190supportKeymasterHi,
It looks like your support period has expired. Please renew it here and will be happy to help you.
January 22, 2020 at 15:41 #27191codex653ParticipantWhoops! I didn’t realize it had expired. I’ve purchased the support renewal as of a few moments ago.
January 22, 2020 at 16:10 #27192supportKeymasterThanks for renewing your support.
If the firmware doesn’t start completely, we would advise checking the following points:
- Using Embedded Memory Explorer, check that the interrupt vector is present at the correct address (double-check the address in the device datasheet, or compare it with a working file).
- Double-check that the interrupt vector points to the correct Reset handler function. You can dump the contents of the section containing the interrupt vector by running arm-none-eabi-objdump or do it at runtime by evaluating *((void *)0xADDRESS) via the Watch window.
- You can configure VisualGDB to stop at the Reset handler via VisualGDB Project Properties – >Embedded Debug Tweaking and then starting debugging with F10 instead of F5.
- If nothing helps, you can also try hardcoding a breakpoint in the reset handler (asm(“bkpt 255”)) and issuing a manual reset via the GDB Session window (mon reset).
January 22, 2020 at 20:21 #27197codex653ParticipantI was able to verify that the isr vector table is located at the correct address with both #1 & #2, but I noticed that the .text section was also located at the same address (0x08000000). As a test, I compiled the HAL blinky example project from the project wizard and objdump-ing the output showed me that the .text and .isr_vector symbols are located at two different addresses. Further inspection of the blinky binary shows the expected Reset_Handler address in the second word of the image and the stack address in the first word, as expected…my project shows essentially garbage data.
I’ve attached an image of the objdump output for an example. This seems to be leading me down the right path…
- This reply was modified 4 years, 9 months ago by codex653.
Attachments:
You must be logged in to view attached files.January 23, 2020 at 00:07 #27204codex653ParticipantI ended up solving the problem. My chip’s startup code is compiled into one of the static libraries that is linked into the larger project. Despite verifying that the vector table IS in there and was compiled with the “__attribute__( ( section( “.isr_vector” ), used ) )” GCC annotation to prevent removal, it’s still being thrown out during linking. In order to fix this, I had to include the startup file in the larger project, which goes against my goal of modularizing the code base.
Is there a way for me to inject
--whole-archive
/--no-whole-archive
into the linker step? I’d rather not have to explicitly reference the interrupt vector in the main project in order to keep that part of the code from the static library.For reference, I’ve been looking at this tutorial: https://visualgdb.com/tutorials/arm/linkerscripts/
and this StackOverflow question: https://stackoverflow.com/questions/1202494/why-doesnt-attribute-constructor-work-in-a-static-library
January 23, 2020 at 01:12 #27207supportKeymasterNo problem, we can add an option for wrapping library references with –whole-archive. Just to double-check, are you using MSBuild and referencing the libraries using the regular References window in VS?
January 23, 2020 at 04:05 #27208codex653ParticipantI’m using MSBuild, but I was explicitly referencing the libraries via the Linker options in the project properties settings. Is there an easier way to do it through references?
January 23, 2020 at 04:16 #27209supportKeymasterHi,
If you are using the Linker Options->Command Line to specify the libraries anyway, you can simply put -Wl,–whole-archive before the library names and -Wl,–no-whole-archive after them.
That said, the recommended way to reference libraries would be to right-click on the executable project in Solution Explorer and select Add->Reference. This will automatically add the libraries to the linker inputs and will also make sure that the libraries are built before the main application. If it helps, we could add a per-library option that will let VisualGDB automatically wrap its name with the –whole-archive/–no-whole-archive when building the linker command line for the main project.
January 24, 2020 at 19:34 #27248codex653ParticipantAdding the references worked a treat. Thanks for the new trick! I wasn’t using the command line to specify the library inputs because it can’t parse Visual Studio macros like $(OutDir), which limits the portability of the solution. So personally I would love having the ability to wrap with -whole-archive/-no-whole-archive! 🙂
January 25, 2020 at 01:44 #27251supportKeymasterNo problem, please try this build: VisualGDB-5.5.3.3461.msi
We have added the following option: VS Project Properties -> Exported Settings-> Link as Whole Archive (needs to be set for the library). After you set it, next time you build the main project, VisualGDB will automatically inject the –whole-archive option into the linker command line (see the .link.rsp file). Note that if you don’t change any other files after applying this option, it won’t trigger a rebuild of the main project.
January 26, 2020 at 15:10 #27262codex653ParticipantThanks so much! That behaves exactly as I hoped and it saved me a ton of headache. I went to debug a project and realized my customized hardfault handler wasn’t being linked in due to the same issue. Turning on the flag linked everything properly and I was able to get to the correct handler! Very very handy flag.
-
AuthorPosts
- You must be logged in to reply to this topic.