Martin Allard
Martin Allard

Reputation: 293

undefined reference of assembly element in c file

I have linkers errors(undefined reference) that I cannot solve by myself. I use GCC Sourcery G++ Lite 4.5.2 for ARM.

I have a lot of undefined reference and they almost all refer to assembly file. Here one example :

I have "_CPU_MmuConfigGet" defined in an assembly file named cpu.sx :

.global _CPU_MmuConfigGet
CPU_MmuConfigGet: 
mrc p15,0,r0,c1,c0,0        
mov pc,lr

In a c file named mmu.c , CPU_MmuConfigGet is called :

#include "cpu.h"
U32 MMU_ConfigGet(void) {
    return CPU_MmuConfigGet();
}

Finally, in the header file cpu.h, CPU_MmuConfigGet is declared :

extern U32 CPU_MmuConfigGet(void);

Theses tree files are located in the following folders :

Base/Common/src/mmu.c     
Base/Common/inc/cpu.h     
Base/Common/src/cpu.sx    

From different post I red on the net, I found that I should add an underline to CPU_MmuConfigGet (tried, but didn't solve my problem). I also red in some forum that , when linking, object file order are important, but in others forums, object order are not important (I'm confused here...). I tried the -S parameter to see the assembly version of mmu.c, but that didn't help me finding a clue about my error...

Here's is the compiler command used (I have added -H in case this help finding what is wrong...) :

arm-none-eabi-gcc -c -g3 -gdwarf-2  -H -o"mmu.o" -Wall -Wa,-adhlns="mmu.o.lst" 
-fmessage-length=0 -MMD -MP -MF"mmu.d" -MT"mmu.d" -fpic  -march=armv4t -mcpu=arm7tdmi -mlittle-endian 
-I"../../OS/ngos/hw/cdb89712" -I"../../OS/ngos" -I"../../OS/ngos/include" -I"../../OS/ngos/rtos/ucosii"  
-I"C:/Program Files/CodeSourcery/Sourcery G++ Lite/lib/gcc/arm-none-eabi/4.5.2/include" -I"./"  
-I"src/" -I"../../Common/inc" -I"../../OS/uCOS-II/SOURCE" -I"../../OS/ngos/drivers/arm" 
-I"../../OS/ngos/include/ngos" -I"../../OS/ngip/include" -I"../../OS/ngip/include/ngip" 
-I"../../Dvcscomponent/Inc" -I"../../Inc"  "../../Common/src/mmu.c"
. ../../Common/inc/base.h
. ../../Common/inc/hw7312.h
. ../../Common/inc/serial.h
.. ../../Common/inc/base.h
.. ../../Common/inc/hw7312.h
. ../../Common/inc/base.h
. ../../Common/inc/cpu.h
.. ../../Common/inc/base.h
.. ../../Common/inc/hw7312.h
. ../../Common/inc/mmu.h

Now the assembly command :

arm-none-eabi-gcc -g3 -gdwarf-2  -x assembler-with-cpp -Wa,-adhlns="cpu.o.lst" -Wall -c 
-fmessage-length=0 -MMD -MP -MF"cpu.d" -MT"cpu.d" -fpic -o"cpu.o" -march=armv4t  -mcpu=arm7tdmi -mlittle-endian 
-I"../../OS/ngos/hw/cdb89712" -I"../../Common" -I"../../OS/ngos/drivers/arm" 
"../../Common/src/cpu.sx"

Finally the linking command with the error :

arm-none-eabi-gcc -fpic -mcpu=arm7tdmi -T".\linker.ld" -Wl,-Map,BootLoad.map -g3 -gdwarf-2  -o "BootLoad.elf"  
InitMain.o tsk_main.o ecp.o memalloc.o tsk_ecp.o firmdesc.o crc.o flash.o eth.o firmflash.o 
firmdest.o bcfg.o bootdownload.o cinit.o serial.o cpu.o mmu.o  ngucos.o cdbini.o cs712sio.o  
cs712eth.o  ../../OS/ngos/lib/rtstub/arm/gcc/libngosd4m32l.a ../../OS/ngip/lib/rtstub/arm/gcc/libngipd4m32l.a 
mmu.o: In function `MMU_ConfigGet':
C:\Working\SF2100-0074-BootLoaderMezz\Base\NexGen\BootLoader/../../Common/src/mmu.c:28: undefined reference to `CPU_MmuConfigGet'

I someone have any suggestions, I would be pleased to hear them!

Thanks in advance!

Upvotes: 0

Views: 2801

Answers (2)

Martin Allard
Martin Allard

Reputation: 293

Finally, after consulting the listing of cpu.sx, I was surprised that a part of the file was "missing". I realized that the file had an include of another assembly file. This included assembly file was ended... by a

.end

directive.

I removed this directive and the project compiled.

Upvotes: 1

ams
ams

Reputation: 25599

The problem appears to be that your source has a leading underscore in some places, but not in others. You don't need them with that toolchain, although you can, if you like, but it has to be consistent.

Even better, perhaps you should ditch the little assembler files altogether, and use assembler inserts in C files?

E.g.

int CPU_MmuConfigGet ()
{
  int config;
  asm ("mrc p15,0,%0,c1,c0,0" : "=r" (config));
  return config;
}

This little function hides all that linker nonsense, cleans up your project tree, and your makefiles, and the compiler is even free to inline it into other functions if it can.

The compiler manual has full details of now to specify inputs and outputs to assember inserts. They're a little bit confusing at first, but worth it in the long run, I find.

Of course, there some places where an assembler file is still necessary - crt0.s, for example.

Upvotes: 0

Related Questions