hippy
Posts: 10745
Joined: Fri Sep 09, 2011 10:34 pm
Location: UK

Binary Information and Linking

Fri Sep 24, 2021 12:47 pm

Am I correct that Binary Information is collated and included in a UF2 when a C file is compiled regardless of whether that C file's object code is actually linked into the final executable ?

What is the best approach for having a C file determine it won't be linked, so it can exclude Binary Information, so 'picotool info' doesn't report a UF2 contains some feature when it does not ?

User avatar
triss64738
Posts: 63
Joined: Wed Jun 16, 2021 5:13 pm
Location: masto/fedi: sys64738@hellsite.site
Contact: Website

Re: Binary Information and Linking

Fri Sep 24, 2021 12:57 pm

UF2 files do contain binary info, but "regardless of whether that C file's object code is actually linked into the final executable" can mean multiple things:
  • The object file is not included in the linker command invocation
  • The object file is in a static archive that is used, but none of its functions are used
  • None of the code in the C file is used, but is included explicitly in the linker command invocation
In the first case, the binary info won't be shown in the output, but in the latter two cases, it will (though I'm not 100% sure about the middle case).

Why and how does this happen? The SDK declares all binary info data to reside in a specific section, and the linker script then concatenates them together in a specific region. The "KEEP" directive tells the linker to include all sections, even if they aren't used (directly or indirectly) by the entrypoint. The linker sees these completely different from the other code in your C file, as the linker operates on these input sections, instead of files.

So I don't immediately know of a good way to make the linker discard the binary data in situations 2 and 3. You could have the binary data somehow be a dependency of the code in that file, and *not* have it be depended on by a ".binary_info.keep.*" section, while still being parseable by external programs. Sadly I don't know much about binary info internals.

(EDIT: of course the "clean" solution would be to have everything depend on preprocessor defines, but, this feels like a workaround rather than a solution.)

hippy
Posts: 10745
Joined: Fri Sep 09, 2011 10:34 pm
Location: UK

Re: Binary Information and Linking

Fri Sep 24, 2021 1:37 pm

triss64738 wrote:
Fri Sep 24, 2021 12:57 pm
Why and how does this happen?
It is when building MicroPython, where user-created C modules can be included or not by adding this kind of magical incantation to the end of such modules -

Code: Select all

MP_REGISTER_MODULE(MP_QSTR_bootsel, mp_module_bootsel, ENABLE_OWN_MODULE_BOOTSEL)
I have no idea how the MicroPython build uses that but it works; no 'bootsel' related code seen in the *.dis file if not enabled, there when it is.
triss64738 wrote:
Fri Sep 24, 2021 12:57 pm
(EDIT: of course the "clean" solution would be to have everything depend on preprocessor defines, but, this feels like a workaround rather than a solution.)
That did indeed become my current workaround when I identified the issue. But it feels like there should be some better way.

kilograham
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 964
Joined: Fri Apr 12, 2019 11:00 am
Location: austin tx

Re: Binary Information and Linking

Fri Sep 24, 2021 1:42 pm

triss64738 wrote:
Fri Sep 24, 2021 12:57 pm

So I don't immediately know of a good way to make the linker discard the binary data in situations 2 and 3. You could have the binary data somehow be a dependency of the code in that file, and *not* have it be depended on by a ".binary_info.keep.*" section, while still being parseable by external programs. Sadly I don't know much about binary info internals.
Use bi_decl_if_func_used that's what its there for. (you declare the BI inside a function, and it will only be included if that function is linked into the final binary)

hippy
Posts: 10745
Joined: Fri Sep 09, 2011 10:34 pm
Location: UK

Re: Binary Information and Linking

Fri Sep 24, 2021 5:38 pm

kilograham wrote:
Fri Sep 24, 2021 1:42 pm
Use bi_decl_if_func_used that's what its there for. (you declare the BI inside a function, and it will only be included if that function is linked into the final binary)
Two problems there. First MicroPython C modules do not necessarily have any functions, may simply return constants or data structures -

Code: Select all

#include "py/runtime.h"

BI_AM_ADD("identify")
BI_AM_TXT("identify module included")

STATIC const mp_rom_map_elem_t identify_module_globals_table[] = {
  { MP_ROM_QSTR(MP_QSTR___name__),  MP_ROM_QSTR(MP_QSTR_identify)   },
  { MP_ROM_QSTR(MP_QSTR_variant),   MP_ROM_QSTR(MP_QSTR_PicoPython) },
};
STATIC MP_DEFINE_CONST_DICT(identify_module_globals, identify_module_globals_table);

const mp_obj_module_t mp_module_identify = {
    .base = { &mp_type_module },
    .globals = (mp_obj_dict_t *)&identify_module_globals,
};

MP_REGISTER_MODULE(MP_QSTR_identify, mp_module_identify, ENABLE_OWN_MODULE_IDENTIFY);
Second I am not sure how I would modify my BI_AM_ADD and BI_AM_TXT macros. I ran into enough problems when I tried to combine them as a single macro - BI_AM_ADD("name", "desc") -

Code: Select all

#define BI_AM_TAG               BINARY_INFO_MAKE_TAG('A', 'M')
#define BI_AM_ID                0x61F52DA4
#define BI_AM_ADD(nam)          bi_decl(bi_string(BI_AM_TAG, BI_AM_ID, nam))
#define BI_AM_TXT(txt)          bi_decl(bi_program_feature(txt))

bi_decl(bi_program_feature_group_with_flags(
        BI_AM_TAG, BI_AM_ID, "added modules",
        BI_NAMED_GROUP_SEPARATE_COMMAS | BI_NAMED_GROUP_SORT_ALPHA));
It seems to me that wrapping them in '#if' conditionals will actually be the best and most elegant solution, the path of least effort.

Return to “SDK”