1

I implement a retarget.c to retarget the printf output to serial port for debugging, it can be linked and works very well, if my link command likes this:

arm-none-eabi-gcc --specs=nano.specs --specs=nosys.specs -g -mcpu=cortex-m4 -mthumb -fmessage-length=0 -std=c99 -fno-builtin -Wl,--gc-sections -Wl,-Map=main.map -T"$(LINKERFILE)" -o main.elf main.o retarget.o $(BUILDDIR)/libs.a -Wl,--start-group -lgcc -lc -lnosys -Wl,--end-group

but when I archive retarget.o into the archive file $(BUILDDIR)/libs.a, and the link command likes this one:

arm-none-eabi-gcc --specs=nano.specs --specs=nosys.specs -g -mcpu=cortex-m4 -mthumb -fmessage-length=0 -std=c99 -fno-builtin -Wl,--gc-sections -Wl,-Map=main.map -T"$(LINKERFILE)" -o main.elf main.o $(BUILDDIR)/libs.a -Wl,--start-group -lgcc -lc -lnosys -Wl,--end-group

it can be linked successfully, but the function printf doesn't output anything to the serial port, it seems that the my own version functions, such as _write in the retarget.c are not used in the final compiled program.

xingkong
  • 11
  • 4
  • What is `$(LIBSFILE)`? I guess you must convert your compiled code to a static lib or dynamic lib to do what you want to do. – LPs Jan 25 '16 at 07:14
  • Try linking your static library before or after libc and see if that changes things. I don't remember the rules for which objects and symbols get picked, but the order of the command line arguments to gcc (which you seem to be using) definitely matters. – Art Jan 25 '16 at 08:05
  • @LPs @Art Thank you for your replies, I updated my questions and replaced some macros with actual arguments. @Art, later on I removed `-Wl,--start-group -lgcc -lc -lnosys -Wl,--end-group` in the command line, then the link command like this: `arm-none-eabi-gcc --specs=nano.specs --specs=nosys.specs -g -mcpu=cortex-m4 -mthumb -fmessage-length=0 -std=c99 -fno-builtin -Wl,--gc-sections -Wl,-map=main.map -T"$(LINKERFILE)" -o main.elf main.o $(BUILDDIR)/libs.a`, but the result still the same, the function printf doesn't output anything to the serial port – xingkong Jan 26 '16 at 22:05
  • Did you try to link your lib with -l option? – LPs Jan 27 '16 at 07:24
  • @LPs, yes, anyway, I believe the `nosys.specs` forced another library was linked firstly. I believe I found the answer somewhere else, here is the link: https://sourceware.org/ml/newlib/2006/msg00036.html – xingkong Jan 30 '16 at 22:12

1 Answers1

3

your _write implementation isn't linked because _write is already defined in libnosys.a which you included via --specs=nosys.specs.

To use the _write symbol defined in your static library libs.a, invoke gcc with -Wl,--undefined=_write during the final linking.

see: man ld | grep -A4 --undefined=symbol

--undefined=symbol
    Force symbol to be entered in the output file as an undefined symbol.

Details

First: spec files. gcc is a compiler-driver which invokes subprograms including cc and ld. Spec files are used to specify the behavior of gcc.

The compiler's builtin specs can be seen with arm-none-eabi-gcc -dumpspecs. Try it out! See also: gcc -dumpspecs

Passing --specs=nosys.specs at the beginning of the command line inserts a -lnosys in the call to ld. (What are “nosys”, “nano”, “rdimon” terms when using ARM GCC?)

arm-none-eabi-objdump -t arm-none-eabi/lib/libnosys.a | grep _write locates the _write(...) that is likely overriding the one you defined in $(BUILDDIR)/libs.a

See also: the Makani firmware repository, in which a static library implementing syscalls marks them as --undefined (Generation of linker options)

RemarkableBucket
  • 340
  • 4
  • 11