xref: /linux/tools/objtool/tests/generic/test-sympos-vmlinux.sh (revision 5b6dca02b3e2254d2fd5706d76d7ab4610a67296)
1*1a50e18bSSong Liu#!/bin/bash
2*1a50e18bSSong Liu# SPDX-License-Identifier: GPL-2.0
3*1a50e18bSSong Liu#
4*1a50e18bSSong Liu# sympos for vmlinux, which is resolved differently from sympos for a module.
5*1a50e18bSSong Liu#
6*1a50e18bSSong Liu# A module's .ko preserves symbol table order, so klp diff can count -- that is
7*1a50e18bSSong Liu# what test-sympos covers.  vmlinux cannot be counted: the final link reorders
8*1a50e18bSSong Liu# sub-sections, so the order in vmlinux.o is not the order the running kernel
9*1a50e18bSSong Liu# has.  klp diff bridges that with .klp.symid, a table of { id, address }
10*1a50e18bSSong Liu# emitted into vmlinux.o whose addresses the linker resolves, read back out of
11*1a50e18bSSong Liu# the linked vmlinux.
12*1a50e18bSSong Liu#
13*1a50e18bSSong Liu# Getting it wrong points the relocation at a different symbol of the same
14*1a50e18bSSong Liu# name.  Nothing fails to build or load; the patched code uses the wrong
15*1a50e18bSSong Liu# object.
16*1a50e18bSSong Liu#
17*1a50e18bSSong Liu# The fixture is arranged so the two answers differ: the static that comes
18*1a50e18bSSong Liu# first in the symbol table is placed at the *higher* address, so counting
19*1a50e18bSSong Liu# gives 1 and reading the linked image gives 2.  Without that, both paths agree
20*1a50e18bSSong Liu# and the test cannot tell them apart.
21*1a50e18bSSong Liu
22*1a50e18bSSong Liu. "$(dirname "$0")/../lib.sh"
23*1a50e18bSSong Liu
24*1a50e18bSSong Liusetup
25*1a50e18bSSong Liu
26*1a50e18bSSong Liu# use_a's static sorts last by section name, use_b's first.  Only use_a is
27*1a50e18bSSong Liu# patched, so exactly one sympos comes out.
28*1a50e18bSSong Liubuild_one sympos_vmlinux.c orig_a.o    -DFUNC_NAME=use_a -DVARSEC='".data.zzz"'
29*1a50e18bSSong Liubuild_one sympos_vmlinux.c patched_a.o -DFUNC_NAME=use_a -DVARSEC='".data.zzz"' -DPATCHED
30*1a50e18bSSong Liubuild_one sympos_vmlinux.c b.o         -DFUNC_NAME=use_b -DVARSEC='".data.aaa"' -DNO_MODINFO
31*1a50e18bSSong Liu
32*1a50e18bSSong Liumake_vmlinux_pair "$workdir/orig_a.o" "$workdir/b.o" \
33*1a50e18bSSong Liu	       -- "$workdir/patched_a.o" "$workdir/b.o"
34*1a50e18bSSong Liu
35*1a50e18bSSong Liu[ "$(count_input_symbols vmlinux.o dup_counter)" = 2 ] ||
36*1a50e18bSSong Liu	fail "fixture did not produce two dup_counter symbols"
37*1a50e18bSSong Liuhas_input_section vmlinux.o .klp.symid ||
38*1a50e18bSSong Liu	fail "objtool --klp-symids emitted no .klp.symid table"
39*1a50e18bSSong Liuhas_input_section vmlinux .klp.symid ||
40*1a50e18bSSong Liu	fail ".klp.symid did not survive the link"
41*1a50e18bSSong Liu
42*1a50e18bSSong Liu# The premise: symbol table order and address order must disagree, or the test
43*1a50e18bSSong Liu# proves nothing.
44*1a50e18bSSong Liufirst_addr="$(in_symbols vmlinux | awk '$8 == "dup_counter" { print $2; exit }')"
45*1a50e18bSSong Liulow_addr="$(in_symbols vmlinux | awk '$8 == "dup_counter" { print $2 }' | sort | head -1)"
46*1a50e18bSSong Liu[ "$first_addr" != "$low_addr" ] ||
47*1a50e18bSSong Liu	probe_skip "linker did not reorder the two statics"
48*1a50e18bSSong Liu
49*1a50e18bSSong Liuassert_input_symbol dup_counter
50*1a50e18bSSong Liurun_diff
51*1a50e18bSSong Liu
52*1a50e18bSSong Liu# Address order says 2.  Counting symbol table order would say 1.
53*1a50e18bSSong Liuassert_klp_sympos dup_counter 2
54*1a50e18bSSong Liuout_symbols | grep -q 'dup_counter,1' &&
55*1a50e18bSSong Liu	fail "sympos 1 emitted: counted symbol table order instead of reading the linked vmlinux"
56*1a50e18bSSong Liu
57*1a50e18bSSong Liupass "vmlinux sympos taken from the linked image, not from symbol table order"
58