the first version relied on ADRP instruction scanning to find kallsyms data. worked on android16-6.12, not on android15-6.6. the ADRP window size depends on compiler inlining, which varies across kernel builds. not something you can hardcode.
the fix is simple. instead of chasing ADRP instructions, search for the
token_index structure directly in kernel .rodata. its layout is
determined by write_src() in scripts/kallsyms.c, identical in 6.6
and 6.12.
output_label("kallsyms_token_index");
for (i = 0; i < 256; i++)
printf("\t.short\t%d\n", best_idx[i]);
// best_idx[i] = byte offset into token_table
// token_index[0] = 0, strictly increasing, 256 x u16
output_label("kallsyms_offsets");
for (i = 0; i < table_cnt; i++) {
offset = table[i]->addr - relative_base;
printf("\t.long\t%#x\n", (int)offset);
}
256 consecutive u16 values, strictly increasing, starting at 0. the chance of random rodata matching that is essentially zero.
once found, kallsyms_offsets is exactly 512 bytes after token_index
(plus .balign 8 padding). the search stops naturally when
copy_from_kernel_nofault hits unmapped pages. we start scanning at
kernel_base + 1MB, which is well inside .text.
kernel_base = (unsigned long)&sprint_symbol & ~0x1FFFFFULL;
no ADRP scanning, no BL chain, no window sizes to guess. simple.
sorted=126031
SCT MATCH, addr->name MATCH, name->addr MATCH
that is it.
Thanks to 汐の月 for providing the device for GKI 6.6 testing.