On Tue, Feb 17, 2026 at 11:06:32AM -0500, Joe Lawrence wrote:
> When adding data to an SHF_MERGE section, set the Elf_Data d_align to
> the section's sh_addralign so libelf aligns entries within the section.
> This ensures that entry offsets are consistent with previously calculated
> relocation addends.
>
> Fixes: 431dbabf2d9d ("objtool: Add elf_create_data()")
> Signed-off-by: Joe Lawrence <[email protected]>
> ---
> tools/objtool/elf.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
> index 2c02c7b49265..bd6502e7bdc0 100644
> --- a/tools/objtool/elf.c
> +++ b/tools/objtool/elf.c
> @@ -1375,7 +1375,7 @@ void *elf_add_data(struct elf *elf, struct section
> *sec, const void *data, size_
> memcpy(sec->data->d_buf, data, size);
>
> sec->data->d_size = size;
> - sec->data->d_align = 1;
> + sec->data->d_align = (sec->sh.sh_flags & SHF_MERGE) ?
> sec->sh.sh_addralign : 1;
>
> offset = ALIGN(sec->sh.sh_size, sec->sh.sh_addralign);
> sec->sh.sh_size = offset + size;
> --
> 2.53.0
>
>
This one stretches my ELF internals knowledge a bit, is ^^ true or
should we rely on the section ".str1.8" suffix to indicate internal
alignment?
Here is the repro:
A simple patch to pr_info a few strings to the kernel buffer:
diff --git a/fs/proc/cmdline.c b/fs/proc/cmdline.c
index a6f76121955f..5b7f43105ea8 100644
--- a/fs/proc/cmdline.c
+++ b/fs/proc/cmdline.c
@@ -7,6 +7,10 @@
static int cmdline_proc_show(struct seq_file *m, void *v)
{
+ pr_info("ABCDEFGHIJKLMN: message 1 here\n");
+ pr_info("OPQRSTUVWXYZ12: message 2 here\n");
+ pr_info("34567890abcdef: message 3 here\n");
+ pr_info("ghijklmnopqrst: message 4 here\n");
seq_puts(m, saved_command_line);
seq_putc(m, '\n');
return 0;
results in strange dmesg output:
[ 6179.571413] ABCDEFGHIJKLMN: message 1 here
[ 6179.575689] QRSTUVWXYZ12: message 2 here
[ 6179.579788] 90abcdef: message 3 here
[ 6179.583541] qrst: message 4 here
patched/vmlinux.o
-----------------
First thing to note, section .rodata.cmdline_proc_show.str1.8 has
entries with an alignment of 8 bytes and the section is SHF_MERGE:
$ readelf --wide -S klp-tmp/patched/vmlinux.o
Section Headers:
[Nr] Name Type Address Off
Size ES Flg Lk Inf Al
[132261] .rodata.cmdline_proc_show.str1.8 PROGBITS 0000000000000000
23b3000 00009c 01 AMS 0 0 8
$ eu-objdump -r -j .rela.text.unlikely.cmdline_proc_show
klp-tmp/patched/vmlinux.o | grep str1.8
0000000000000020 R_X86_64_32S .rodata.cmdline_proc_show.str1.8
000000000000002c R_X86_64_32S .rodata.cmdline_proc_show.str1.8+0x28
0000000000000038 R_X86_64_32S .rodata.cmdline_proc_show.str1.8+0x50
0000000000000044 R_X86_64_32S .rodata.cmdline_proc_show.str1.8+0x78
$ eu-objdump -s -j .rodata.cmdline_proc_show.str1.8 klp-tmp/patched/vmlinux.o
klp-tmp/patched/vmlinux.o: elf64-elf_x86_64
Contents of section .rodata.cmdline_proc_show.str1.8:
0000 01364142 43444546 4748494a 4b4c4d4e .6ABCDEFGHIJKLMN
^ (+0x00) ^
0010 3a202020 6d657373 61676520 31206865 : message 1 he
0020 72650a00 00000000 01364f50 51525354 re.......6OPQRST
^ (+0x28) ^
0030 55565758 595a3132 3a202020 6d657373 UVWXYZ12: mess
0040 61676520 32206865 72650a00 00000000 age 2 here......
0050 01363334 35363738 39306162 63646566 .634567890abcdef
^ (+0x50) ^
0060 3a202020 6d657373 61676520 33206865 : message 3 he
0070 72650a00 00000000 01366768 696a6b6c re.......6ghijkl
^ (+0x78) ^
0080 6d6e6f70 71727374 3a202020 6d657373 mnopqrst: mess
0090 61676520 34206865 72650a00 age 4 here..
diff/vmlinux.o
--------------
Same 8-byte alignment of .rodata.cmdline_proc_show.str1.8:
$ readelf --wide -S klp-tmp/diff/vmlinux.o | grep str1.8
Section Headers:
[Nr] Name Type Address Off
Size ES Flg Lk Inf Al
[6] .rodata.cmdline_proc_show.str1.8 PROGBITS 0000000000000000 000540
000090 01 AMS 0 0 8
$ eu-objdump -r klp-tmp/diff/vmlinux.o | grep str1.8
0000000000000020 R_X86_64_32S .rodata.cmdline_proc_show.str1.8
000000000000002c R_X86_64_32S .rodata.cmdline_proc_show.str1.8+0x28
0000000000000038 R_X86_64_32S .rodata.cmdline_proc_show.str1.8+0x50
0000000000000044 R_X86_64_32S .rodata.cmdline_proc_show.str1.8+0x78
but notice they do not point to the strings in a now packed section
contents:
$ eu-objdump -s -j .rodata.cmdline_proc_show.str1.8 klp-tmp/diff/vmlinux.o
klp-tmp/diff/vmlinux.o: elf64-elf_x86_64
Contents of section .rodata.cmdline_proc_show.str1.8:
0000 01364142 43444546 4748494a 4b4c4d4e .6ABCDEFGHIJKLMN
^ (+0x00) ^
0010 3a202020 6d657373 61676520 31206865 : message 1 he
0020 72650a00 01364f50 51525354 55565758 re...6OPQRSTUVWX
^ (+0x28) ^
0030 595a3132 3a202020 6d657373 61676520 YZ12: message
0040 32206865 72650a00 01363334 35363738 2 here...6345678
0050 39306162 63646566 3a202020 6d657373 90abcdef: mess
^ (+0x50) ^
0060 61676520 33206865 72650a00 01366768 age 3 here...6gh
0070 696a6b6c 6d6e6f70 71727374 3a202020 ijklmnopqrst:
^ (+0x78) ^
0080 6d657373 61676520 34206865 72650a00 message 4 here..
--
Joe