2
votes

I am using gcc compiler in windows10's powershell. gcc came with the Atollic TrueSTUDIO ide. The reason I am doing this is to be able to create an .exe file from the C code so unit testing becomes easier.

I encounter a linker error (undefined reference to 'function_name') when there is a function that is defined as weak and that function is used in another .c file.

Meanwhile I do not get this linker error if I use arm-atollic-eabi-gcc or gcc running on ubuntu.

Here is a simple code to demonstrate this:

hello.c:

#include "weak.h"
void whatever(void)
{
  iamweak();
}

weak.c:

#include <stdio.h>
#include "weak.h"

void __attribute__((weak)) iamweak(void)
{
    printf("i am weak...\n");
}

weak.h

void iamweak(void);

main.c

int main(void)
{
 return 0;
}

Creating the object files and linking:

> gcc -c main.c weak.c hello.c

> gcc -o main.exe main.o weak.o hello.o

> hello.o:hello.c:(.text+0x7): undefined reference to `iamweak' collect2.exe: error: ld returned 1 exit status

Now I checked with gcc-nm the symbol table of hello.o:

> gcc-nm hello.o

00000000 b .bss

00000000 d .data

00000000 r .eh_frame

00000000 r .rdata$zzz

00000000 t .text

U _iamweak

00000000 T _whatever

Symbol table for weak.o:

>gcc-nm weak.o

00000000 b .bss

00000000 d .data

00000000 r .eh_frame

00000000 r .rdata

00000000 r .rdata$zzz

00000000 t .text

00000000 T .weak._iamweak.

w _iamweak

U _puts

Now when I use gcc on Ubuntu as I said everything works. Also the symbol tables are a little different.

Symbol table for hello.o:

nm hello.o

U _GLOBAL_OFFSET_TABLE_

U iamweak

0000000000000000 T whatever

Symbol table for weak.o:

nm weak.o

U _GLOBAL_OFFSET_TABLE_

0000000000000000 W iamweak

U puts

From https://linux.die.net/man/1/nm it says that "If lowercase, the symbol is local; if uppercase, the symbol is global (external)."

So iamweak is local in windows10 and global in Ubuntu. Is that why the linker cannot see it? What can I do about this? The weak function definitions are also in some HAL libraries and I don't want to modify those. Is there a workaround?

1
Try to use this other kind of syntax // function declaration int __attribute__((weak)) power2(int x); // or int power2(int x) __attribute__((weak)); // variable declaration; extern int __attribute__((weak)) global_var; (They are explanation lines terminated by ;)Sir Jo Black
I use attolic studio for years and I do not see anything like this0___________
@P__J__ Have you actually tried what I described?Tomi_Stack
@SirJoBlack I don't want the declarations to be weak, only the function definitions.Tomi_Stack
Does gcc even support weak symbols on non-ELF platforms? The gcc manual says nothing about it: "Weak symbols are supported for ELF targets, and also for a.out targets when using the GNU assembler and linker"mosvy

1 Answers

0
votes

it is atollic gcc fork error. It does even worse:

          main:
00401440:   push    %ebp
00401441:   mov     %esp,%ebp
00401443:   and     $0xfffffff0,%esp
00401446:   call    0x401970 <__main>
36          iamweak();
0040144b:   call    0x0
37          return 0;
00401450:   mov     $0x0,%eax
38        }

the complete atollic studio project here