简体   繁体   中英

Position independent code on MCU - everything works, except vsnprintf - C alternative for vsnprintf?

I am pulling my hear out for quite a while. I am trying to achieve position independent code on a microcontroller. It's quite a rabbit hole. I've gotten so far that I can bring my app online, and responsive for mqtt commands.

The only thing I can't seem to do, for to me completely unknown reasons, is 1 specific stdlib call: vsnprintf or any of its siblings. I am using the arm-none-eabi toolchain version 10.2. I have the source code, also of this specific function, but it goes sooo deep into stuff I just don't understand enough about, so I am stuck on every attempt to get around this problem.

I am using lwip (light weight IP) which makes calls into snprintf . It works fine, until I relocate my app to a different location in flash. The .got section and sram memory is properly patched with the lma_offset I calculate in my custom bootloader. Again, everything works, except this horrible single freaking call into the std lib.

For debugging purposes, I made a wrapper for snprintf in the hope I could drill down just a bit more to understand what the problem is. I am not getting much further.

    int snprintf_override (
        char *__restrict buffer, 
        size_t size, 
        const char *__restrict format, 
        ...)
    {
        int result;
        va_list args;

        va_start(args, format);
        // The next line calls into std lib, and hard faults, I wish I could share anything else that made any sense...
        result = vsnprintf(buffer, sizeof(buffer), format, args);
        va_end(args);

        return result;
    }

Question 1:

Is there anybody who can suggest another way to achieve functionally the same as vsnprintf ? Is it even doable to write something from scratch? I have the feeling there is quite some complexity in that function?

Question 2:

Or, is there anybody, who has ANY idea what can be the problem in relocating code which causes svnprintf to fail? Digging through the stdlib code I come across REENT / impurepointers (?), and the implementation relies on a FILE instance. Still "just data" I would say in my naivety, but maybe it's more than that? Is there some assembly hidden somewhere which is simply not relocatable (I can't believe it's not possible, linux OS does nothing else than compile with -fpic ...)?

I am afraid this question gets little attention, but maybe, just maybe, somebody with some severe understanding of std lib and/or position independent code clicks on it, and is willing to help me out...

I never found out exactly goes wrong in the libc-nano. But, I think I have proof enough that the problem I ran into has everything to do with libc-nano not being compiled with -fpic.

I reproduced the problem in a smaller test setup which consists of:

  • a bootloader (runs from 0x60000000) which copies vtor of app to sram,
  • an app (runs from 0x60020000 or 0x600a0000) which copies global offset table, data, and c++ constructors, to sram, during startup.
  • in the main of the app, I only make a call to stdlib's vsnprintf .
libc-nano picolibc picolibc recompiled with -fpic
app@0x60000000 works works works
app@0x600a0000 hard fault hard fault works

I integrated picolibc (recompiled with -fpic) into my original project. Now everything works perfectly.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM