5

I have a question related to gcc's linker.

I'm working with embedded stuff (PIC32), but PIC32's compiler and linker are based on gcc, so, main things should be common for "regular" gcc linker and PIC32 linker.

In order to save flash space (which is often insufficient on microcontrollers) I need to put several large functions in the bootloader, and application should call these functions just by pointers.

So, I need to create vector table in the generated code.

I'm trying to get absolute address of the function and write it to the generated code, but still getting errors.

In the example below I'm trying to get address of the function _formatted_write.

Code:

.user_addr_table _USER_ADDR_TABLE_ADDR :
{
   KEEP(*(.user_addr_table))
   LONG((ABSOLUTE(_formatted_write))); /* _formatted_write is a name of my function */
} > user_addr_table

Linker returns error: "unresolvable symbol '_formatted_write' referenced in expression".

I have noticed that if I write some garbage instead of _formatted_write, then it returns error "undefined symbol .....", so, _formatted_write is known by linker.

It makes me think I should perform some additional steps to make it "resolvable". But still no idea how to do that.

2
  • Is it a requirement to call these functions via entries in a vector table? Otherwise you can try to link while passing the symbols of the bootloader elf file. Commented Oct 15, 2013 at 19:53
  • The name _formatted_write is the name as it appears in the map file of the bootloader? Commented Oct 15, 2013 at 19:54

2 Answers 2

2

The way I found around this was to use function pointers, i.e.

void (*formatted_write)( int a, char * b, struct mystruct c );

then, in the code somewhere at boot set the address of this function, i.e.

formatted_write = 0xa0000;

you can then call your function using the normal convention.

Additionally, you can use the -Wl,--just-symbols=symbols.txt flag when compiling. You can set the address of your symbols as follows:

formatted_write = 0xa0000;
Sign up to request clarification or add additional context in comments.

Comments

2

For the case that someone has the same problem (like me some hours ago), there is a still better solution:

Let "bootloader.out" be the bootloader-binary. Then we can generate with

nm -g bootloader.out | grep '^[0-9,a-f,A-F]\{8\} T' | awk '{printf "PROVIDE(%s = 0x%s);\n",$3,$1}' > bootloader.inc

a file that we can include in the linker script of the application with

INCLUDE bootloader.inc

The linker knows now the addresses of all bootloader-functions and we can link against it without to have the actual function code in the application. All what we need there is a declaration for every bootloader-function which we want to execute.

2 Comments

I was trying the given code, however I noticed the regex only contains the letters a-e instead of a-f (as well as A-F).
Thanks, was a typo.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.