On Wed, Mar 04, 2026 at 06:33:47PM -0800, Josh Poimboeuf wrote:
> On Tue, Feb 17, 2026 at 11:14:17AM -0500, Joe Lawrence wrote:
> > 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?
>
> I hit the same issue in my testing for the klp-build arm64 port, I think
> it can be simplified to the below?
>
> diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
> @@ -1375,7 +1382,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_addralign;
>
> offset = ALIGN(sec->sh.sh_size, sec->sh.sh_addralign);
> sec->sh.sh_size = offset + size;
>
Yeah that make sense, but I think we both missed the second half of the
fix in the symbol table. This patch fails with your version:
-->8-- -->8-- -->8-- -->8-- -->8-- -->8-- -->8-- -->8-- -->8-- -->8--
diff --git a/fs/proc/stat.c b/fs/proc/stat.c
--- a/fs/proc/stat.c
+++ b/fs/proc/stat.c
@@ -54,6 +54,13 @@ static u64 get_iowait_time(struct kernel_cpustat *kcs, int
cpu)
return iowait;
}
+static void klp_test_stat_accessed(void)
+{
+ static atomic_t call_count = ATOMIC_INIT(0);
+ atomic_inc(&call_count);
+ pr_info("klp-build-test: stat accessed %d times\n",
atomic_read(&call_count));
+}
+
static int show_stat(struct seq_file *p, void *v)
{
int i, j;
@@ -92,6 +99,7 @@ static int show_stat(struct seq_file *p, void *v)
user = nice = system = idle = iowait =
irq = softirq = steal = 0;
guest = guest_nice = 0;
+ klp_test_stat_accessed();
getboottime64(&boottime);
/* shift boot timestamp according to the timens offset */
timens_sub_boottime(&boottime);
-->8-- -->8-- -->8-- -->8-- -->8-- -->8-- -->8-- -->8-- -->8-- -->8--
Confused on instruction decoding?
livepatch-test.o: warning: objtool: show_stat+0x696: can't find jump dest
instruction at .rodata.show_stat.str1.1+0x38
make[3]: *** [/root/linux/scripts/Makefile.build:505: livepatch-test.o] Error
255
make[3]: *** Deleting file 'livepatch-test.o'
make[2]: *** [/root/linux/Makefile:2064: .] Error 2
make[1]: *** [/root/linux/Makefile:248: __sub-make] Error 2
make: *** [Makefile:248: __sub-make] Error 2
error: klp-build: line 793: '"${cmd[@]}" > >(tee -a "$log") 2> >(tee -a
"$log" 1>&2)'
error: klp-build: line 795: '( cd "$SRC"; "${cmd[@]}" > >(tee -a "$log") 2>
>(tee -a "$log" 1>&2) )'
Notice the 0x10 section offset value for show_stat in the generated
vmlinux.o diff object symbol table:
$ readelf --wide --symbols klp-tmp/diff/vmlinux.o | grep -E
'Ndx|\.text\.show_stat$|show_stat$|pfx_show_stat$'
Num: Value Size Type Bind Vis Ndx Name
1: 0000000000000000 16 FUNC LOCAL DEFAULT 4 __pfx_show_stat
2: 0000000000000010 2126 FUNC LOCAL DEFAULT 4 show_stat
5: 0000000000000000 0 SECTION LOCAL DEFAULT 4 .text.show_stat
but then in the disassembly, show_stat() starts 0x20 bytes into the
section:
$ objdump -d -j .text.show_stat --start-address=0x0 --stop-address=0x24
klp-tmp/diff/vmlinux.o
klp-tmp/diff/vmlinux.o: file format elf64-x86-64
Disassembly of section .text.show_stat:
0000000000000000 <__pfx_show_stat>:
0: 90 nop
1: 90 nop
2: 90 nop
3: 90 nop
4: 90 nop
5: 90 nop
6: 90 nop
7: 90 nop
8: 90 nop
9: 90 nop
a: 90 nop
b: 90 nop
c: 90 nop
d: 90 nop
e: 90 nop
f: 90 nop
0000000000000010 <show_stat>:
...
20: f3 0f 1e fa endbr64
When cloning the symbol, if we ensure the symbol's offset aligns
with the sh_addralign (as elf_add_data() does now):
-->8-- -->8-- -->8-- -->8-- -->8-- -->8-- -->8-- -->8-- -->8-- -->8--
diff --git a/tools/objtool/klp-diff.c b/tools/objtool/klp-diff.c
index a3198a63c2..c2c4e4968b 100644
--- a/tools/objtool/klp-diff.c
+++ b/tools/objtool/klp-diff.c
@@ -14,6 +14,7 @@
#include <objtool/util.h>
#include <arch/special.h>
+#include <linux/align.h>
#include <linux/objtool_types.h>
#include <linux/livepatch_external.h>
#include <linux/stringify.h>
@@ -560,7 +561,7 @@ static struct symbol *__clone_symbol(struct elf *elf,
struct symbol *patched_sym
}
if (!is_sec_sym(patched_sym))
- offset = sec_size(out_sec);
+ offset = ALIGN(sec_size(out_sec),
out_sec->sh.sh_addralign);
if (patched_sym->len || is_sec_sym(patched_sym)) {
void *data = NULL;
-->8-- -->8-- -->8-- -->8-- -->8-- -->8-- -->8-- -->8-- -->8-- -->8--
Results are as expected:
$ readelf --wide --symbols klp-tmp/diff/vmlinux.o | grep -E
'Ndx|\.text\.show_stat$|show_stat$|pfx_show_stat$'
Num: Value Size Type Bind Vis Ndx Name
1: 0000000000000000 16 FUNC LOCAL DEFAULT 4 __pfx_show_stat
2: 0000000000000020 2126 FUNC LOCAL DEFAULT 4 show_stat
5: 0000000000000000 0 SECTION LOCAL DEFAULT 4 .text.show_stat
$ objdump -d -j .text.show_stat --start-address=0x0 --stop-address=0x24
klp-tmp/diff/vmlinux.o
klp-tmp/diff/vmlinux.o: file format elf64-x86-64
Disassembly of section .text.show_stat:
0000000000000000 <__pfx_show_stat>:
0: 90 nop
1: 90 nop
2: 90 nop
3: 90 nop
4: 90 nop
5: 90 nop
6: 90 nop
7: 90 nop
8: 90 nop
9: 90 nop
a: 90 nop
b: 90 nop
c: 90 nop
d: 90 nop
e: 90 nop
f: 90 nop
...
0000000000000020 <show_stat>:
20: f3 0f 1e fa endbr64
LMK if you want me to update the patch in this set, or drop it here so
you can update in ("objtool/arm64: Port klp-build to arm64").
Thanks,
--
Joe