]> git.pld-linux.org Git - packages/gdb.git/blame - gdb-bz539590-gnu-ifunc.patch
- NOTE: does not build with -j2
[packages/gdb.git] / gdb-bz539590-gnu-ifunc.patch
CommitLineData
ab050a48
BZ
1gdb/
22009-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
28gdb/testsuite/
292009-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
35Index: 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)
61Index: 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,
95Index: 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;
147Index: 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);
179Index: 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 &current_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
214Index: 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);
265Index: 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:
281Index: 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
295Index: 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;
309Index: 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;
322Index: 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
344Index: 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+}
394Index: 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+}
435Index: 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"
This page took 0.131272 seconds and 4 git commands to generate.