]>
Commit | Line | Data |
---|---|---|
51a5ef0f PS |
1 | http://sourceware.org/ml/gdb-patches/2010-07/msg00237.html |
2 | Subject: [patch] Fix regression on prelinked executables | |
3 | ||
4 | Hi, | |
5 | ||
6 | there is a regression since gdb-7.0 for a combination of: | |
7 | * prelinked | |
8 | * main executable | |
9 | * using separate debug info | |
10 | * using copy relocations | |
11 | ||
12 | It is since a patch for both PIE and (AFAIK) OSX support: | |
13 | [commit] syms_from_objfile: Relativize also MAINLINE | |
14 | http://sourceware.org/ml/gdb-patches/2010-01/msg00080.html | |
15 | ||
16 | which started to use problematic addr_info_make_relative even for main | |
17 | executables. prelink<->gdb discussion at: | |
18 | https://bugzilla.redhat.com/show_bug.cgi?id=614659 | |
19 | ||
20 | Currently in the unfortunately executables GDB has invalid displcement for | |
21 | symbols in .bss: | |
22 | int bssvar, *bssvarp = &bssvar; | |
23 | (gdb) p &bssvar | |
24 | $1 = (int *) 0x600b54 | |
25 | (gdb) p bssvarp | |
26 | $2 = (int *) 0x600b50 | |
27 | ||
28 | <abstract-higher-point-of-view> | |
29 | addr_info_make_relative could just simply subtract entry point address and | |
30 | provide single CORE_ADDR objfile->offset (instead of the current | |
31 | section_offsets array with offsets specific for each section). Linux systems | |
32 | use always single offset for the whole objfile. AFAIK these per-section | |
33 | offsets are there for some embedded targets. Curiously GDB already uses at | |
34 | many places | |
35 | baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); | |
36 | instead of using offset for the appropriate section at that place and nobody | |
37 | complains. | |
38 | </abstract-higher-point-of-view> | |
39 | ||
40 | No regressions on {x86_64,x86_64-m32,i686}-fedora13-linux-gnu. | |
41 | ||
42 | Proposing for the gdb-7.2 branch. I had problems fixing up my crashing X. | |
43 | ||
44 | ||
45 | Thanks, | |
46 | Jan | |
47 | ||
48 | ||
49 | gdb/ | |
50 | 2010-07-15 Jan Kratochvil <jan.kratochvil@redhat.com> | |
51 | ||
52 | * symfile.c (addr_section_name): New function. | |
53 | (addrs_section_compar): Use it. | |
54 | (addr_info_make_relative): Use it. Move variable sect_name into a more | |
55 | inner block. Make ".dynbss" and ".sdynbss" checks more strict. | |
56 | ||
57 | gdb/testsuite/ | |
58 | 2010-07-15 Jan Kratochvil <jan.kratochvil@redhat.com> | |
59 | ||
60 | * gdb.base/prelink-lib.c (copyreloc): New initialized variable. | |
61 | * gdb.base/prelink.c (copyreloc, bssvar, bssvarp): New variables. | |
62 | (main): Use copyreloc. | |
63 | * gdb.base/prelink.exp (split debug of executable) | |
64 | (.dynbss vs. .bss address shift): New tests. | |
65 | ||
66 | --- a/gdb/symfile.c | |
67 | +++ b/gdb/symfile.c | |
68 | @@ -547,6 +547,23 @@ relative_addr_info_to_section_offsets (struct section_offsets *section_offsets, | |
69 | } | |
70 | } | |
71 | ||
72 | +/* Transform section name S for a name comparison. prelink can split section | |
73 | + `.bss' into two sections `.dynbss' and `.bss' (in this order). Similarly | |
74 | + prelink can split `.sbss' into `.sdynbss' and `.sbss'. Use virtual address | |
75 | + of the new `.dynbss' (`.sdynbss') section as the adjacent new `.bss' | |
76 | + (`.sbss') section has invalid (increased) virtual address. */ | |
77 | + | |
78 | +static const char * | |
79 | +addr_section_name (const char *s) | |
80 | +{ | |
81 | + if (strcmp (s, ".dynbss") == 0) | |
82 | + return ".bss"; | |
83 | + if (strcmp (s, ".sdynbss") == 0) | |
84 | + return ".sbss"; | |
85 | + | |
86 | + return s; | |
87 | +} | |
88 | + | |
89 | /* qsort comparator for addrs_section_sort. Sort entries in ascending order by | |
90 | their (name, sectindex) pair. sectindex makes the sort by name stable. */ | |
91 | ||
92 | @@ -557,7 +574,7 @@ addrs_section_compar (const void *ap, const void *bp) | |
93 | const struct other_sections *b = *((struct other_sections **) bp); | |
94 | int retval, a_idx, b_idx; | |
95 | ||
96 | - retval = strcmp (a->name, b->name); | |
97 | + retval = strcmp (addr_section_name (a->name), addr_section_name (b->name)); | |
98 | if (retval) | |
99 | return retval; | |
100 | ||
101 | @@ -641,14 +658,16 @@ addr_info_make_relative (struct section_addr_info *addrs, bfd *abfd) | |
102 | ||
103 | while (*addrs_sorted) | |
104 | { | |
105 | - const char *sect_name = (*addrs_sorted)->name; | |
106 | + const char *sect_name = addr_section_name ((*addrs_sorted)->name); | |
107 | ||
108 | while (*abfd_addrs_sorted | |
109 | - && strcmp ((*abfd_addrs_sorted)->name, sect_name) < 0) | |
110 | + && strcmp (addr_section_name ((*abfd_addrs_sorted)->name), | |
111 | + sect_name) < 0) | |
112 | abfd_addrs_sorted++; | |
113 | ||
114 | if (*abfd_addrs_sorted | |
115 | - && strcmp ((*abfd_addrs_sorted)->name, sect_name) == 0) | |
116 | + && strcmp (addr_section_name ((*abfd_addrs_sorted)->name), | |
117 | + sect_name) == 0) | |
118 | { | |
119 | int index_in_addrs; | |
120 | ||
121 | @@ -676,7 +695,6 @@ addr_info_make_relative (struct section_addr_info *addrs, bfd *abfd) | |
122 | ||
123 | for (i = 0; i < addrs->num_sections && addrs->other[i].name; i++) | |
124 | { | |
125 | - const char *sect_name = addrs->other[i].name; | |
126 | struct other_sections *sect = addrs_to_abfd_addrs[i]; | |
127 | ||
128 | if (sect) | |
129 | @@ -694,6 +712,9 @@ addr_info_make_relative (struct section_addr_info *addrs, bfd *abfd) | |
130 | } | |
131 | else | |
132 | { | |
133 | + /* addr_section_name transformation is not used for SECT_NAME. */ | |
134 | + const char *sect_name = addrs->other[i].name; | |
135 | + | |
136 | /* This section does not exist in ABFD, which is normally | |
137 | unexpected and we want to issue a warning. | |
138 | ||
139 | @@ -704,12 +725,20 @@ addr_info_make_relative (struct section_addr_info *addrs, bfd *abfd) | |
140 | a warning. Shared libraries contain just the section | |
141 | ".gnu.liblist" but it is not marked as loadable there. There is | |
142 | no other way to identify them than by their name as the sections | |
143 | - created by prelink have no special flags. */ | |
144 | + created by prelink have no special flags. | |
145 | + | |
146 | + For the sections `.bss' and `.sbss' see addr_section_name. */ | |
147 | ||
148 | if (!(strcmp (sect_name, ".gnu.liblist") == 0 | |
149 | || strcmp (sect_name, ".gnu.conflict") == 0 | |
150 | - || strcmp (sect_name, ".dynbss") == 0 | |
151 | - || strcmp (sect_name, ".sdynbss") == 0)) | |
152 | + || (strcmp (sect_name, ".bss") == 0 | |
153 | + && i > 0 | |
154 | + && strcmp (addrs->other[i - 1].name, ".dynbss") == 0 | |
155 | + && addrs_to_abfd_addrs[i - 1] != NULL) | |
156 | + || (strcmp (sect_name, ".sbss") == 0 | |
157 | + && i > 0 | |
158 | + && strcmp (addrs->other[i - 1].name, ".sdynbss") == 0 | |
159 | + && addrs_to_abfd_addrs[i - 1] != NULL))) | |
160 | warning (_("section %s not found in %s"), sect_name, | |
161 | bfd_get_filename (abfd)); | |
162 | ||
163 | --- a/gdb/testsuite/gdb.base/prelink-lib.c | |
164 | +++ b/gdb/testsuite/gdb.base/prelink-lib.c | |
165 | @@ -16,6 +16,8 @@ | |
166 | along with this program. If not, see <http://www.gnu.org/licenses/>. | |
167 | */ | |
168 | ||
169 | +int copyreloc = 1; | |
170 | + | |
171 | int | |
172 | g (void (*p)(void)) | |
173 | { | |
174 | --- a/gdb/testsuite/gdb.base/prelink.c | |
175 | +++ b/gdb/testsuite/gdb.base/prelink.c | |
176 | @@ -18,6 +18,11 @@ | |
177 | ||
178 | #include <stdio.h> | |
179 | ||
180 | +extern int copyreloc; | |
181 | + | |
182 | +/* Test GDB itself finds `&bssvar' right. */ | |
183 | +static int bssvar, *bssvarp = &bssvar; | |
184 | + | |
185 | extern void (*h (void)) (void (*)(void)); | |
186 | ||
187 | int | |
188 | @@ -25,5 +30,6 @@ main (void) | |
189 | { | |
190 | void (*f) (void (*)(void)) = h (); | |
191 | printf ("%p\n", f); | |
192 | + printf ("%d\n", copyreloc); | |
193 | f (0); | |
194 | } | |
195 | --- a/gdb/testsuite/gdb.base/prelink.exp | |
196 | +++ b/gdb/testsuite/gdb.base/prelink.exp | |
197 | @@ -57,6 +57,13 @@ if {$prelink_args == ""} { | |
198 | return -1 | |
199 | } | |
200 | ||
201 | +set test "split debug of executable" | |
202 | +if [gdb_gnu_strip_debug $binfile] { | |
203 | + fail $test | |
204 | +} else { | |
205 | + pass $test | |
206 | +} | |
207 | + | |
208 | if ![prelink_yes $prelink_args] { | |
209 | # Maybe we don't have prelink. | |
210 | return -1 | |
211 | @@ -105,3 +112,5 @@ clean_restart $executable | |
212 | gdb_test_no_output "set verbose on" | |
213 | ||
214 | gdb_test "core-file $objdir/$subdir/prelink.core" "Using PIC \\(Position Independent Code\\) prelink displacement 0x\[^0\]\[0-9a-f\]* for \[^\r\n\]*[file tail ${libfile}].*" "seen displacement message" | |
215 | + | |
216 | +gdb_test "p &bssvar == bssvarp" " = 1" ".dynbss vs. .bss address shift" | |
217 |