Skip to content

Commit c494ade

Browse files
npigginmpe
authored andcommitted
powerpc/64: Tool to check head sections location sanity
Use a tool to check that the location of "fixed sections" are where we expected them to be, which catches cases the linker script can't (stubs being added to start of .text section), and which ends up being neater. Sample output: ERROR: start_text address is c000000000008100, should be c000000000008000 ERROR: see comments in arch/powerpc/tools/head_check.sh Signed-off-by: Nicholas Piggin <[email protected]> [mpe: Fold in fix from Nick for 4.6 era toolchains] Signed-off-by: Michael Ellerman <[email protected]>
1 parent 951eede commit c494ade

File tree

4 files changed

+87
-25
lines changed

4 files changed

+87
-25
lines changed

arch/powerpc/Makefile.postlink

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ __archpost:
1010
-include include/config/auto.conf
1111
include scripts/Kbuild.include
1212

13+
quiet_cmd_head_check = CHKHEAD $@
14+
cmd_head_check = $(CONFIG_SHELL) $(srctree)/arch/powerpc/tools/head_check.sh "$(NM)" "$@"
15+
1316
quiet_cmd_relocs_check = CHKREL $@
1417
ifdef CONFIG_PPC_BOOK3S_64
1518
cmd_relocs_check = \
@@ -24,6 +27,9 @@ endif
2427

2528
vmlinux: FORCE
2629
@true
30+
ifdef CONFIG_PPC64
31+
$(call cmd,head_check)
32+
endif
2733
ifdef CONFIG_RELOCATABLE
2834
$(call if_changed,relocs_check)
2935
endif
@@ -32,7 +38,7 @@ endif
3238
@true
3339

3440
clean:
35-
@true
41+
rm -f .tmp_symbols.txt
3642

3743
PHONY += FORCE clean
3844

arch/powerpc/include/asm/head-64.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@
4949
* CLOSE_FIXED_SECTION() or elsewhere, there may be something
5050
* unexpected being added there. Remove the '. = x_len' line, rebuild, and
5151
* check what is pushing the section down.
52-
* - If the build dies in linking, check arch/powerpc/kernel/vmlinux.lds.S
53-
* for instructions.
52+
* - If the build dies in linking, check arch/powerpc/tools/head_check.sh
53+
* comments.
5454
* - If the kernel crashes or hangs in very early boot, it could be linker
5555
* stubs at the start of the main text.
5656
*/

arch/powerpc/kernel/vmlinux.lds.S

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -58,44 +58,22 @@ SECTIONS
5858
#ifdef CONFIG_PPC64
5959
KEEP(*(.head.text.first_256B));
6060
#ifdef CONFIG_PPC_BOOK3E
61-
# define END_FIXED 0x100
6261
#else
6362
KEEP(*(.head.text.real_vectors));
6463
*(.head.text.real_trampolines);
6564
KEEP(*(.head.text.virt_vectors));
6665
*(.head.text.virt_trampolines);
6766
# if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV)
6867
KEEP(*(.head.data.fwnmi_page));
69-
# define END_FIXED 0x8000
70-
# else
71-
# define END_FIXED 0x7000
7268
# endif
7369
#endif
74-
ASSERT((. == END_FIXED), "vmlinux.lds.S: fixed section overflow error");
7570
#else /* !CONFIG_PPC64 */
7671
HEAD_TEXT
7772
#endif
7873
} :kernel
7974

8075
__head_end = .;
8176

82-
/*
83-
* If the build dies here, it's likely code in head_64.S is referencing
84-
* labels it can't reach, and the linker inserting stubs without the
85-
* assembler's knowledge. To debug, remove the above assert and
86-
* rebuild. Look for branch stubs in the fixed section region.
87-
*
88-
* Linker stub generation could be allowed in "trampoline"
89-
* sections if absolutely necessary, but this would require
90-
* some rework of the fixed sections. Before resorting to this,
91-
* consider references that have sufficient addressing range,
92-
* (e.g., hand coded trampolines) so the linker does not have
93-
* to add stubs.
94-
*
95-
* Linker stubs at the top of the main text section are currently not
96-
* detected, and will result in a crash at boot due to offsets being
97-
* wrong.
98-
*/
9977
#ifdef CONFIG_PPC64
10078
/*
10179
* BLOCK(0) overrides the default output section alignment because

arch/powerpc/tools/head_check.sh

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# Copyright © 2016 IBM Corporation
2+
3+
# This program is free software; you can redistribute it and/or
4+
# modify it under the terms of the GNU General Public License
5+
# as published by the Free Software Foundation; either version
6+
# 2 of the License, or (at your option) any later version.
7+
8+
# This script checks the head of a vmlinux for linker stubs that
9+
# break our placement of fixed-location code for 64-bit.
10+
11+
# based on relocs_check.pl
12+
# Copyright © 2009 IBM Corporation
13+
14+
# NOTE!
15+
#
16+
# If the build dies here, it's likely code in head_64.S/exception-64*.S or
17+
# nearby, is branching to labels it can't reach directly, which results in the
18+
# linker inserting branch stubs. This can move code around in ways that break
19+
# the fixed section calculations (head-64.h). To debug this, disassemble the
20+
# vmlinux and look for branch stubs (long_branch, plt_branch, etc.) in the
21+
# fixed section region (0 - 0x8000ish). Check what code is calling those stubs,
22+
# and perhaps change so a direct branch can reach.
23+
#
24+
# A ".linker_stub_catch" section is used to catch some stubs generated by
25+
# early .text code, which tend to get placed at the start of the section.
26+
# If there are too many such stubs, they can overflow this section. Expanding
27+
# it may help (or reducing the number of stub branches).
28+
#
29+
# Linker stubs use the TOC pointer, so even if fixed section code could
30+
# tolerate them being inserted into head code, they can't be allowed in low
31+
# level entry code (boot, interrupt vectors, etc) until r2 is set up. This
32+
# could cause the kernel to die in early boot.
33+
34+
# Turn this on if you want more debug output:
35+
# set -x
36+
37+
if [ $# -lt 2 ]; then
38+
echo "$0 [path to nm] [path to vmlinux]" 1>&2
39+
exit 1
40+
fi
41+
42+
# Have Kbuild supply the path to nm so we handle cross compilation.
43+
nm="$1"
44+
vmlinux="$2"
45+
46+
# gcc-4.6-era toolchain make _stext an A (absolute) symbol rather than T
47+
$nm "$vmlinux" | grep -e " [TA] _stext$" -e " t start_first_256B$" -e " a text_start$" -e " t start_text$" -m4 > .tmp_symbols.txt
48+
49+
50+
vma=$(cat .tmp_symbols.txt | grep -e " [TA] _stext$" | cut -d' ' -f1)
51+
52+
expected_start_head_addr=$vma
53+
54+
start_head_addr=$(cat .tmp_symbols.txt | grep " t start_first_256B$" | cut -d' ' -f1)
55+
56+
if [ "$start_head_addr" != "$expected_start_head_addr" ]; then
57+
echo "ERROR: head code starts at $start_head_addr, should be $expected_start_head_addr"
58+
echo "ERROR: try to enable LD_HEAD_STUB_CATCH config option"
59+
echo "ERROR: see comments in arch/powerpc/tools/head_check.sh"
60+
61+
exit 1
62+
fi
63+
64+
top_vma=$(echo $vma | cut -d'0' -f1)
65+
66+
expected_start_text_addr=$(cat .tmp_symbols.txt | grep " a text_start$" | cut -d' ' -f1 | sed "s/^0/$top_vma/")
67+
68+
start_text_addr=$(cat .tmp_symbols.txt | grep " t start_text$" | cut -d' ' -f1)
69+
70+
if [ "$start_text_addr" != "$expected_start_text_addr" ]; then
71+
echo "ERROR: start_text address is $start_text_addr, should be $expected_start_text_addr"
72+
echo "ERROR: try to enable LD_HEAD_STUB_CATCH config option"
73+
echo "ERROR: see comments in arch/powerpc/tools/head_check.sh"
74+
75+
exit 1
76+
fi
77+
78+
rm -f .tmp_symbols.txt

0 commit comments

Comments
 (0)