Linking to a bootloader callback function from firmware - gcc

I'm trying to achieve something similar as in this quesition. I'm compiling a firmware file written in C, and the code needs to call a function in the bootloader.
My firmware file looks like this:
void callback(void);
int main(void){
__asm__("nop; ");
callback();
__asm__("nop; ");
return(0)
}
The firmware function compiles without error using gcc firmware.c but the function body only contains the two nop instruction with nothing in-between them (which makes sense, the function is undefined).
I made a script that runs the bootloader and prints out the address &callback, which i can use in the firmware to define a function pointer in my main():
void (*call_this)(void) = (void (*)(void )) 0x555555554abd;
call_this();
That makes the callback work, but I don't want to have to run the bootloader to compile the firmware.
I've tried fumbling around with linker scripts, but I'm new to those.
I tried supplying
PROVIDE(callback = 0x0000000000000969);
or
PROVIDE(callback = 0x555555554abd);
to the linker by compiling the firmware with:
gcc -Xlinker -T linkerscript firmware.c
The first address is from nm firmware.out | grep callback, the other from running the bootloader in gdb. Compiling with the linker script gives this error:
/usr/bin/ld: firmware.out: Not enough room for program headers, try linking with -N
/usr/bin/ld: final link failed: Bad value
collect2: error: ld returned 1 exit status
After some more reading, I think I should to use the -R flag of ld to accomplish this.
Read symbol names and their addresses from filename, but do not relocate it or include it in the output. This allows your output file to refer symbolically to absolute locations of memory defined in other programs. You may use this option more than once.
Just haven't made it work quite right yet.

Use the --no-dynamic-linker linking option, as done by U-Boot to solve this issue. Note that if you invoke the linker trough gcc the option must be set using -Wl,--no-dynamic-linker.

Related

is there a way to have the compiler warn/err if an attribute section is not defined in the linker script?

Using arm-none-eabi-gcc compiler toolchain for arm microcontrollers, and am defining a specific section in FLASH where this foo variable should live.
Let's say I have the example definition:
int foo __attribute__((section(".bar"))) = 5;
What I have observed is that if .bar is not assigned in the linker script, than the build will successfully succeed and foo will live in RAM instead as initialized data (the constant initial value will of course add to the FLASH size as well). The annoying part is, the linker does not complain when the section does not exist and so if expecting data to reside in FLASH it may silently live in a non-fixed location in RAM. Is there a compile/linker option to force a failure if this occurs?
According to GNU ld documentation, ld can be told to handle orphan linker sections as errors using the --orphan-handling=error command-line option.
Assuming orphan.c does contain the following code:
int foo __attribute__((section(".bar"))) = 5;
int main(void)
{
return 0;
}
The following command does succeed:
aarch64-elf-gcc --specs=rdimon.specs -o orphan orphan.c
But that one does fail:
aarch64-elf-gcc --specs=rdimon.specs -Wl,--orphan-handling=error -o orphan orphan.c
c:/git/cortex-baremetal/opt/gcc-linaro-7.3.1-2018.05-i686-mingw32_aarch64-elf/bin/../lib/gcc/aarch64-elf/7.3.1/../../../../aarch64-elf/bin/ld.exe: error: unplaced orphan section `.tm_clone_table' from `c:/git/cortex-baremetal/opt/gcc-linaro-7.3.1-2018.05-i686-mingw32_aarch64-elf/bin/../lib/gcc/aarch64-elf/7.3.1/crtbegin.o'.
c:/git/cortex-baremetal/opt/gcc-linaro-7.3.1-2018.05-i686-mingw32_aarch64-elf/bin/../lib/gcc/aarch64-elf/7.3.1/../../../../aarch64-elf/bin/ld.exe: error: unplaced orphan section `.bar' from `C:\Users\user\AppData\Local\Temp\cc6aRct8.o'.
c:/git/cortex-baremetal/opt/gcc-linaro-7.3.1-2018.05-i686-mingw32_aarch64-elf/bin/../lib/gcc/aarch64-elf/7.3.1/../../../../aarch64-elf/bin/ld.exe: error: unplaced orphan section `.tm_clone_table' from `c:/git/cortex-baremetal/opt/gcc-linaro-7.3.1-2018.05-i686-mingw32_aarch64-elf/bin/../lib/gcc/aarch64-elf/7.3.1/crtend.o'.
It seems the default linker script I used for the purpose of this example is missing another section, '.tm_clone_table'. It would have to be fixed in order not to trigger an error when '.bar' section is properly defined.

Dynamically load code on embedded target

I have an application which runs on bare metal target and has the following structure
main.c
service.c/.h
It's compiled to ELF executable (system.elf) using standard gcc -c, ld sequence. I use linker to generate a map file showing adresses of all symbols.
Now, without re-flashing my system I need to add an extra functionality with a custom run-time loader. Remember, this is a bare-metal with no OS.
I'd like to
compile extra.c which uses APIs defined in service.h (and somehow link against existing service.o/system.elf)
copy the resulting executable to my SDRAM at runtime and jump to it
loaded code should be able to run and accesses the exported symbols from service.c as expected
I thought I'd be able to to reuse map file to link the extra.o against system.elf but this didn't work:
ld -o extraExe extra.o system.map
Does gcc or ld have some mode to make this late linking procedure? If not, how can I achieve dynamic code loading which I outlined above?
You can use the '-R filename' or '--just-symbols=filename' command options in ld. It reads symbol names and their addresses from filename, but does not relocate it or include it in the output. This allows your output file to refer symbolically to absolute locations of memory defined in your system.elf program.
(refer to ftp://ftp.gnu.org/old-gnu/Manuals/ld-2.9.1/html_node/ld_3.html).
So here filename will be 'system.elf'. You can compile extra.c with GCC normally including services.h but without linking and generate 'extra.o' then call ld as below:
ld -R"system.elf" -o"extra.out" extra.o
The 'extra.out' shall have your symbols linked. You can use objdump to compare contents of both 'extra.out' and 'extra.o'.
Note that you can always pass the start address of your program to the ld (e.g. -defsym _TEXT_START_ADDR=0xAAAA0123) as well as start address of other memory sections like bss,data. (i.e. -Tbss, -Tdata)
Be careful to use a valid address that does not conflict with your 'system.elf' as ld will not generate error for that. You can define new areas for the loaded code+data+bss in your original linker script and re-compile the system.elf then point the start addresses to your defined areas while linking 'extra.o'.

How to make printf work on STM32F103?

I am new to the world of STM32F103. I have a demo code for STM32F103 and I am using arm-none-eabi to compile it.
I tried what I could find on Google, but nothing worked so far. I have already spent three days on the problem.
Anyone can give me a demo code for printf which works well?
Part of my makefile:
CFLAG = -mcpu=$(CPU) -mthumb -Wall -fdump-rtl-expand -specs=nano.specs --specs=rdimon.specs -Wl,--start-group -lgcc -lc -lm -lrdimon -Wl,--end-group
LDFLAG = -mcpu=$(CPU) -T ./stm32_flash.ld -specs=nano.specs --specs=rdimon.specs -Wl,--start-group -lgcc -lc -lm -lrdimon -Wl,--end-group
By including the following linker flags:
LDFLAGS += --specs=rdimon.specs -lc -lrdimon
it looks like you are trying to use what is called semihosting. You are telling the linker to include system call libraries.
Semihosting is a mechanism that enables code running on an ARM target to communicate and use the Input/Output facilities on a host computer that is running a debugger.
Examples of these facilities include keyboard input, screen output, and disk I/O. For example, you can use this mechanism to enable functions in the C library, such as printf() and scanf(), to use the screen and keyboard of the host instead of having a screen and keyboard on the target system.
Since you are using openSource tools for your STM32 development (Makefile and arm-none-eabi), I am assuming you are also using openOCD to program your microcontroller. openOCD requires you to enable semihosting as well using the following command:
arm semihosting enable
You can at the command to your openOCD script making sure you terminate the configuration stage and enter the run stage with the 'init' command. Below is an example of an openOCD script (adapted for STM32F103):
source [find target/stm32f1x.cfg]
init
arm semihosting enable
Other solutions mentioned here where your retarget the fputc() function to a UART interface will also work and might. Semihosting will work on all recent ARM Cortex-M but will require some compiler & debugger configuration (see above). Retargeting the fputc() function to a UART interface will work with any compiler but you will have to check your pin configurations for every board.
Writing an own printf implementation is an option, and probably the most recommended option according to me. Get some inspiration from the standard library implementation and write your own version, only to cater your requirements. In general, what you have to do is, first retarget a putc function to send char s through your serial interface. Then override the printf method by using the putc custom implementation. Perhaps, a very simple approach is sending the string character-wise by recursive calls for putc function.
Last but not least, you can find some lightweight printf implementations. The code size and the set of features offered by these lightweight implementations lie in between the custom written printf function and the stock standard printf function (aka the beast). I have recently tried this Tiny Printf and very pleased with its performance on an ARM core in terms of memory footprint and the number of execution cycles required.
-PS
Copied from my own writings sometime back.
Link: How to retarget printf() on an STM32F10x?
Try hijacking the _write function like so:
#define STDOUT_FILENO 1
#define STDERR_FILENO 2
int _write(int file, char *ptr, int len)
{
switch (file)
{
case STDOUT_FILENO: /*stdout*/
// Send the string somewhere
break;
case STDERR_FILENO: /* stderr */
// Send the string somewhere
break;
default:
return -1;
}
return len;
}
The original printf will go through this function (depending on what libs you use of course).
Look there. This is printf from glib. But you have microcontroller. So you sould write own printf, where vfprintf will return result into buffer and next you will send data from buffer to UART. Kind of
void printf( const char * format, ... )
{
char buffer[256];
va_list args;
va_start (args, format);
vsprintf (buffer,format, args);
send_via_USART1 (buffer);
va_end (args);
}
Also you can write own vsprintf. Standart vsprintf is very heavy. Usually little part of vsprintf features is used.

error: unknown "%" symbol on SPARC

My program works fine on Ubuntu.
It encounters error when I compile it with gcc on a Solaris SPARC system.
I have several pieces of code like:
printf("endian_convert: %s\n", endian_convert);
asm("movl $8, %esi\n\t"
"movl $.LC0, %edi\n\t"
"movl $0, %eax");
This is the error I get on SPARC:
gcc -g -Wall -Werror -pedantic -Wextra src/utfconverter.c -o bin/utf
/usr/ccs/bin/as: "/var/tmp//cc9czJEf.s", line 957: error: unknown "%"-symbol
/usr/ccs/bin/as: "/var/tmp//cc9czJEf.s", line 957: error: statement syntax
.......
/usr/ccs/bin/as: "/var/tmp//cc9czJEf.s", line 1058: error: unknown "%"-symbol
/usr/ccs/bin/as: "/var/tmp//cc9czJEf.s", line 1058: error: statement syntax
*** Error code 1 make: Fatal error: Command failed for target `utf'
So, the "%" symbol is considered as unknown on SPARC?
How can I fix this and make it working on SPARC?
(The original version of the question didn't mention that the errors were from a SPARC Solaris system, and just called it C90 because the old version of gcc installed on it defaulted to -std=c90, leading to error messages about things that are illegal in C90.)
Wait a minute, "works fine on Ubuntu but not on C90"? /usr/ccs/bin/as (in your screenshot) looks like Solaris. That + the hostname is a clue that this might be a SPARC machine, not x86 at all.
Obviously x86 assembly isn't valid SPARC assembly syntax. It's a different CPU architecture.
If you'd used gcc foo.c -S and looked at the resulting foo.s asm output file, you'd see that it was full of SPARC asm, except for text inserted literally by your asm statements.
SPARC syntax does use % decorators on register names, but the register names are different. e.g. add %i0, %i1, %o0 adds input registers i0 and i1, storing the result in output register o0. (Input as in function arg and output as in function result. SPARC uses a sliding window onto a large virtual register file that might or might not spill to memory, depending on whether the CPU microarchitecture is out of registers when the save instruction runs.)
Remember that these errors are from the Solaris assembler, not from gcc. You're using gcc but it's using the system assembler instead of the GNU assembler.
Anyway, I recommend rewriting your code into pure portable C, rather than using #ifdef __x86__ to keep using that inline asm, or writing a SPARC port of it.
BTW, your asm statement looks horrible. A different version of gcc might store a different constant at .LC0, breaking your code. More importantly, you're not using input/output constraints to tell the compiler what value is where. If you're assuming it's ok to set eax in asm inside a function, that's incorrect. The function can and will inline, and then your asm is just floating free in the middle of wherever your function inlined. See the end of this answer for links to some GNU C inline asm tutorials.
Also, you don't need inline asm to endian-convert. You will get better asm from using endian.h functions like uint32_t le32toh(uint32_t little_endian_32bits); which use gcc builtins or inline asm to get the compiler to make optimal assembly output itself.
See also https://gcc.gnu.org/wiki/DontUseInlineAsm, which applies even if you did know how to use it properly.

Compiling within the code with g++ in Code::Blocks

I am trying to write a game similar to code hunt (https://www.codehunt.com/about.aspx)
So How this will work, is the player can modify a .cpp file, which will be compiled and and ran within the code, but I have problems about how to compile it.
I'am using the latest g++ compiler, and this is how I try to achive this:
void Builder::build(const char* file){
std::string s = "g++ ";
s += file;
s += " -o test.o";
system(s.c_str());
}
Where we get the .cpp file's name, and this code piece is supposed to build test.o
This is just a test now, it might get more complex, I just wanted to test if the compiler will work within the code, but I get this error message when I try to run this:
c:/mingw/bin/../lib/gcc/mingw32/4.9.3/../../../libmingw32.a(main.o):(.text.startup+0xa7):undefined reference to 'WinMain#16'
collect2.exe: error: ld returned 1 exit status
PATH for mingw is set correctly, I checked.
I am using Windows 8.1, g++ 4.9.3 and Code::Blocks.
In Windows execution doesn't normally start at the main functions, it starts at the WinMain function, which takes some Windows-specific arguments. You should read e.g. this WinMain reference for more information.
That some programs still seems to start at a main function is because there is an object file linked with the program that contains the WinMain function which calls your main function.
OK I'm an idiot, so the problem was that I was trying to build a file whitout a main function. This was deliberat design choice at first, but...well yeah. Sorry about that.
Thank you Joachim Pileborg for leading me to it.

Resources