ld: Question about the string merging feature
Jan Beulich
jbeulich@suse.com
Thu Jun 13 11:15:55 GMT 2024
On 13.06.2024 12:59, Ludwig Rydberg wrote:
>
> Dear maintainers,
>
> I have a question about the string merging feature of the GNU linker
> which seems to be doing things a bit differently since the 2.41 release.
>
> When I specify multiple inputs (including text,data,rodata) in an output
> section the order seems not to be considered/preserved for the mergeable
> strings. Instead all mergeable strings are written into the first
> matching section.
>
> Here follows an example that explains what I see.
>
> main.c:
> extern const char* foo_str;
> extern const char* bar_str1;
> extern const char* bar_str2;
> extern const char* baz_str1;
>
> int run()
> {
> return 0;
> }
>
> foo.c
> const char *foo_str = "FOO_STR1";
>
> bar1.c:
> const char *bar_str1 = "BAR_STR1";
>
> bar2.c:
> const char *bar_str2 = "BAR_STR2";
>
> baz.c:
> const char *baz_str = "BAZ_STR";
>
> link.lds:
> ENTRY(run)
> SECTIONS {
> .my_section (READONLY) : {
> *foo*.o(.*data*);
> *foo*.o(.text);
>
> *bar*.o(.text);
> *bar*.o(.*data*);
>
> *(.text);
> *(.*data*);
> }
> .bss : { *(.bss); *(.bss.*) }
> }
>
> The files are compiled (using gcc 11.4 with -fmerge-constants enabled)
> and linked:
>
> gcc -fmerge-constants -c *.c
> ld foo.o bar1.o bar2.o main.o baz.o -T link.lds
>
> The output of the section looks like this before 2.41:
>
> Contents of section .my_section:
> 0000 08000000 00000000 464f4f5f 53545231 ........FOO_STR1
> 0010 000f1f80 00000000 20000000 00000000 ........ .......
> 0020 4241525f 53545231 000f1f80 00000000 BAR_STR1........
> 0030 38000000 00000000 4241525f 53545232 8.......BAR_STR2
> 0040 00554889 e5b80000 00005dc3 0f1f4000 .UH.......]...@.
> 0050 58000000 00000000 42415a5f 53545231 X.......BAZ_STR1
> 0060 00
>
> Here we see that the sections and strings are written in the order as
> specified in the linker script (i.e first *data* and then *text* from foo).
>
> From 2.41 (and newer) it looks like this:
>
> Contents of section .my_section:
> 0000 08000000 00000000 464f4f5f 53545231 ........FOO_STR1
> 0010 00424152 5f535452 31004241 525f5354 .BAR_STR1.BAR_ST
> 0020 52320042 415a5f53 54523100 0f1f4000 R2.BAZ_STR1...@.
> 0030 11000000 00000000 1a000000 00000000 ................
> 0040 554889e5 b8000000 005dc30f 1f440000 UH.......]...D..
> 0050 23000000 00000000 #.......
>
> Now all strings from all inputs are merged and written at the same
> location. Hence, the order of the inputs (as they are stated in the
> linker script) seems not to be considered.
>
> By bisecting the source I found that this was changed by the following
> commit: 1a528d3ef07f ("Faster string merging")
>
> My question is what to expect here?
My understanding is that by permitting merging, you give up certain
expectations you could normally validly have as to placement in the final
binary. This would become more obvious if you had some cases in your
example where strings could actually be merged. The (true) merging that
then would happen would already break your assumptions. Since making such
assumptions isn't correct anyway when merging is permitted, the new
logic may as well move stuff around further (presumably all into the 1st
.rodata, i.e. resulting from *foo*.o(.*data*) in your linker script).
> Was this change intended and part of
> the work with the "Faster string merging" feature?
It may not have been "intended", but I suppose such side effects were at
least to be expected.
Jan
More information about the Binutils
mailing list