]>
Commit | Line | Data |
---|---|---|
ab050a48 BZ |
1 | gdb/ |
2 | 2009-11-24 Jan Kratochvil <jan.kratochvil@redhat.com> | |
3 | ||
4 | Transparent GNU-IFUNCs support. | |
5 | * elfread.c (record_minimal_symbol): Apply also for mst_text_gnu_ifunc. | |
6 | (elf_symtab_read): Set also mst_text_gnu_ifunc. | |
7 | * gdbtypes.c (init_type): Support TYPE_FLAG_GNU_IFUNC. | |
8 | (gdbtypes_post_init): Initialize builtin_func_func_ptr. | |
9 | (objfile_type): Initialize nodebug_text_gnu_ifunc_symbol. | |
10 | * gdbtypes.h (enum type_flag_value <TYPE_FLAG_GNU_IFUNC>) | |
11 | (TYPE_GNU_IFUNC, struct main_type <flag_gnu_ifunc>) | |
12 | (struct builtin_type <builtin_func_func_ptr>) | |
13 | (struct objfile_type <nodebug_text_gnu_ifunc_symbol>): New. | |
14 | * infcall.c (find_function_addr <TYPE_GNU_IFUNC (ftype)>): New. | |
15 | * minsyms.c (lookup_minimal_symbol_text, prim_record_minimal_symbol) | |
16 | (find_solib_trampoline_target): Support also mst_text_gnu_ifunc. | |
17 | (in_gnu_ifunc_stub): New. | |
18 | * parse.c (write_exp_msymbol <mst_text_gnu_ifunc>): New. | |
19 | * solib-svr4.c (svr4_in_dynsym_resolve_code): Call also | |
20 | in_gnu_ifunc_stub. | |
21 | * symmisc.c (dump_msymbols <mst_text_gnu_ifunc>): New. | |
22 | * symtab.c (search_symbols): Support also mst_text_gnu_ifunc. | |
23 | * symtab.h (enum minimal_symbol_type <mst_text_gnu_ifunc>) | |
24 | (in_gnu_ifunc_stub): New. | |
25 | * linespec.c: Include infcall.h. | |
26 | (minsym_found <MSYMBOL_TYPE (msymbol) == mst_text_gnu_ifunc>): New. | |
27 | ||
28 | gdb/testsuite/ | |
29 | 2009-11-24 Jan Kratochvil <jan.kratochvil@redhat.com> | |
30 | ||
31 | Transparent GNU-IFUNCs support. | |
32 | * gdb.base/gnu-ifunc-lib.c, gdb.base/gnu-ifunc.c, | |
33 | gdb.base/gnu-ifunc.exp: New. | |
34 | ||
35 | Index: gdb-7.0/gdb/elfread.c | |
36 | =================================================================== | |
37 | --- gdb-7.0.orig/gdb/elfread.c 2009-11-25 10:24:45.000000000 +0100 | |
38 | +++ gdb-7.0/gdb/elfread.c 2009-11-25 10:25:50.000000000 +0100 | |
39 | @@ -168,7 +168,8 @@ record_minimal_symbol (char *name, CORE_ | |
40 | { | |
41 | struct gdbarch *gdbarch = get_objfile_arch (objfile); | |
42 | ||
43 | - if (ms_type == mst_text || ms_type == mst_file_text) | |
44 | + if (ms_type == mst_text || ms_type == mst_file_text | |
45 | + || ms_type == mst_text_gnu_ifunc) | |
46 | address = gdbarch_smash_text_address (gdbarch, address); | |
47 | ||
48 | return prim_record_minimal_symbol_and_info | |
49 | @@ -373,7 +374,10 @@ elf_symtab_read (struct objfile *objfile | |
50 | { | |
51 | if (sym->flags & (BSF_GLOBAL | BSF_WEAK)) | |
52 | { | |
53 | - ms_type = mst_text; | |
54 | + if (sym->flags & BSF_GNU_INDIRECT_FUNCTION) | |
55 | + ms_type = mst_text_gnu_ifunc; | |
56 | + else | |
57 | + ms_type = mst_text; | |
58 | } | |
59 | else if ((sym->name[0] == '.' && sym->name[1] == 'L') | |
60 | || ((sym->flags & BSF_LOCAL) | |
61 | Index: gdb-7.0/gdb/gdbtypes.c | |
62 | =================================================================== | |
63 | --- gdb-7.0.orig/gdb/gdbtypes.c 2009-11-25 10:24:47.000000000 +0100 | |
64 | +++ gdb-7.0/gdb/gdbtypes.c 2009-11-25 10:24:56.000000000 +0100 | |
65 | @@ -1904,6 +1904,8 @@ init_type (enum type_code code, int leng | |
66 | TYPE_NOTTEXT (type) = 1; | |
67 | if (flags & TYPE_FLAG_FIXED_INSTANCE) | |
68 | TYPE_FIXED_INSTANCE (type) = 1; | |
69 | + if (flags & TYPE_FLAG_GNU_IFUNC) | |
70 | + TYPE_GNU_IFUNC (type) = 1; | |
71 | ||
72 | if (name) | |
73 | TYPE_NAME (type) = obsavestring (name, strlen (name), | |
74 | @@ -3762,6 +3764,8 @@ gdbtypes_post_init (struct gdbarch *gdba | |
75 | = lookup_pointer_type (builtin_type->builtin_void); | |
76 | builtin_type->builtin_func_ptr | |
77 | = lookup_pointer_type (lookup_function_type (builtin_type->builtin_void)); | |
78 | + builtin_type->builtin_func_func_ptr | |
79 | + = lookup_pointer_type (lookup_function_type (builtin_type->builtin_func_ptr)); | |
80 | ||
81 | /* This type represents a GDB internal function. */ | |
82 | builtin_type->internal_fn | |
83 | @@ -3878,6 +3882,11 @@ objfile_type (struct objfile *objfile) | |
84 | "<text variable, no debug info>", objfile); | |
85 | TYPE_TARGET_TYPE (objfile_type->nodebug_text_symbol) | |
86 | = objfile_type->builtin_int; | |
87 | + objfile_type->nodebug_text_gnu_ifunc_symbol | |
88 | + = init_type (TYPE_CODE_FUNC, 1, TYPE_FLAG_GNU_IFUNC, | |
89 | + "<text gnu-ifunc variable, no debug info>", objfile); | |
90 | + TYPE_TARGET_TYPE (objfile_type->nodebug_text_gnu_ifunc_symbol) | |
91 | + = objfile_type->nodebug_text_symbol; | |
92 | objfile_type->nodebug_data_symbol | |
93 | = init_type (TYPE_CODE_INT, | |
94 | gdbarch_int_bit (gdbarch) / HOST_CHAR_BIT, 0, | |
95 | Index: gdb-7.0/gdb/gdbtypes.h | |
96 | =================================================================== | |
97 | --- gdb-7.0.orig/gdb/gdbtypes.h 2009-11-25 10:24:48.000000000 +0100 | |
98 | +++ gdb-7.0/gdb/gdbtypes.h 2009-11-25 10:25:17.000000000 +0100 | |
99 | @@ -187,6 +187,7 @@ enum type_flag_value | |
100 | TYPE_FLAG_FIXED_INSTANCE = (1 << 15), | |
101 | TYPE_FLAG_STUB_SUPPORTED = (1 << 16), | |
102 | TYPE_FLAG_NOTTEXT = (1 << 17), | |
103 | + TYPE_FLAG_GNU_IFUNC = (1 << 18), | |
104 | ||
105 | /* Used for error-checking. */ | |
106 | TYPE_FLAG_MIN = TYPE_FLAG_UNSIGNED | |
107 | @@ -292,6 +293,12 @@ enum type_instance_flag_value | |
108 | ||
109 | #define TYPE_NOTTEXT(t) (TYPE_MAIN_TYPE (t)->flag_nottext) | |
110 | ||
111 | +/* Currently used only for TYPE_CODE_FUNC where specifies the real function | |
112 | + address is returned by this function call. TYPE_TARGET_TYPE determines the | |
113 | + final returned function type to be presented to user. */ | |
114 | + | |
115 | +#define TYPE_GNU_IFUNC(t) (TYPE_MAIN_TYPE (t)->flag_gnu_ifunc) | |
116 | + | |
117 | /* Type owner. If TYPE_OBJFILE_OWNED is true, the type is owned by | |
118 | the objfile retrieved as TYPE_OBJFILE. Otherweise, the type is | |
119 | owned by an architecture; TYPE_OBJFILE is NULL in this case. */ | |
120 | @@ -427,6 +434,7 @@ struct main_type | |
121 | unsigned int flag_vector : 1; | |
122 | unsigned int flag_stub_supported : 1; | |
123 | unsigned int flag_nottext : 1; | |
124 | + unsigned int flag_gnu_ifunc : 1; | |
125 | unsigned int flag_fixed_instance : 1; | |
126 | unsigned int flag_objfile_owned : 1; | |
127 | unsigned int flag_discardable : 1; | |
128 | @@ -1144,6 +1152,10 @@ struct builtin_type | |
129 | (*) () can server as a generic function pointer. */ | |
130 | struct type *builtin_func_ptr; | |
131 | ||
132 | + /* `pointer to function returning pointer to function (returning void)' type. | |
133 | + The final void return type is not significant for it. */ | |
134 | + struct type *builtin_func_func_ptr; | |
135 | + | |
136 | ||
137 | /* Special-purpose types. */ | |
138 | ||
139 | @@ -1186,6 +1198,7 @@ struct objfile_type | |
140 | ||
141 | /* Types used for symbols with no debug information. */ | |
142 | struct type *nodebug_text_symbol; | |
143 | + struct type *nodebug_text_gnu_ifunc_symbol; | |
144 | struct type *nodebug_data_symbol; | |
145 | struct type *nodebug_unknown_symbol; | |
146 | struct type *nodebug_tls_symbol; | |
147 | Index: gdb-7.0/gdb/infcall.c | |
148 | =================================================================== | |
149 | --- gdb-7.0.orig/gdb/infcall.c 2009-11-25 10:24:45.000000000 +0100 | |
150 | +++ gdb-7.0/gdb/infcall.c 2009-11-25 10:24:56.000000000 +0100 | |
151 | @@ -286,6 +286,27 @@ find_function_addr (struct value *functi | |
152 | else | |
153 | error (_("Invalid data type for function to be called.")); | |
154 | ||
155 | + if (TYPE_GNU_IFUNC (ftype)) | |
156 | + { | |
157 | + struct type *func_func_ptr; | |
158 | + | |
159 | + funaddr += gdbarch_deprecated_function_start_offset (gdbarch); | |
160 | + | |
161 | + /* Cast FUNADDR to drop TYPE_GNU_IFUNC and being able to call gnu-ifunc | |
162 | + FUNADDR without causing deadlock by this block of code. */ | |
163 | + | |
164 | + func_func_ptr = builtin_type (gdbarch)->builtin_func_func_ptr; | |
165 | + function = value_from_pointer (func_func_ptr, funaddr); | |
166 | + | |
167 | + /* gnu-ifuncs have no arguments. */ | |
168 | + function = call_function_by_hand (function, 0, NULL); | |
169 | + | |
170 | + funaddr = value_as_address (function); | |
171 | + | |
172 | + /* This is `int' as the return type of the final function. */ | |
173 | + value_type = TYPE_TARGET_TYPE (value_type); | |
174 | + } | |
175 | + | |
176 | if (retval_type != NULL) | |
177 | *retval_type = value_type; | |
178 | return funaddr + gdbarch_deprecated_function_start_offset (gdbarch); | |
179 | Index: gdb-7.0/gdb/linespec.c | |
180 | =================================================================== | |
181 | --- gdb-7.0.orig/gdb/linespec.c 2009-11-25 10:24:45.000000000 +0100 | |
182 | +++ gdb-7.0/gdb/linespec.c 2009-11-25 10:24:56.000000000 +0100 | |
183 | @@ -40,6 +40,7 @@ | |
184 | #include "interps.h" | |
185 | #include "mi/mi-cmds.h" | |
186 | #include "target.h" | |
187 | +#include "infcall.h" | |
188 | ||
189 | /* We share this one with symtab.c, but it is not exported widely. */ | |
190 | ||
191 | @@ -1875,6 +1876,22 @@ minsym_found (int funfirstline, struct m | |
192 | pc = gdbarch_convert_from_func_ptr_addr (gdbarch, | |
193 | values.sals[0].pc, | |
194 | ¤t_target); | |
195 | + | |
196 | + /* Call gnu-ifunc to resolve breakpoint at its returned function. */ | |
197 | + if (MSYMBOL_TYPE (msymbol) == mst_text_gnu_ifunc) | |
198 | + { | |
199 | + struct type *func_func_ptr; | |
200 | + struct value *function; | |
201 | + | |
202 | + func_func_ptr = builtin_type (gdbarch)->builtin_func_func_ptr; | |
203 | + function = value_from_pointer (func_func_ptr, pc); | |
204 | + | |
205 | + /* gnu-ifuncs have no arguments. */ | |
206 | + function = call_function_by_hand (function, 0, NULL); | |
207 | + | |
208 | + pc = value_as_address (function); | |
209 | + } | |
210 | + | |
211 | if (pc != values.sals[0].pc) | |
212 | values.sals[0] = find_pc_sect_line (pc, NULL, 0); | |
213 | ||
214 | Index: gdb-7.0/gdb/minsyms.c | |
215 | =================================================================== | |
216 | --- gdb-7.0.orig/gdb/minsyms.c 2009-11-25 10:24:47.000000000 +0100 | |
217 | +++ gdb-7.0/gdb/minsyms.c 2009-11-25 10:24:56.000000000 +0100 | |
218 | @@ -331,8 +331,9 @@ lookup_minimal_symbol_text (const char * | |
219 | msymbol = msymbol->hash_next) | |
220 | { | |
221 | if (strcmp (SYMBOL_LINKAGE_NAME (msymbol), name) == 0 && | |
222 | - (MSYMBOL_TYPE (msymbol) == mst_text || | |
223 | - MSYMBOL_TYPE (msymbol) == mst_file_text)) | |
224 | + (MSYMBOL_TYPE (msymbol) == mst_text | |
225 | + || MSYMBOL_TYPE (msymbol) == mst_text_gnu_ifunc | |
226 | + || MSYMBOL_TYPE (msymbol) == mst_file_text)) | |
227 | { | |
228 | switch (MSYMBOL_TYPE (msymbol)) | |
229 | { | |
230 | @@ -699,6 +700,16 @@ lookup_minimal_symbol_by_pc (CORE_ADDR p | |
231 | { | |
232 | return lookup_minimal_symbol_by_pc_section (pc, NULL); | |
233 | } | |
234 | + | |
235 | +/* Return non-zero iff PC is in function implementing gnu-ifunc selection. */ | |
236 | + | |
237 | +int | |
238 | +in_gnu_ifunc_stub (CORE_ADDR pc) | |
239 | +{ | |
240 | + struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (pc); | |
241 | + | |
242 | + return msymbol && MSYMBOL_TYPE (msymbol) == mst_text_gnu_ifunc; | |
243 | +} | |
244 | \f | |
245 | ||
246 | /* Return leading symbol character for a BFD. If BFD is NULL, | |
247 | @@ -738,6 +749,7 @@ prim_record_minimal_symbol (const char * | |
248 | switch (ms_type) | |
249 | { | |
250 | case mst_text: | |
251 | + case mst_text_gnu_ifunc: | |
252 | case mst_file_text: | |
253 | case mst_solib_trampoline: | |
254 | section = SECT_OFF_TEXT (objfile); | |
255 | @@ -1184,7 +1196,8 @@ find_solib_trampoline_target (struct fra | |
256 | { | |
257 | ALL_MSYMBOLS (objfile, msymbol) | |
258 | { | |
259 | - if (MSYMBOL_TYPE (msymbol) == mst_text | |
260 | + if ((MSYMBOL_TYPE (msymbol) == mst_text | |
261 | + || MSYMBOL_TYPE (msymbol) == mst_text_gnu_ifunc) | |
262 | && strcmp (SYMBOL_LINKAGE_NAME (msymbol), | |
263 | SYMBOL_LINKAGE_NAME (tsymbol)) == 0) | |
264 | return SYMBOL_VALUE_ADDRESS (msymbol); | |
265 | Index: gdb-7.0/gdb/parse.c | |
266 | =================================================================== | |
267 | --- gdb-7.0.orig/gdb/parse.c 2009-11-25 10:24:47.000000000 +0100 | |
268 | +++ gdb-7.0/gdb/parse.c 2009-11-25 10:26:16.000000000 +0100 | |
269 | @@ -517,6 +517,11 @@ write_exp_msymbol (struct minimal_symbol | |
270 | write_exp_elt_type (objfile_type (objfile)->nodebug_text_symbol); | |
271 | break; | |
272 | ||
273 | + case mst_text_gnu_ifunc: | |
274 | + write_exp_elt_type (objfile_type (objfile) | |
275 | + ->nodebug_text_gnu_ifunc_symbol); | |
276 | + break; | |
277 | + | |
278 | case mst_data: | |
279 | case mst_file_data: | |
280 | case mst_bss: | |
281 | Index: gdb-7.0/gdb/solib-svr4.c | |
282 | =================================================================== | |
283 | --- gdb-7.0.orig/gdb/solib-svr4.c 2009-11-25 10:24:49.000000000 +0100 | |
284 | +++ gdb-7.0/gdb/solib-svr4.c 2009-11-25 10:26:41.000000000 +0100 | |
285 | @@ -1242,7 +1242,8 @@ svr4_in_dynsym_resolve_code (CORE_ADDR p | |
286 | { | |
287 | return ((pc >= interp_text_sect_low && pc < interp_text_sect_high) | |
288 | || (pc >= interp_plt_sect_low && pc < interp_plt_sect_high) | |
289 | - || in_plt_section (pc, NULL)); | |
290 | + || in_plt_section (pc, NULL) | |
291 | + || in_gnu_ifunc_stub (pc)); | |
292 | } | |
293 | ||
294 | /* Given an executable's ABFD and target, compute the entry-point | |
295 | Index: gdb-7.0/gdb/symmisc.c | |
296 | =================================================================== | |
297 | --- gdb-7.0.orig/gdb/symmisc.c 2009-11-25 10:24:47.000000000 +0100 | |
298 | +++ gdb-7.0/gdb/symmisc.c 2009-11-25 10:24:56.000000000 +0100 | |
299 | @@ -287,6 +287,9 @@ dump_msymbols (struct objfile *objfile, | |
300 | case mst_text: | |
301 | ms_type = 'T'; | |
302 | break; | |
303 | + case mst_text_gnu_ifunc: | |
304 | + ms_type = 'i'; | |
305 | + break; | |
306 | case mst_solib_trampoline: | |
307 | ms_type = 'S'; | |
308 | break; | |
309 | Index: gdb-7.0/gdb/symtab.c | |
310 | =================================================================== | |
311 | --- gdb-7.0.orig/gdb/symtab.c 2009-11-25 10:24:47.000000000 +0100 | |
312 | +++ gdb-7.0/gdb/symtab.c 2009-11-25 10:24:56.000000000 +0100 | |
313 | @@ -3155,7 +3155,7 @@ search_symbols (char *regexp, domain_enu | |
314 | {mst_file_data, mst_solib_trampoline, mst_abs, mst_unknown}; | |
315 | static enum minimal_symbol_type types4[] | |
316 | = | |
317 | - {mst_file_bss, mst_text, mst_abs, mst_unknown}; | |
318 | + {mst_file_bss, mst_text_gnu_ifunc, mst_abs, mst_unknown}; | |
319 | enum minimal_symbol_type ourtype; | |
320 | enum minimal_symbol_type ourtype2; | |
321 | enum minimal_symbol_type ourtype3; | |
322 | Index: gdb-7.0/gdb/symtab.h | |
323 | =================================================================== | |
324 | --- gdb-7.0.orig/gdb/symtab.h 2009-11-25 10:24:45.000000000 +0100 | |
325 | +++ gdb-7.0/gdb/symtab.h 2009-11-25 10:24:56.000000000 +0100 | |
326 | @@ -275,6 +275,8 @@ enum minimal_symbol_type | |
327 | { | |
328 | mst_unknown = 0, /* Unknown type, the default */ | |
329 | mst_text, /* Generally executable instructions */ | |
330 | + mst_text_gnu_ifunc, /* Executable code returning address | |
331 | + of executable code */ | |
332 | mst_data, /* Generally initialized data */ | |
333 | mst_bss, /* Generally uninitialized data */ | |
334 | mst_abs, /* Generally absolute (nonrelocatable) */ | |
335 | @@ -1149,6 +1151,8 @@ extern struct minimal_symbol *lookup_min | |
336 | ||
337 | extern struct minimal_symbol *lookup_minimal_symbol_by_pc (CORE_ADDR); | |
338 | ||
339 | +extern int in_gnu_ifunc_stub (CORE_ADDR pc); | |
340 | + | |
341 | extern struct minimal_symbol | |
342 | *lookup_minimal_symbol_by_pc_section (CORE_ADDR, struct obj_section *); | |
343 | ||
344 | Index: gdb-7.0/gdb/testsuite/gdb.base/gnu-ifunc-lib.c | |
345 | =================================================================== | |
346 | --- /dev/null 1970-01-01 00:00:00.000000000 +0000 | |
347 | +++ gdb-7.0/gdb/testsuite/gdb.base/gnu-ifunc-lib.c 2009-11-25 10:24:56.000000000 +0100 | |
348 | @@ -0,0 +1,45 @@ | |
349 | +/* This testcase is part of GDB, the GNU debugger. | |
350 | + | |
351 | + Copyright 2009 Free Software Foundation, Inc. | |
352 | + | |
353 | + This program is free software; you can redistribute it and/or modify | |
354 | + it under the terms of the GNU General Public License as published by | |
355 | + the Free Software Foundation; either version 3 of the License, or | |
356 | + (at your option) any later version. | |
357 | + | |
358 | + This program is distributed in the hope that it will be useful, | |
359 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | |
360 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
361 | + GNU General Public License for more details. | |
362 | + | |
363 | + You should have received a copy of the GNU General Public License | |
364 | + along with this program. If not, see <http://www.gnu.org/licenses/>. */ | |
365 | + | |
366 | +#include <assert.h> | |
367 | + | |
368 | +typedef int (*final_t) (int arg); | |
369 | + | |
370 | +static int | |
371 | +final (int arg) | |
372 | +{ | |
373 | + return arg + 1; | |
374 | +} | |
375 | + | |
376 | +static volatile int gnu_ifunc_initialized; | |
377 | + | |
378 | +void | |
379 | +gnu_ifunc_pre (void) | |
380 | +{ | |
381 | + assert (!gnu_ifunc_initialized); | |
382 | +} | |
383 | + | |
384 | +final_t gnu_ifuncX (void) asm ("gnu_ifunc"); | |
385 | +asm (".type gnu_ifunc, @gnu_indirect_function"); | |
386 | + | |
387 | +final_t | |
388 | +gnu_ifuncX (void) | |
389 | +{ | |
390 | + gnu_ifunc_initialized = 1; | |
391 | + | |
392 | + return final; | |
393 | +} | |
394 | Index: gdb-7.0/gdb/testsuite/gdb.base/gnu-ifunc.c | |
395 | =================================================================== | |
396 | --- /dev/null 1970-01-01 00:00:00.000000000 +0000 | |
397 | +++ gdb-7.0/gdb/testsuite/gdb.base/gnu-ifunc.c 2009-11-25 10:24:56.000000000 +0100 | |
398 | @@ -0,0 +1,36 @@ | |
399 | +/* This testcase is part of GDB, the GNU debugger. | |
400 | + | |
401 | + Copyright 2009 Free Software Foundation, Inc. | |
402 | + | |
403 | + This program is free software; you can redistribute it and/or modify | |
404 | + it under the terms of the GNU General Public License as published by | |
405 | + the Free Software Foundation; either version 3 of the License, or | |
406 | + (at your option) any later version. | |
407 | + | |
408 | + This program is distributed in the hope that it will be useful, | |
409 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | |
410 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
411 | + GNU General Public License for more details. | |
412 | + | |
413 | + You should have received a copy of the GNU General Public License | |
414 | + along with this program. If not, see <http://www.gnu.org/licenses/>. */ | |
415 | + | |
416 | +#include <assert.h> | |
417 | + | |
418 | +extern int gnu_ifunc (int arg); | |
419 | +extern void gnu_ifunc_pre (void); | |
420 | + | |
421 | +int | |
422 | +main (void) | |
423 | +{ | |
424 | + int i; | |
425 | + | |
426 | + gnu_ifunc_pre (); | |
427 | + | |
428 | + i = gnu_ifunc (1); /* break-at-call */ | |
429 | + assert (i == 2); | |
430 | + | |
431 | + gnu_ifunc (2); /* break-at-nextcall */ | |
432 | + | |
433 | + return 0; /* break-at-exit */ | |
434 | +} | |
435 | Index: gdb-7.0/gdb/testsuite/gdb.base/gnu-ifunc.exp | |
436 | =================================================================== | |
437 | --- /dev/null 1970-01-01 00:00:00.000000000 +0000 | |
438 | +++ gdb-7.0/gdb/testsuite/gdb.base/gnu-ifunc.exp 2009-11-25 10:24:56.000000000 +0100 | |
439 | @@ -0,0 +1,72 @@ | |
440 | +# Copyright (C) 2009 Free Software Foundation, Inc. | |
441 | + | |
442 | +# This program is free software; you can redistribute it and/or modify | |
443 | +# it under the terms of the GNU General Public License as published by | |
444 | +# the Free Software Foundation; either version 3 of the License, or | |
445 | +# (at your option) any later version. | |
446 | +# | |
447 | +# This program is distributed in the hope that it will be useful, | |
448 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
449 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
450 | +# GNU General Public License for more details. | |
451 | +# | |
452 | +# You should have received a copy of the GNU General Public License | |
453 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
454 | + | |
455 | +if {[skip_shlib_tests]} { | |
456 | + return 0 | |
457 | +} | |
458 | + | |
459 | +set testfile "gnu-ifunc" | |
460 | +set srcfile ${testfile}.c | |
461 | +set binfile ${objdir}/${subdir}/${testfile} | |
462 | + | |
463 | +set libfile "${testfile}-lib" | |
464 | +set libsrc ${libfile}.c | |
465 | +set lib_so ${objdir}/${subdir}/${libfile}.so | |
466 | + | |
467 | +set lib_opts [list debug] | |
468 | +set exec_opts [list debug shlib=$lib_so] | |
469 | + | |
470 | +if [get_compiler_info ${binfile}] { | |
471 | + return -1 | |
472 | +} | |
473 | + | |
474 | +if { [gdb_compile_shlib ${srcdir}/${subdir}/$libsrc $lib_so $lib_opts] != "" | |
475 | + || [gdb_compile ${srcdir}/${subdir}/$srcfile $binfile executable $exec_opts] != ""} { | |
476 | + untested "Could not compile either $libsrc or $srcfile." | |
477 | + return -1 | |
478 | +} | |
479 | + | |
480 | +# Start with a fresh gdb. | |
481 | + | |
482 | +clean_restart $testfile | |
483 | +gdb_load_shlibs ${lib_so} | |
484 | + | |
485 | +if ![runto_main] then { | |
486 | + fail "Can't run to main" | |
487 | + return 1; | |
488 | +} | |
489 | + | |
490 | +gdb_breakpoint [gdb_get_line_number "break-at-nextcall"] | |
491 | + | |
492 | +gdb_breakpoint [gdb_get_line_number "break-at-call"] | |
493 | +gdb_continue_to_breakpoint "break-at-call" ".*break-at-call.*" | |
494 | + | |
495 | +# Test GDB will automatically indirect the call. | |
496 | + | |
497 | +gdb_test "p gnu_ifunc (3)" " = 4" | |
498 | + | |
499 | +# Test GDB will skip the gnu_ifunc resolver on first call. | |
500 | + | |
501 | +gdb_test "step" "\r\nfinal .*" | |
502 | + | |
503 | +# Test GDB will not break before the final chosen implementation. | |
504 | + | |
505 | +gdb_continue_to_breakpoint "break-at-nextcall" ".*break-at-nextcall.*" | |
506 | + | |
507 | +gdb_breakpoint "gnu_ifunc" | |
508 | + | |
509 | +gdb_continue_to_breakpoint "nextcall gnu_ifunc" | |
510 | + | |
511 | +gdb_test "frame" "#0 +final \\(.*" "nextcall gnu_ifunc skipped" |