Linker script: insert the absolute address of the function in the generated code

I have a question related to the gcc linker.

I work with embedded material (PIC32), but the PIC32 compiler and linker are gcc-based, so the basic things should be normal for a โ€œregularโ€ gcc linker and PIC32 linker.

To save flash space (which is often not enough on microcontrollers), I need to add some large functions to the bootloader, and the application should call these functions only with pointers.

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

I try to get the absolute address of the function and write it to the generated code, but still get errors.

In the example below, I am trying to get the address of the _formatted_write function.

the 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 

The link returns an error: " unresolvable symbol '_formatted_write' referenced in expression ".

I noticed that if I write a little garbage instead of _formatted_write , then it will return the error " undefined symbol ..... ", so _formatted_write is known to the linker.

It makes me think that I have to follow some extra steps to make it "solvable." But I still donโ€™t know how to do it.

+4
source share
2 answers

The way I found this was using function pointers, i.e.

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

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

 formatted_write = 0xa0000; 

you can call your function using the usual convention.

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

 formatted_write = 0xa0000; 
+1
source

In case someone has the same problem (like a few hours ago), there is an even better solution:

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

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

file that we can include in the application script builder with

 INCLUDE bootloader.inc 

Now the linker knows the addresses of all the functions of the loader, and we can bind them without using the actual function code in the application. All we need is a declaration for each bootloader function that we want to execute.

+1
source

Source: https://habr.com/ru/post/1496412/


All Articles