Commit | Line | Data |
---|---|---|
caf26be9 SB |
1 | #! /bin/sh |
2 | ||
3 | # Add a .gdb_index section to a file. | |
4 | ||
88b9d363 | 5 | # Copyright (C) 2010-2022 Free Software Foundation, Inc. |
caf26be9 SB |
6 | # This program is free software; you can redistribute it and/or modify |
7 | # it under the terms of the GNU General Public License as published by | |
8 | # the Free Software Foundation; either version 3 of the License, or | |
9 | # (at your option) any later version. | |
10 | # | |
11 | # This program is distributed in the hope that it will be useful, | |
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | # GNU General Public License for more details. | |
15 | # | |
16 | # You should have received a copy of the GNU General Public License | |
17 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
18 | ||
19 | # This program assumes gdb and objcopy are in $PATH. | |
20 | # If not, or you want others, pass the following in the environment | |
21 | GDB=${GDB:=gdb} | |
22 | OBJCOPY=${OBJCOPY:=objcopy} | |
2b9f6e89 | 23 | READELF=${READELF:=readelf} |
caf26be9 SB |
24 | |
25 | myname="${0##*/}" | |
26 | ||
25289ac1 JK |
27 | dwarf5="" |
28 | if [ "$1" = "-dwarf-5" ]; then | |
29 | dwarf5="$1" | |
30 | shift | |
31 | fi | |
32 | ||
caf26be9 | 33 | if test $# != 1; then |
25289ac1 | 34 | echo "usage: $myname [-dwarf-5] FILE" 1>&2 |
caf26be9 SB |
35 | exit 1 |
36 | fi | |
37 | ||
38 | file="$1" | |
39 | ||
db1f6cd6 LS |
40 | if test -L "$file"; then |
41 | if ! command -v readlink >/dev/null 2>&1; then | |
42 | echo "$myname: 'readlink' missing. Failed to follow symlink $1." 1>&2 | |
43 | exit 1 | |
44 | fi | |
45 | ||
46 | # Count number of links followed in order to detect loops. | |
47 | count=0 | |
48 | while test -L "$file"; do | |
49 | target=$(readlink "$file") | |
50 | ||
51 | case "$target" in | |
52 | /*) | |
53 | file="$target" | |
54 | ;; | |
55 | *) | |
56 | file="$(dirname "$file")/$target" | |
57 | ;; | |
58 | esac | |
59 | ||
60 | count="$((count + 1))" | |
61 | if test "$count" -gt 10; then | |
62 | echo "$myname: Detected loop while following link $file" | |
63 | exit 1 | |
64 | fi | |
65 | done | |
66 | fi | |
67 | ||
caf26be9 SB |
68 | if test ! -r "$file"; then |
69 | echo "$myname: unable to access: $file" 1>&2 | |
70 | exit 1 | |
71 | fi | |
72 | ||
73 | dir="${file%/*}" | |
74 | test "$dir" = "$file" && dir="." | |
caf26be9 | 75 | |
2b9f6e89 TV |
76 | dwz_file="" |
77 | if $READELF -S "$file" | grep -q " \.gnu_debugaltlink "; then | |
78 | dwz_file=$($READELF --string-dump=.gnu_debugaltlink "$file" \ | |
79 | | grep -A1 "'\.gnu_debugaltlink':" \ | |
80 | | tail -n +2 \ | |
81 | | sed 's/.*]//') | |
82 | dwz_file=$(echo $dwz_file) | |
83 | if $READELF -S "$dwz_file" | grep -E -q " \.(gdb_index|debug_names) "; then | |
84 | # Already has an index, skip it. | |
85 | dwz_file="" | |
86 | fi | |
87 | fi | |
88 | ||
89 | set_files () | |
90 | { | |
efe1ecd8 | 91 | fpath="$1" |
2b9f6e89 | 92 | |
efe1ecd8 LS |
93 | index4="${fpath}.gdb-index" |
94 | index5="${fpath}.debug_names" | |
95 | debugstr="${fpath}.debug_str" | |
96 | debugstrmerge="${fpath}.debug_str.merge" | |
97 | debugstrerr="${fpath}.debug_str.err" | |
2b9f6e89 TV |
98 | } |
99 | ||
100 | tmp_files= | |
101 | for f in "$file" "$dwz_file"; do | |
102 | if [ "$f" = "" ]; then | |
103 | continue | |
104 | fi | |
105 | set_files "$f" | |
106 | tmp_files="$tmp_files $index4 $index5 $debugstr $debugstrmerge $debugstrerr" | |
107 | done | |
108 | ||
109 | rm -f $tmp_files | |
110 | ||
caf26be9 | 111 | # Ensure intermediate index file is removed when we exit. |
2b9f6e89 | 112 | trap "rm -f $tmp_files" 0 |
caf26be9 SB |
113 | |
114 | $GDB --batch -nx -iex 'set auto-load no' \ | |
25289ac1 | 115 | -ex "file $file" -ex "save gdb-index $dwarf5 $dir" || { |
caf26be9 SB |
116 | # Just in case. |
117 | status=$? | |
118 | echo "$myname: gdb error generating index for $file" 1>&2 | |
119 | exit $status | |
120 | } | |
121 | ||
122 | # In some situations gdb can exit without creating an index. This is | |
123 | # not an error. | |
124 | # E.g., if $file is stripped. This behaviour is akin to stripping an | |
125 | # already stripped binary, it's a no-op. | |
126 | status=0 | |
127 | ||
2b9f6e89 TV |
128 | handle_file () |
129 | { | |
efe1ecd8 | 130 | fpath="$1" |
2b9f6e89 | 131 | |
efe1ecd8 | 132 | set_files "$fpath" |
2b9f6e89 TV |
133 | |
134 | if test -f "$index4" -a -f "$index5"; then | |
efe1ecd8 | 135 | echo "$myname: Both index types were created for $fpath" 1>&2 |
2b9f6e89 TV |
136 | status=1 |
137 | elif test -f "$index4" -o -f "$index5"; then | |
138 | if test -f "$index4"; then | |
139 | index="$index4" | |
140 | section=".gdb_index" | |
437afbb8 | 141 | else |
2b9f6e89 TV |
142 | index="$index5" |
143 | section=".debug_names" | |
144 | fi | |
145 | debugstradd=false | |
146 | debugstrupdate=false | |
147 | if test -s "$debugstr"; then | |
efe1ecd8 | 148 | if ! $OBJCOPY --dump-section .debug_str="$debugstrmerge" "$fpath" \ |
2b9f6e89 TV |
149 | /dev/null 2>$debugstrerr; then |
150 | cat >&2 $debugstrerr | |
151 | exit 1 | |
152 | fi | |
153 | if grep -q "can't dump section '.debug_str' - it does not exist" \ | |
154 | $debugstrerr; then | |
155 | debugstradd=true | |
156 | else | |
157 | debugstrupdate=true | |
158 | cat >&2 $debugstrerr | |
159 | fi | |
160 | cat "$debugstr" >>"$debugstrmerge" | |
437afbb8 | 161 | fi |
437afbb8 | 162 | |
2b9f6e89 TV |
163 | $OBJCOPY --add-section $section="$index" \ |
164 | --set-section-flags $section=readonly \ | |
165 | $(if $debugstradd; then \ | |
166 | echo --add-section .debug_str="$debugstrmerge"; \ | |
167 | echo --set-section-flags .debug_str=readonly; \ | |
168 | fi; \ | |
169 | if $debugstrupdate; then \ | |
170 | echo --update-section .debug_str="$debugstrmerge"; \ | |
171 | fi) \ | |
efe1ecd8 | 172 | "$fpath" "$fpath" |
2b9f6e89 TV |
173 | |
174 | status=$? | |
175 | else | |
efe1ecd8 | 176 | echo "$myname: No index was created for $fpath" 1>&2 |
2b9f6e89 TV |
177 | echo "$myname: [Was there no debuginfo? Was there already an index?]" \ |
178 | 1>&2 | |
179 | fi | |
180 | } | |
437afbb8 | 181 | |
2b9f6e89 TV |
182 | handle_file "$file" |
183 | if [ "$dwz_file" != "" ]; then | |
184 | handle_file "$dwz_file" | |
caf26be9 SB |
185 | fi |
186 | ||
187 | exit $status |