79563d6f81
- archer-jankratochvil-fedora13 commit: ccde1530479cc966374351038057b9dda90aa251 - [expr-cumulative] Archer branch is now included.
1046 lines
37 KiB
Diff
1046 lines
37 KiB
Diff
http://sourceware.org/gdb/wiki/ProjectArcher
|
||
http://sourceware.org/gdb/wiki/ArcherBranchManagement
|
||
|
||
GIT snapshot:
|
||
commit 791165df07fd22d381def1318954c389a606f81a
|
||
|
||
archer-jankratochvil-ifunc
|
||
|
||
Index: gdb-7.0.50.20100121/gdb/alpha-linux-tdep.c
|
||
===================================================================
|
||
--- gdb-7.0.50.20100121.orig/gdb/alpha-linux-tdep.c 2010-01-01 08:31:29.000000000 +0100
|
||
+++ gdb-7.0.50.20100121/gdb/alpha-linux-tdep.c 2010-01-21 15:15:41.000000000 +0100
|
||
@@ -26,6 +26,7 @@
|
||
#include "symtab.h"
|
||
#include "regset.h"
|
||
#include "regcache.h"
|
||
+#include "linux-tdep.h"
|
||
|
||
#include "alpha-tdep.h"
|
||
|
||
@@ -236,6 +237,9 @@ alpha_linux_init_abi (struct gdbarch_inf
|
||
|
||
set_gdbarch_regset_from_core_section
|
||
(gdbarch, alpha_linux_regset_from_core_section);
|
||
+
|
||
+ set_gdbarch_convert_from_func_ptr_addr (gdbarch,
|
||
+ linux_convert_from_func_ptr_addr);
|
||
}
|
||
|
||
/* Provide a prototype to silence -Wmissing-prototypes. */
|
||
Index: gdb-7.0.50.20100121/gdb/amd64-linux-tdep.c
|
||
===================================================================
|
||
--- gdb-7.0.50.20100121.orig/gdb/amd64-linux-tdep.c 2010-01-21 15:13:26.000000000 +0100
|
||
+++ gdb-7.0.50.20100121/gdb/amd64-linux-tdep.c 2010-01-21 15:15:41.000000000 +0100
|
||
@@ -1557,6 +1557,9 @@ amd64_linux_init_abi (struct gdbarch_inf
|
||
amd64_linux_record_tdep.arg6 = AMD64_R9_REGNUM;
|
||
|
||
tdep->i386_syscall_record = amd64_linux_syscall_record;
|
||
+
|
||
+ set_gdbarch_convert_from_func_ptr_addr (gdbarch,
|
||
+ linux_convert_from_func_ptr_addr);
|
||
}
|
||
|
||
|
||
Index: gdb-7.0.50.20100121/gdb/arm-linux-tdep.c
|
||
===================================================================
|
||
--- gdb-7.0.50.20100121.orig/gdb/arm-linux-tdep.c 2010-01-01 08:31:29.000000000 +0100
|
||
+++ gdb-7.0.50.20100121/gdb/arm-linux-tdep.c 2010-01-21 15:15:41.000000000 +0100
|
||
@@ -907,6 +907,9 @@ arm_linux_init_abi (struct gdbarch_info
|
||
set_gdbarch_displaced_step_free_closure (gdbarch,
|
||
simple_displaced_step_free_closure);
|
||
set_gdbarch_displaced_step_location (gdbarch, displaced_step_at_entry_point);
|
||
+
|
||
+ set_gdbarch_convert_from_func_ptr_addr (gdbarch,
|
||
+ linux_convert_from_func_ptr_addr);
|
||
}
|
||
|
||
/* Provide a prototype to silence -Wmissing-prototypes. */
|
||
Index: gdb-7.0.50.20100121/gdb/elfread.c
|
||
===================================================================
|
||
--- gdb-7.0.50.20100121.orig/gdb/elfread.c 2010-01-21 15:13:27.000000000 +0100
|
||
+++ gdb-7.0.50.20100121/gdb/elfread.c 2010-01-21 15:15:41.000000000 +0100
|
||
@@ -184,7 +184,8 @@ record_minimal_symbol (const char *name,
|
||
{
|
||
struct gdbarch *gdbarch = get_objfile_arch (objfile);
|
||
|
||
- if (ms_type == mst_text || ms_type == mst_file_text)
|
||
+ if (ms_type == mst_text || ms_type == mst_file_text
|
||
+ || ms_type == mst_text_gnu_ifunc)
|
||
address = gdbarch_smash_text_address (gdbarch, address);
|
||
|
||
return prim_record_minimal_symbol_full (name, name_len, copy_name, address,
|
||
@@ -393,7 +394,10 @@ elf_symtab_read (struct objfile *objfile
|
||
{
|
||
if (sym->flags & (BSF_GLOBAL | BSF_WEAK))
|
||
{
|
||
- ms_type = mst_text;
|
||
+ if (sym->flags & BSF_GNU_INDIRECT_FUNCTION)
|
||
+ ms_type = mst_text_gnu_ifunc;
|
||
+ else
|
||
+ ms_type = mst_text;
|
||
}
|
||
else if ((sym->name[0] == '.' && sym->name[1] == 'L')
|
||
|| ((sym->flags & BSF_LOCAL)
|
||
Index: gdb-7.0.50.20100121/gdb/frv-linux-tdep.c
|
||
===================================================================
|
||
--- gdb-7.0.50.20100121.orig/gdb/frv-linux-tdep.c 2010-01-01 08:31:32.000000000 +0100
|
||
+++ gdb-7.0.50.20100121/gdb/frv-linux-tdep.c 2010-01-21 15:15:41.000000000 +0100
|
||
@@ -32,6 +32,7 @@
|
||
#include "frame-unwind.h"
|
||
#include "regset.h"
|
||
#include "gdb_string.h"
|
||
+#include "linux-tdep.h"
|
||
|
||
/* Define the size (in bytes) of an FR-V instruction. */
|
||
static const int frv_instr_size = 4;
|
||
@@ -486,7 +487,21 @@ frv_linux_regset_from_core_section (stru
|
||
return NULL;
|
||
}
|
||
|
||
-
|
||
+static CORE_ADDR
|
||
+frv_linux_convert_from_func_ptr_addr (struct gdbarch *gdbarch,
|
||
+ CORE_ADDR addr,
|
||
+ struct target_ops *targ)
|
||
+{
|
||
+ CORE_ADDR pc = frv_convert_from_func_ptr_addr (gdbarch, addr, targ);
|
||
+ CORE_ADDR resolved;
|
||
+
|
||
+ resolved = linux_convert_from_func_and_ptr (gdbarch, addr, pc);
|
||
+ if (resolved != pc)
|
||
+ pc = frv_convert_from_func_ptr_addr (gdbarch, resolved, targ);
|
||
+
|
||
+ return pc;
|
||
+}
|
||
+
|
||
static void
|
||
frv_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
|
||
{
|
||
@@ -494,6 +509,10 @@ frv_linux_init_abi (struct gdbarch_info
|
||
frame_unwind_append_unwinder (gdbarch, &frv_linux_sigtramp_frame_unwind);
|
||
set_gdbarch_regset_from_core_section (gdbarch,
|
||
frv_linux_regset_from_core_section);
|
||
+
|
||
+ if (frv_abi (gdbarch) == FRV_ABI_FDPIC)
|
||
+ set_gdbarch_convert_from_func_ptr_addr (gdbarch,
|
||
+ frv_linux_convert_from_func_ptr_addr);
|
||
}
|
||
|
||
static enum gdb_osabi
|
||
Index: gdb-7.0.50.20100121/gdb/frv-tdep.c
|
||
===================================================================
|
||
--- gdb-7.0.50.20100121.orig/gdb/frv-tdep.c 2010-01-01 08:31:32.000000000 +0100
|
||
+++ gdb-7.0.50.20100121/gdb/frv-tdep.c 2010-01-21 15:15:41.000000000 +0100
|
||
@@ -1169,7 +1169,7 @@ find_func_descr (struct gdbarch *gdbarch
|
||
return descr;
|
||
}
|
||
|
||
-static CORE_ADDR
|
||
+CORE_ADDR
|
||
frv_convert_from_func_ptr_addr (struct gdbarch *gdbarch, CORE_ADDR addr,
|
||
struct target_ops *targ)
|
||
{
|
||
Index: gdb-7.0.50.20100121/gdb/frv-tdep.h
|
||
===================================================================
|
||
--- gdb-7.0.50.20100121.orig/gdb/frv-tdep.h 2010-01-01 08:31:32.000000000 +0100
|
||
+++ gdb-7.0.50.20100121/gdb/frv-tdep.h 2010-01-21 15:15:41.000000000 +0100
|
||
@@ -118,3 +118,6 @@ CORE_ADDR frv_fetch_objfile_link_map (st
|
||
struct target_so_ops;
|
||
extern struct target_so_ops frv_so_ops;
|
||
|
||
+CORE_ADDR frv_convert_from_func_ptr_addr (struct gdbarch *gdbarch,
|
||
+ CORE_ADDR addr,
|
||
+ struct target_ops *targ);
|
||
Index: gdb-7.0.50.20100121/gdb/gdbtypes.c
|
||
===================================================================
|
||
--- gdb-7.0.50.20100121.orig/gdb/gdbtypes.c 2010-01-21 15:13:26.000000000 +0100
|
||
+++ gdb-7.0.50.20100121/gdb/gdbtypes.c 2010-01-21 15:15:41.000000000 +0100
|
||
@@ -1946,6 +1946,8 @@ init_type (enum type_code code, int leng
|
||
TYPE_NOTTEXT (type) = 1;
|
||
if (flags & TYPE_FLAG_FIXED_INSTANCE)
|
||
TYPE_FIXED_INSTANCE (type) = 1;
|
||
+ if (flags & TYPE_FLAG_GNU_IFUNC)
|
||
+ TYPE_GNU_IFUNC (type) = 1;
|
||
|
||
if (name)
|
||
TYPE_NAME (type) = obsavestring (name, strlen (name),
|
||
@@ -3955,6 +3957,8 @@ gdbtypes_post_init (struct gdbarch *gdba
|
||
= lookup_pointer_type (builtin_type->builtin_void);
|
||
builtin_type->builtin_func_ptr
|
||
= lookup_pointer_type (lookup_function_type (builtin_type->builtin_void));
|
||
+ builtin_type->builtin_func_func
|
||
+ = lookup_function_type (builtin_type->builtin_func_ptr);
|
||
|
||
/* This type represents a GDB internal function. */
|
||
builtin_type->internal_fn
|
||
@@ -4071,6 +4075,11 @@ objfile_type (struct objfile *objfile)
|
||
"<text variable, no debug info>", objfile);
|
||
TYPE_TARGET_TYPE (objfile_type->nodebug_text_symbol)
|
||
= objfile_type->builtin_int;
|
||
+ objfile_type->nodebug_text_gnu_ifunc_symbol
|
||
+ = init_type (TYPE_CODE_FUNC, 1, TYPE_FLAG_GNU_IFUNC,
|
||
+ "<text gnu-ifunc variable, no debug info>", objfile);
|
||
+ TYPE_TARGET_TYPE (objfile_type->nodebug_text_gnu_ifunc_symbol)
|
||
+ = objfile_type->nodebug_text_symbol;
|
||
objfile_type->nodebug_data_symbol
|
||
= init_type (TYPE_CODE_INT,
|
||
gdbarch_int_bit (gdbarch) / HOST_CHAR_BIT, 0,
|
||
Index: gdb-7.0.50.20100121/gdb/gdbtypes.h
|
||
===================================================================
|
||
--- gdb-7.0.50.20100121.orig/gdb/gdbtypes.h 2010-01-21 15:14:41.000000000 +0100
|
||
+++ gdb-7.0.50.20100121/gdb/gdbtypes.h 2010-01-21 15:16:39.000000000 +0100
|
||
@@ -188,6 +188,7 @@ enum type_flag_value
|
||
TYPE_FLAG_FIXED_INSTANCE = (1 << 15),
|
||
TYPE_FLAG_STUB_SUPPORTED = (1 << 16),
|
||
TYPE_FLAG_NOTTEXT = (1 << 17),
|
||
+ TYPE_FLAG_GNU_IFUNC = (1 << 18),
|
||
|
||
/* Used for error-checking. */
|
||
TYPE_FLAG_MIN = TYPE_FLAG_UNSIGNED
|
||
@@ -293,6 +294,12 @@ enum type_instance_flag_value
|
||
|
||
#define TYPE_NOTTEXT(t) (TYPE_MAIN_TYPE (t)->flag_nottext)
|
||
|
||
+/* Currently used only for TYPE_CODE_FUNC where specifies the real function
|
||
+ address is returned by this function call. TYPE_TARGET_TYPE determines the
|
||
+ final returned function type to be presented to user. */
|
||
+
|
||
+#define TYPE_GNU_IFUNC(t) (TYPE_MAIN_TYPE (t)->flag_gnu_ifunc)
|
||
+
|
||
/* Type owner. If TYPE_OBJFILE_OWNED is true, the type is owned by
|
||
the objfile retrieved as TYPE_OBJFILE. Otherweise, the type is
|
||
owned by an architecture; TYPE_OBJFILE is NULL in this case. */
|
||
@@ -447,6 +454,7 @@ struct main_type
|
||
unsigned int flag_vector : 1;
|
||
unsigned int flag_stub_supported : 1;
|
||
unsigned int flag_nottext : 1;
|
||
+ unsigned int flag_gnu_ifunc : 1;
|
||
unsigned int flag_fixed_instance : 1;
|
||
unsigned int flag_objfile_owned : 1;
|
||
unsigned int flag_discardable : 1;
|
||
@@ -1243,6 +1251,10 @@ struct builtin_type
|
||
(*) () can server as a generic function pointer. */
|
||
struct type *builtin_func_ptr;
|
||
|
||
+ /* `function returning pointer to function (returning void)' type.
|
||
+ The final void return type is not significant for it. */
|
||
+ struct type *builtin_func_func;
|
||
+
|
||
|
||
/* Special-purpose types. */
|
||
|
||
@@ -1285,6 +1297,7 @@ struct objfile_type
|
||
|
||
/* Types used for symbols with no debug information. */
|
||
struct type *nodebug_text_symbol;
|
||
+ struct type *nodebug_text_gnu_ifunc_symbol;
|
||
struct type *nodebug_data_symbol;
|
||
struct type *nodebug_unknown_symbol;
|
||
struct type *nodebug_tls_symbol;
|
||
Index: gdb-7.0.50.20100121/gdb/hppa-linux-tdep.c
|
||
===================================================================
|
||
--- gdb-7.0.50.20100121.orig/gdb/hppa-linux-tdep.c 2010-01-01 08:31:33.000000000 +0100
|
||
+++ gdb-7.0.50.20100121/gdb/hppa-linux-tdep.c 2010-01-21 15:15:41.000000000 +0100
|
||
@@ -32,6 +32,7 @@
|
||
#include "regset.h"
|
||
#include "regcache.h"
|
||
#include "hppa-tdep.h"
|
||
+#include "linux-tdep.h"
|
||
|
||
#include "elf/common.h"
|
||
|
||
@@ -513,7 +514,21 @@ hppa_linux_regset_from_core_section (str
|
||
|
||
return NULL;
|
||
}
|
||
-
|
||
+
|
||
+static CORE_ADDR
|
||
+hppa32_linux_convert_from_func_ptr_addr (struct gdbarch *gdbarch,
|
||
+ CORE_ADDR addr,
|
||
+ struct target_ops *targ)
|
||
+{
|
||
+ CORE_ADDR pc = hppa32_convert_from_func_ptr_addr (gdbarch, addr, targ);
|
||
+ CORE_ADDR resolved;
|
||
+
|
||
+ resolved = linux_convert_from_func_and_ptr (gdbarch, addr, pc);
|
||
+ if (resolved != pc)
|
||
+ pc = hppa32_convert_from_func_ptr_addr (gdbarch, resolved, targ);
|
||
+
|
||
+ return pc;
|
||
+}
|
||
|
||
/* Forward declarations. */
|
||
extern initialize_file_ftype _initialize_hppa_linux_tdep;
|
||
@@ -555,6 +570,10 @@ hppa_linux_init_abi (struct gdbarch_info
|
||
/* Enable TLS support. */
|
||
set_gdbarch_fetch_tls_load_module_address (gdbarch,
|
||
svr4_fetch_objfile_link_map);
|
||
+
|
||
+ if (tdep->bytes_per_address == 4)
|
||
+ set_gdbarch_convert_from_func_ptr_addr (gdbarch,
|
||
+ hppa32_linux_convert_from_func_ptr_addr);
|
||
}
|
||
|
||
void
|
||
Index: gdb-7.0.50.20100121/gdb/hppa-tdep.c
|
||
===================================================================
|
||
--- gdb-7.0.50.20100121.orig/gdb/hppa-tdep.c 2010-01-19 10:39:12.000000000 +0100
|
||
+++ gdb-7.0.50.20100121/gdb/hppa-tdep.c 2010-01-21 15:15:41.000000000 +0100
|
||
@@ -1247,7 +1247,7 @@ hppa64_return_value (struct gdbarch *gdb
|
||
}
|
||
|
||
|
||
-static CORE_ADDR
|
||
+CORE_ADDR
|
||
hppa32_convert_from_func_ptr_addr (struct gdbarch *gdbarch, CORE_ADDR addr,
|
||
struct target_ops *targ)
|
||
{
|
||
Index: gdb-7.0.50.20100121/gdb/hppa-tdep.h
|
||
===================================================================
|
||
--- gdb-7.0.50.20100121.orig/gdb/hppa-tdep.h 2010-01-01 08:31:33.000000000 +0100
|
||
+++ gdb-7.0.50.20100121/gdb/hppa-tdep.h 2010-01-21 15:15:41.000000000 +0100
|
||
@@ -246,4 +246,8 @@ extern int hppa_in_solib_call_trampoline
|
||
CORE_ADDR pc, char *name);
|
||
extern CORE_ADDR hppa_skip_trampoline_code (struct frame_info *, CORE_ADDR pc);
|
||
|
||
+extern CORE_ADDR hppa32_convert_from_func_ptr_addr (struct gdbarch *gdbarch,
|
||
+ CORE_ADDR addr,
|
||
+ struct target_ops *targ);
|
||
+
|
||
#endif /* hppa-tdep.h */
|
||
Index: gdb-7.0.50.20100121/gdb/i386-linux-tdep.c
|
||
===================================================================
|
||
--- gdb-7.0.50.20100121.orig/gdb/i386-linux-tdep.c 2010-01-04 15:57:43.000000000 +0100
|
||
+++ gdb-7.0.50.20100121/gdb/i386-linux-tdep.c 2010-01-21 15:15:41.000000000 +0100
|
||
@@ -798,6 +798,9 @@ i386_linux_init_abi (struct gdbarch_info
|
||
i386_linux_get_syscall_number);
|
||
|
||
set_gdbarch_get_siginfo_type (gdbarch, linux_get_siginfo_type);
|
||
+
|
||
+ set_gdbarch_convert_from_func_ptr_addr (gdbarch,
|
||
+ linux_convert_from_func_ptr_addr);
|
||
}
|
||
|
||
/* Provide a prototype to silence -Wmissing-prototypes. */
|
||
Index: gdb-7.0.50.20100121/gdb/ia64-linux-tdep.c
|
||
===================================================================
|
||
--- gdb-7.0.50.20100121.orig/gdb/ia64-linux-tdep.c 2010-01-01 08:31:36.000000000 +0100
|
||
+++ gdb-7.0.50.20100121/gdb/ia64-linux-tdep.c 2010-01-21 15:15:41.000000000 +0100
|
||
@@ -26,6 +26,7 @@
|
||
#include "osabi.h"
|
||
#include "solib-svr4.h"
|
||
#include "symtab.h"
|
||
+#include "linux-tdep.h"
|
||
|
||
/* The sigtramp code is in a non-readable (executable-only) region
|
||
of memory called the ``gate page''. The addresses in question
|
||
@@ -139,6 +140,9 @@ ia64_linux_init_abi (struct gdbarch_info
|
||
/* Enable TLS support. */
|
||
set_gdbarch_fetch_tls_load_module_address (gdbarch,
|
||
svr4_fetch_objfile_link_map);
|
||
+
|
||
+ set_gdbarch_convert_from_func_ptr_addr (gdbarch,
|
||
+ linux_convert_from_func_ptr_addr);
|
||
}
|
||
|
||
/* Provide a prototype to silence -Wmissing-prototypes. */
|
||
Index: gdb-7.0.50.20100121/gdb/infcall.c
|
||
===================================================================
|
||
--- gdb-7.0.50.20100121.orig/gdb/infcall.c 2010-01-01 08:31:36.000000000 +0100
|
||
+++ gdb-7.0.50.20100121/gdb/infcall.c 2010-01-21 15:15:41.000000000 +0100
|
||
@@ -252,9 +252,17 @@ find_function_addr (struct value *functi
|
||
if (TYPE_CODE (ftype) == TYPE_CODE_FUNC
|
||
|| TYPE_CODE (ftype) == TYPE_CODE_METHOD)
|
||
{
|
||
- funaddr = gdbarch_convert_from_func_ptr_addr (gdbarch, funaddr,
|
||
- ¤t_target);
|
||
- value_type = TYPE_TARGET_TYPE (ftype);
|
||
+ CORE_ADDR funaddr2;
|
||
+
|
||
+ funaddr2 = gdbarch_convert_from_func_ptr_addr (gdbarch, funaddr,
|
||
+ ¤t_target);
|
||
+
|
||
+ /* If TYPE_GNU_IFUNC is currently not resolvable keep its type. */
|
||
+ if (funaddr2 != funaddr || !TYPE_GNU_IFUNC (ftype))
|
||
+ {
|
||
+ funaddr = funaddr2;
|
||
+ value_type = TYPE_TARGET_TYPE (ftype);
|
||
+ }
|
||
}
|
||
}
|
||
else if (code == TYPE_CODE_INT)
|
||
Index: gdb-7.0.50.20100121/gdb/linux-tdep.c
|
||
===================================================================
|
||
--- gdb-7.0.50.20100121.orig/gdb/linux-tdep.c 2010-01-14 22:20:11.000000000 +0100
|
||
+++ gdb-7.0.50.20100121/gdb/linux-tdep.c 2010-01-21 15:15:41.000000000 +0100
|
||
@@ -23,6 +23,8 @@
|
||
#include "auxv.h"
|
||
#include "target.h"
|
||
#include "elf/common.h"
|
||
+#include "value.h"
|
||
+#include "infcall.h"
|
||
|
||
/* This function is suitable for architectures that don't
|
||
extend/override the standard siginfo structure. */
|
||
@@ -152,3 +154,43 @@ linux_has_shared_address_space (void)
|
||
|
||
return target_is_uclinux;
|
||
}
|
||
+
|
||
+/* Call gnu-ifunc to resolve breakpoint at its returned function. */
|
||
+
|
||
+CORE_ADDR
|
||
+linux_convert_from_func_and_ptr (struct gdbarch *gdbarch, CORE_ADDR func_ptr,
|
||
+ CORE_ADDR pc)
|
||
+{
|
||
+ struct type *func_func_type = builtin_type (gdbarch)->builtin_func_func;
|
||
+ struct minimal_symbol *msymbol;
|
||
+ struct value *function, *address;
|
||
+
|
||
+ if (!target_has_execution)
|
||
+ return pc;
|
||
+
|
||
+ msymbol = lookup_minimal_symbol_by_pc (func_ptr);
|
||
+ if (msymbol == NULL)
|
||
+ return pc;
|
||
+ if (MSYMBOL_TYPE (msymbol) != mst_text_gnu_ifunc)
|
||
+ return pc;
|
||
+
|
||
+ /* Not at the gnu-ifunc entry point? */
|
||
+ if (SYMBOL_VALUE_ADDRESS (msymbol) != func_ptr)
|
||
+ return pc;
|
||
+
|
||
+ function = allocate_value (func_func_type);
|
||
+ set_value_address (function, pc);
|
||
+
|
||
+ /* gnu-ifuncs have no arguments. FUNCTION is the code instruction address
|
||
+ while ADDRESS is a function descriptor. */
|
||
+ address = call_function_by_hand (function, 0, NULL);
|
||
+
|
||
+ return value_as_address (address);
|
||
+}
|
||
+
|
||
+CORE_ADDR
|
||
+linux_convert_from_func_ptr_addr (struct gdbarch *gdbarch, CORE_ADDR addr,
|
||
+ struct target_ops *targ)
|
||
+{
|
||
+ return linux_convert_from_func_and_ptr (gdbarch, addr, addr);
|
||
+}
|
||
Index: gdb-7.0.50.20100121/gdb/linux-tdep.h
|
||
===================================================================
|
||
--- gdb-7.0.50.20100121.orig/gdb/linux-tdep.h 2010-01-01 08:31:37.000000000 +0100
|
||
+++ gdb-7.0.50.20100121/gdb/linux-tdep.h 2010-01-21 15:15:41.000000000 +0100
|
||
@@ -22,4 +22,11 @@
|
||
|
||
struct type *linux_get_siginfo_type (struct gdbarch *);
|
||
|
||
+CORE_ADDR linux_convert_from_func_and_ptr (struct gdbarch *gdbarch,
|
||
+ CORE_ADDR func_ptr, CORE_ADDR pc);
|
||
+
|
||
+CORE_ADDR linux_convert_from_func_ptr_addr (struct gdbarch *gdbarch,
|
||
+ CORE_ADDR addr,
|
||
+ struct target_ops *targ);
|
||
+
|
||
#endif /* linux-tdep.h */
|
||
Index: gdb-7.0.50.20100121/gdb/m32r-linux-tdep.c
|
||
===================================================================
|
||
--- gdb-7.0.50.20100121.orig/gdb/m32r-linux-tdep.c 2010-01-01 08:31:37.000000000 +0100
|
||
+++ gdb-7.0.50.20100121/gdb/m32r-linux-tdep.c 2010-01-21 15:15:41.000000000 +0100
|
||
@@ -30,6 +30,7 @@
|
||
#include "gdb_string.h"
|
||
|
||
#include "glibc-tdep.h"
|
||
+#include "linux-tdep.h"
|
||
#include "solib-svr4.h"
|
||
#include "symtab.h"
|
||
|
||
@@ -422,6 +423,9 @@ m32r_linux_init_abi (struct gdbarch_info
|
||
/* Enable TLS support. */
|
||
set_gdbarch_fetch_tls_load_module_address (gdbarch,
|
||
svr4_fetch_objfile_link_map);
|
||
+
|
||
+ set_gdbarch_convert_from_func_ptr_addr (gdbarch,
|
||
+ linux_convert_from_func_ptr_addr);
|
||
}
|
||
|
||
/* Provide a prototype to silence -Wmissing-prototypes. */
|
||
Index: gdb-7.0.50.20100121/gdb/microblaze-linux-tdep.c
|
||
===================================================================
|
||
--- gdb-7.0.50.20100121.orig/gdb/microblaze-linux-tdep.c 2010-01-01 08:31:37.000000000 +0100
|
||
+++ gdb-7.0.50.20100121/gdb/microblaze-linux-tdep.c 2010-01-21 15:15:41.000000000 +0100
|
||
@@ -35,6 +35,7 @@
|
||
#include "trad-frame.h"
|
||
#include "frame-unwind.h"
|
||
#include "tramp-frame.h"
|
||
+#include "linux-tdep.h"
|
||
|
||
|
||
static int
|
||
@@ -133,6 +134,9 @@ microblaze_linux_init_abi (struct gdbarc
|
||
/* Trampolines. */
|
||
tramp_frame_prepend_unwinder (gdbarch,
|
||
µblaze_linux_sighandler_tramp_frame);
|
||
+
|
||
+ set_gdbarch_convert_from_func_ptr_addr (gdbarch,
|
||
+ linux_convert_from_func_ptr_addr);
|
||
}
|
||
|
||
void
|
||
Index: gdb-7.0.50.20100121/gdb/minsyms.c
|
||
===================================================================
|
||
--- gdb-7.0.50.20100121.orig/gdb/minsyms.c 2010-01-21 15:13:26.000000000 +0100
|
||
+++ gdb-7.0.50.20100121/gdb/minsyms.c 2010-01-21 15:15:41.000000000 +0100
|
||
@@ -331,8 +331,9 @@ lookup_minimal_symbol_text (const char *
|
||
msymbol = msymbol->hash_next)
|
||
{
|
||
if (strcmp (SYMBOL_LINKAGE_NAME (msymbol), name) == 0 &&
|
||
- (MSYMBOL_TYPE (msymbol) == mst_text ||
|
||
- MSYMBOL_TYPE (msymbol) == mst_file_text))
|
||
+ (MSYMBOL_TYPE (msymbol) == mst_text
|
||
+ || MSYMBOL_TYPE (msymbol) == mst_text_gnu_ifunc
|
||
+ || MSYMBOL_TYPE (msymbol) == mst_file_text))
|
||
{
|
||
switch (MSYMBOL_TYPE (msymbol))
|
||
{
|
||
@@ -698,6 +699,16 @@ lookup_minimal_symbol_by_pc (CORE_ADDR p
|
||
{
|
||
return lookup_minimal_symbol_by_pc_section (pc, NULL);
|
||
}
|
||
+
|
||
+/* Return non-zero iff PC is in function implementing gnu-ifunc selection. */
|
||
+
|
||
+int
|
||
+in_gnu_ifunc_stub (CORE_ADDR pc)
|
||
+{
|
||
+ struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (pc);
|
||
+
|
||
+ return msymbol && MSYMBOL_TYPE (msymbol) == mst_text_gnu_ifunc;
|
||
+}
|
||
|
||
|
||
/* Return leading symbol character for a BFD. If BFD is NULL,
|
||
@@ -737,6 +748,7 @@ prim_record_minimal_symbol (const char *
|
||
switch (ms_type)
|
||
{
|
||
case mst_text:
|
||
+ case mst_text_gnu_ifunc:
|
||
case mst_file_text:
|
||
case mst_solib_trampoline:
|
||
section = SECT_OFF_TEXT (objfile);
|
||
@@ -1202,7 +1214,8 @@ find_solib_trampoline_target (struct fra
|
||
{
|
||
ALL_MSYMBOLS (objfile, msymbol)
|
||
{
|
||
- if (MSYMBOL_TYPE (msymbol) == mst_text
|
||
+ if ((MSYMBOL_TYPE (msymbol) == mst_text
|
||
+ || MSYMBOL_TYPE (msymbol) == mst_text_gnu_ifunc)
|
||
&& strcmp (SYMBOL_LINKAGE_NAME (msymbol),
|
||
SYMBOL_LINKAGE_NAME (tsymbol)) == 0)
|
||
return SYMBOL_VALUE_ADDRESS (msymbol);
|
||
Index: gdb-7.0.50.20100121/gdb/mips-linux-tdep.c
|
||
===================================================================
|
||
--- gdb-7.0.50.20100121.orig/gdb/mips-linux-tdep.c 2010-01-01 08:31:37.000000000 +0100
|
||
+++ gdb-7.0.50.20100121/gdb/mips-linux-tdep.c 2010-01-21 15:15:41.000000000 +0100
|
||
@@ -38,6 +38,7 @@
|
||
#include "target-descriptions.h"
|
||
#include "mips-linux-tdep.h"
|
||
#include "glibc-tdep.h"
|
||
+#include "linux-tdep.h"
|
||
|
||
static struct target_so_ops mips_svr4_so_ops;
|
||
|
||
@@ -1225,6 +1226,9 @@ mips_linux_init_abi (struct gdbarch_info
|
||
tdesc_numbered_register (feature, tdesc_data, MIPS_RESTART_REGNUM,
|
||
"restart");
|
||
}
|
||
+
|
||
+ set_gdbarch_convert_from_func_ptr_addr (gdbarch,
|
||
+ linux_convert_from_func_ptr_addr);
|
||
}
|
||
|
||
/* Provide a prototype to silence -Wmissing-prototypes. */
|
||
Index: gdb-7.0.50.20100121/gdb/mn10300-linux-tdep.c
|
||
===================================================================
|
||
--- gdb-7.0.50.20100121.orig/gdb/mn10300-linux-tdep.c 2010-01-01 08:31:37.000000000 +0100
|
||
+++ gdb-7.0.50.20100121/gdb/mn10300-linux-tdep.c 2010-01-21 15:15:41.000000000 +0100
|
||
@@ -32,6 +32,7 @@
|
||
#include "frame.h"
|
||
#include "trad-frame.h"
|
||
#include "tramp-frame.h"
|
||
+#include "linux-tdep.h"
|
||
|
||
#include <stdlib.h>
|
||
|
||
@@ -718,6 +719,9 @@ am33_linux_init_osabi (struct gdbarch_in
|
||
|
||
tramp_frame_prepend_unwinder (gdbarch, &am33_linux_sigframe);
|
||
tramp_frame_prepend_unwinder (gdbarch, &am33_linux_rt_sigframe);
|
||
+
|
||
+ set_gdbarch_convert_from_func_ptr_addr (gdbarch,
|
||
+ linux_convert_from_func_ptr_addr);
|
||
}
|
||
|
||
/* Provide a prototype to silence -Wmissing-prototypes. */
|
||
Index: gdb-7.0.50.20100121/gdb/objc-lang.c
|
||
===================================================================
|
||
--- gdb-7.0.50.20100121.orig/gdb/objc-lang.c 2010-01-14 09:03:36.000000000 +0100
|
||
+++ gdb-7.0.50.20100121/gdb/objc-lang.c 2010-01-21 15:15:41.000000000 +0100
|
||
@@ -1178,16 +1178,6 @@ find_methods (struct symtab *symtab, cha
|
||
|
||
QUIT;
|
||
|
||
- /* The minimal symbol might point to a function descriptor;
|
||
- resolve it to the actual code address instead. */
|
||
- pc = gdbarch_convert_from_func_ptr_addr (gdbarch, pc,
|
||
- ¤t_target);
|
||
-
|
||
- if (symtab)
|
||
- if (pc < BLOCK_START (block) || pc >= BLOCK_END (block))
|
||
- /* Not in the specified symtab. */
|
||
- continue;
|
||
-
|
||
symname = SYMBOL_NATURAL_NAME (msymbol);
|
||
if (symname == NULL)
|
||
continue;
|
||
@@ -1223,6 +1213,17 @@ find_methods (struct symtab *symtab, cha
|
||
((nselector == NULL) || (strcmp (selector, nselector) != 0)))
|
||
continue;
|
||
|
||
+ /* The minimal symbol might point to a function descriptor;
|
||
+ resolve it to the actual code address instead. Delay the call as
|
||
+ its resolution may be expensive. */
|
||
+ pc = gdbarch_convert_from_func_ptr_addr (gdbarch, pc,
|
||
+ ¤t_target);
|
||
+
|
||
+ if (symtab)
|
||
+ if (pc < BLOCK_START (block) || pc >= BLOCK_END (block))
|
||
+ /* Not in the specified symtab. */
|
||
+ continue;
|
||
+
|
||
sym = find_pc_function (pc);
|
||
if (sym != NULL)
|
||
{
|
||
Index: gdb-7.0.50.20100121/gdb/parse.c
|
||
===================================================================
|
||
--- gdb-7.0.50.20100121.orig/gdb/parse.c 2010-01-21 15:13:26.000000000 +0100
|
||
+++ gdb-7.0.50.20100121/gdb/parse.c 2010-01-21 15:16:15.000000000 +0100
|
||
@@ -516,6 +516,11 @@ write_exp_msymbol (struct minimal_symbol
|
||
write_exp_elt_type (objfile_type (objfile)->nodebug_text_symbol);
|
||
break;
|
||
|
||
+ case mst_text_gnu_ifunc:
|
||
+ write_exp_elt_type (objfile_type (objfile)
|
||
+ ->nodebug_text_gnu_ifunc_symbol);
|
||
+ break;
|
||
+
|
||
case mst_data:
|
||
case mst_file_data:
|
||
case mst_bss:
|
||
Index: gdb-7.0.50.20100121/gdb/ppc-linux-tdep.c
|
||
===================================================================
|
||
--- gdb-7.0.50.20100121.orig/gdb/ppc-linux-tdep.c 2010-01-04 15:57:44.000000000 +0100
|
||
+++ gdb-7.0.50.20100121/gdb/ppc-linux-tdep.c 2010-01-21 15:15:41.000000000 +0100
|
||
@@ -48,6 +48,7 @@
|
||
#include "arch-utils.h"
|
||
#include "spu-tdep.h"
|
||
#include "xml-syscall.h"
|
||
+#include "linux-tdep.h"
|
||
|
||
#include "features/rs6000/powerpc-32l.c"
|
||
#include "features/rs6000/powerpc-altivec32l.c"
|
||
@@ -672,8 +673,19 @@ ppc64_linux_convert_from_func_ptr_addr (
|
||
res = bfd_get_section_contents (s->bfd, s->the_bfd_section,
|
||
&buf, addr - s->addr, 8);
|
||
if (res != 0)
|
||
- return extract_unsigned_integer (buf, 8, byte_order)
|
||
- - bfd_section_vma (s->bfd, s->the_bfd_section) + s->addr;
|
||
+ {
|
||
+ CORE_ADDR pc, resolved;
|
||
+
|
||
+ pc = extract_unsigned_integer (buf, 8, byte_order)
|
||
+ - bfd_section_vma (s->bfd, s->the_bfd_section) + s->addr;
|
||
+
|
||
+ resolved = linux_convert_from_func_and_ptr (gdbarch, addr, pc);
|
||
+ if (resolved != pc)
|
||
+ pc = ppc64_linux_convert_from_func_ptr_addr (gdbarch, resolved,
|
||
+ targ);
|
||
+
|
||
+ return pc;
|
||
+ }
|
||
}
|
||
|
||
return addr;
|
||
Index: gdb-7.0.50.20100121/gdb/sh-linux-tdep.c
|
||
===================================================================
|
||
--- gdb-7.0.50.20100121.orig/gdb/sh-linux-tdep.c 2010-01-01 08:31:41.000000000 +0100
|
||
+++ gdb-7.0.50.20100121/gdb/sh-linux-tdep.c 2010-01-21 15:15:41.000000000 +0100
|
||
@@ -25,6 +25,7 @@
|
||
|
||
#include "glibc-tdep.h"
|
||
#include "sh-tdep.h"
|
||
+#include "linux-tdep.h"
|
||
|
||
#define REGSx16(base) \
|
||
{(base), 0}, \
|
||
@@ -89,6 +90,9 @@ sh_linux_init_abi (struct gdbarch_info i
|
||
tdep->core_gregmap = (struct sh_corefile_regmap *)gregs_table;
|
||
tdep->core_fpregmap = (struct sh_corefile_regmap *)fpregs_table;
|
||
}
|
||
+
|
||
+ set_gdbarch_convert_from_func_ptr_addr (gdbarch,
|
||
+ linux_convert_from_func_ptr_addr);
|
||
}
|
||
|
||
/* Provide a prototype to silence -Wmissing-prototypes. */
|
||
Index: gdb-7.0.50.20100121/gdb/solib-svr4.c
|
||
===================================================================
|
||
--- gdb-7.0.50.20100121.orig/gdb/solib-svr4.c 2010-01-21 15:15:22.000000000 +0100
|
||
+++ gdb-7.0.50.20100121/gdb/solib-svr4.c 2010-01-21 15:15:41.000000000 +0100
|
||
@@ -1257,7 +1257,8 @@ svr4_in_dynsym_resolve_code (CORE_ADDR p
|
||
&& pc < info->interp_text_sect_high)
|
||
|| (pc >= info->interp_plt_sect_low
|
||
&& pc < info->interp_plt_sect_high)
|
||
- || in_plt_section (pc, NULL));
|
||
+ || in_plt_section (pc, NULL)
|
||
+ || in_gnu_ifunc_stub (pc));
|
||
}
|
||
|
||
/* Given an executable's ABFD and target, compute the entry-point
|
||
Index: gdb-7.0.50.20100121/gdb/sparc-linux-tdep.c
|
||
===================================================================
|
||
--- gdb-7.0.50.20100121.orig/gdb/sparc-linux-tdep.c 2010-01-01 08:31:42.000000000 +0100
|
||
+++ gdb-7.0.50.20100121/gdb/sparc-linux-tdep.c 2010-01-21 15:15:41.000000000 +0100
|
||
@@ -32,6 +32,7 @@
|
||
#include "symtab.h"
|
||
#include "trad-frame.h"
|
||
#include "tramp-frame.h"
|
||
+#include "linux-tdep.h"
|
||
|
||
#include "sparc-tdep.h"
|
||
|
||
@@ -279,6 +280,9 @@ sparc32_linux_init_abi (struct gdbarch_i
|
||
dwarf2_append_unwinders (gdbarch);
|
||
|
||
set_gdbarch_write_pc (gdbarch, sparc_linux_write_pc);
|
||
+
|
||
+ set_gdbarch_convert_from_func_ptr_addr (gdbarch,
|
||
+ linux_convert_from_func_ptr_addr);
|
||
}
|
||
|
||
/* Provide a prototype to silence -Wmissing-prototypes. */
|
||
Index: gdb-7.0.50.20100121/gdb/sparc64-linux-tdep.c
|
||
===================================================================
|
||
--- gdb-7.0.50.20100121.orig/gdb/sparc64-linux-tdep.c 2010-01-01 08:31:42.000000000 +0100
|
||
+++ gdb-7.0.50.20100121/gdb/sparc64-linux-tdep.c 2010-01-21 15:15:41.000000000 +0100
|
||
@@ -31,6 +31,7 @@
|
||
#include "symtab.h"
|
||
#include "trad-frame.h"
|
||
#include "tramp-frame.h"
|
||
+#include "linux-tdep.h"
|
||
|
||
#include "sparc64-tdep.h"
|
||
|
||
@@ -244,6 +245,9 @@ sparc64_linux_init_abi (struct gdbarch_i
|
||
tdep->step_trap = sparc64_linux_step_trap;
|
||
|
||
set_gdbarch_write_pc (gdbarch, sparc64_linux_write_pc);
|
||
+
|
||
+ set_gdbarch_convert_from_func_ptr_addr (gdbarch,
|
||
+ linux_convert_from_func_ptr_addr);
|
||
}
|
||
|
||
|
||
Index: gdb-7.0.50.20100121/gdb/symmisc.c
|
||
===================================================================
|
||
--- gdb-7.0.50.20100121.orig/gdb/symmisc.c 2010-01-21 15:13:27.000000000 +0100
|
||
+++ gdb-7.0.50.20100121/gdb/symmisc.c 2010-01-21 15:15:41.000000000 +0100
|
||
@@ -294,6 +294,9 @@ dump_msymbols (struct objfile *objfile,
|
||
case mst_text:
|
||
ms_type = 'T';
|
||
break;
|
||
+ case mst_text_gnu_ifunc:
|
||
+ ms_type = 'i';
|
||
+ break;
|
||
case mst_solib_trampoline:
|
||
ms_type = 'S';
|
||
break;
|
||
Index: gdb-7.0.50.20100121/gdb/symtab.c
|
||
===================================================================
|
||
--- gdb-7.0.50.20100121.orig/gdb/symtab.c 2010-01-21 15:13:27.000000000 +0100
|
||
+++ gdb-7.0.50.20100121/gdb/symtab.c 2010-01-21 15:15:41.000000000 +0100
|
||
@@ -3244,7 +3244,7 @@ search_symbols (char *regexp, domain_enu
|
||
{mst_file_data, mst_solib_trampoline, mst_abs, mst_unknown};
|
||
static enum minimal_symbol_type types4[]
|
||
=
|
||
- {mst_file_bss, mst_text, mst_abs, mst_unknown};
|
||
+ {mst_file_bss, mst_text_gnu_ifunc, mst_abs, mst_unknown};
|
||
enum minimal_symbol_type ourtype;
|
||
enum minimal_symbol_type ourtype2;
|
||
enum minimal_symbol_type ourtype3;
|
||
Index: gdb-7.0.50.20100121/gdb/symtab.h
|
||
===================================================================
|
||
--- gdb-7.0.50.20100121.orig/gdb/symtab.h 2010-01-21 15:11:09.000000000 +0100
|
||
+++ gdb-7.0.50.20100121/gdb/symtab.h 2010-01-21 15:15:41.000000000 +0100
|
||
@@ -280,6 +280,8 @@ enum minimal_symbol_type
|
||
{
|
||
mst_unknown = 0, /* Unknown type, the default */
|
||
mst_text, /* Generally executable instructions */
|
||
+ mst_text_gnu_ifunc, /* Executable code returning address
|
||
+ of executable code */
|
||
mst_data, /* Generally initialized data */
|
||
mst_bss, /* Generally uninitialized data */
|
||
mst_abs, /* Generally absolute (nonrelocatable) */
|
||
@@ -1157,6 +1159,8 @@ extern struct minimal_symbol *lookup_min
|
||
|
||
extern struct minimal_symbol *lookup_minimal_symbol_by_pc (CORE_ADDR);
|
||
|
||
+extern int in_gnu_ifunc_stub (CORE_ADDR pc);
|
||
+
|
||
extern struct minimal_symbol
|
||
*lookup_minimal_symbol_by_pc_section (CORE_ADDR, struct obj_section *);
|
||
|
||
Index: gdb-7.0.50.20100121/gdb/testsuite/gdb.base/gnu-ifunc-lib.c
|
||
===================================================================
|
||
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
|
||
+++ gdb-7.0.50.20100121/gdb/testsuite/gdb.base/gnu-ifunc-lib.c 2010-01-21 15:15:41.000000000 +0100
|
||
@@ -0,0 +1,54 @@
|
||
+/* This testcase is part of GDB, the GNU debugger.
|
||
+
|
||
+ Copyright 2009 Free Software Foundation, Inc.
|
||
+
|
||
+ This program is free software; you can redistribute it and/or modify
|
||
+ it under the terms of the GNU General Public License as published by
|
||
+ the Free Software Foundation; either version 3 of the License, or
|
||
+ (at your option) any later version.
|
||
+
|
||
+ This program is distributed in the hope that it will be useful,
|
||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
+ GNU General Public License for more details.
|
||
+
|
||
+ You should have received a copy of the GNU General Public License
|
||
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <assert.h>
|
||
+
|
||
+typedef int (*final_t) (int arg);
|
||
+
|
||
+static int
|
||
+init_stub (int arg)
|
||
+{
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+static int
|
||
+final (int arg)
|
||
+{
|
||
+ return arg + 1;
|
||
+}
|
||
+
|
||
+static volatile int gnu_ifunc_initialized;
|
||
+
|
||
+void
|
||
+gnu_ifunc_pre (void)
|
||
+{
|
||
+ assert (!gnu_ifunc_initialized);
|
||
+
|
||
+ gnu_ifunc_initialized = 1;
|
||
+}
|
||
+
|
||
+final_t gnu_ifuncX (void) asm ("gnu_ifunc");
|
||
+asm (".type gnu_ifunc, @gnu_indirect_function");
|
||
+
|
||
+final_t
|
||
+gnu_ifuncX (void)
|
||
+{
|
||
+ if (!gnu_ifunc_initialized)
|
||
+ return init_stub;
|
||
+ else
|
||
+ return final;
|
||
+}
|
||
Index: gdb-7.0.50.20100121/gdb/testsuite/gdb.base/gnu-ifunc.c
|
||
===================================================================
|
||
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
|
||
+++ gdb-7.0.50.20100121/gdb/testsuite/gdb.base/gnu-ifunc.c 2010-01-21 15:15:41.000000000 +0100
|
||
@@ -0,0 +1,36 @@
|
||
+/* This testcase is part of GDB, the GNU debugger.
|
||
+
|
||
+ Copyright 2009 Free Software Foundation, Inc.
|
||
+
|
||
+ This program is free software; you can redistribute it and/or modify
|
||
+ it under the terms of the GNU General Public License as published by
|
||
+ the Free Software Foundation; either version 3 of the License, or
|
||
+ (at your option) any later version.
|
||
+
|
||
+ This program is distributed in the hope that it will be useful,
|
||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
+ GNU General Public License for more details.
|
||
+
|
||
+ You should have received a copy of the GNU General Public License
|
||
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <assert.h>
|
||
+
|
||
+extern int gnu_ifunc (int arg);
|
||
+extern void gnu_ifunc_pre (void);
|
||
+
|
||
+int
|
||
+main (void)
|
||
+{
|
||
+ int i;
|
||
+
|
||
+ gnu_ifunc_pre ();
|
||
+
|
||
+ i = gnu_ifunc (1); /* break-at-call */
|
||
+ assert (i == 2);
|
||
+
|
||
+ gnu_ifunc (2); /* break-at-nextcall */
|
||
+
|
||
+ return 0; /* break-at-exit */
|
||
+}
|
||
Index: gdb-7.0.50.20100121/gdb/testsuite/gdb.base/gnu-ifunc.exp
|
||
===================================================================
|
||
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
|
||
+++ gdb-7.0.50.20100121/gdb/testsuite/gdb.base/gnu-ifunc.exp 2010-01-21 15:15:41.000000000 +0100
|
||
@@ -0,0 +1,115 @@
|
||
+# Copyright (C) 2009 Free Software Foundation, Inc.
|
||
+
|
||
+# This program is free software; you can redistribute it and/or modify
|
||
+# it under the terms of the GNU General Public License as published by
|
||
+# the Free Software Foundation; either version 3 of the License, or
|
||
+# (at your option) any later version.
|
||
+#
|
||
+# This program is distributed in the hope that it will be useful,
|
||
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
+# GNU General Public License for more details.
|
||
+#
|
||
+# You should have received a copy of the GNU General Public License
|
||
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
+
|
||
+if {[skip_shlib_tests]} {
|
||
+ return 0
|
||
+}
|
||
+
|
||
+set testfile "gnu-ifunc"
|
||
+set srcfile ${testfile}.c
|
||
+set binfile ${objdir}/${subdir}/${testfile}
|
||
+
|
||
+set libfile "${testfile}-lib"
|
||
+set libsrc ${libfile}.c
|
||
+set lib_so ${objdir}/${subdir}/${libfile}.so
|
||
+
|
||
+set lib_nodebug_so_base ${libfile}-nodebug.so
|
||
+set lib_nodebug_so ${objdir}/${subdir}/${lib_nodebug_so_base}
|
||
+
|
||
+# {debug} provides DWARF symbol gnu_ifuncX confusing the ELF symbol
|
||
+# gnu_ifunc during address->symbol resolution for printing the symbol.
|
||
+# Still we need it here for "step"ping into the function.
|
||
+set lib_opts [list debug]
|
||
+set lib_nodebug_opts [list]
|
||
+set exec_opts [list debug shlib=$lib_so]
|
||
+
|
||
+if [get_compiler_info ${binfile}] {
|
||
+ return -1
|
||
+}
|
||
+
|
||
+if { [gdb_compile_shlib ${srcdir}/${subdir}/$libsrc $lib_so $lib_opts] != ""
|
||
+ || [gdb_compile ${srcdir}/${subdir}/$srcfile $binfile executable $exec_opts] != ""} {
|
||
+ untested "Could not compile either $libsrc or $srcfile."
|
||
+ return -1
|
||
+}
|
||
+
|
||
+# Start with a fresh gdb.
|
||
+
|
||
+clean_restart $testfile
|
||
+gdb_load_shlibs ${lib_so}
|
||
+
|
||
+if ![runto_main] then {
|
||
+ fail "Can't run to main"
|
||
+ return 1;
|
||
+}
|
||
+
|
||
+# The "if" condition is artifical to test regression of a format patch.
|
||
+gdb_breakpoint "[gdb_get_line_number "break-at-nextcall"] if i && gnu_ifunc (i) != 42"
|
||
+
|
||
+gdb_breakpoint [gdb_get_line_number "break-at-call"]
|
||
+gdb_continue_to_breakpoint "break-at-call" ".*break-at-call.*"
|
||
+
|
||
+# Test GDB will automatically indirect the call.
|
||
+
|
||
+gdb_test "p gnu_ifunc (3)" " = 4"
|
||
+
|
||
+# Test GDB will skip the gnu_ifunc resolver on first call.
|
||
+
|
||
+gdb_test "step" "\r\nfinal .*"
|
||
+
|
||
+# Test GDB will not break before the final chosen implementation.
|
||
+
|
||
+# Also test a format patch regression:
|
||
+# Continuing.
|
||
+# Error in testing breakpoint condition:
|
||
+# Attempt to take address of value not located in memory.
|
||
+#
|
||
+# Breakpoint 2, main () at ./gdb.base/gnu-ifunc.c:33
|
||
+
|
||
+gdb_test "continue" "Continuing.\r\n\r\nBreakpoint .* (at|in) .*break-at-nextcall.*" \
|
||
+ "continue to break-at-nextcall"
|
||
+
|
||
+gdb_breakpoint "gnu_ifunc"
|
||
+
|
||
+gdb_continue_to_breakpoint "nextcall gnu_ifunc"
|
||
+
|
||
+gdb_test "frame" "#0 +(0x\[0-9a-f\]+ in +)?final \\(.*" "nextcall gnu_ifunc skipped"
|
||
+
|
||
+
|
||
+# Compare the two different addresses:
|
||
+
|
||
+gdb_test "p gnu_ifunc" " = {<text variable, no debug info>} 0x\[0-9a-f\]+ <final>" "p gnu_ifunc executing"
|
||
+gdb_test "info sym gnu_ifunc" "final in section .*" "info sym gnu_ifunc executing"
|
||
+
|
||
+set test "info addr gnu_ifunc"
|
||
+gdb_test_multiple $test $test {
|
||
+ -re "Symbol \"gnu_ifunc\" is at (0x\[0-9a-f\]+) in .*$gdb_prompt $" {
|
||
+ pass $test
|
||
+ }
|
||
+}
|
||
+gdb_test "info sym $expect_out(1,string)" "gnu_ifunc in section .*" "info sym <gnu_ifunc-address>"
|
||
+
|
||
+# <*gnu_ifunc> would be an incorrect resolution from DW_AT_MIPS_linkage_name.
|
||
+# We do not use {debug} build option for this purpose.
|
||
+
|
||
+if { [gdb_compile_shlib ${srcdir}/${subdir}/$libsrc $lib_nodebug_so $lib_nodebug_opts] != ""} {
|
||
+ untested "Could not compile either $libsrc."
|
||
+ return -1
|
||
+}
|
||
+
|
||
+clean_restart $lib_nodebug_so_base
|
||
+
|
||
+gdb_test "p gnu_ifunc" " = {<text gnu-ifunc variable, no debug info>} 0x\[0-9a-f\]+ <gnu_ifunc>" "p gnu_ifunc not executing without debug"
|
||
+gdb_test "info sym gnu_ifunc" "gnu_ifunc in section .*" "info sym gnu_ifunc not executing without debug"
|
||
Index: gdb-7.0.50.20100121/gdb/xtensa-linux-tdep.c
|
||
===================================================================
|
||
--- gdb-7.0.50.20100121.orig/gdb/xtensa-linux-tdep.c 2010-01-01 08:31:46.000000000 +0100
|
||
+++ gdb-7.0.50.20100121/gdb/xtensa-linux-tdep.c 2010-01-21 15:15:41.000000000 +0100
|
||
@@ -22,6 +22,7 @@
|
||
|
||
#include "solib-svr4.h"
|
||
#include "symtab.h"
|
||
+#include "linux-tdep.h"
|
||
|
||
/* OS specific initialization of gdbarch. */
|
||
|
||
@@ -30,6 +31,9 @@ xtensa_linux_init_abi (struct gdbarch_in
|
||
{
|
||
set_solib_svr4_fetch_link_map_offsets
|
||
(gdbarch, svr4_ilp32_fetch_link_map_offsets);
|
||
+
|
||
+ set_gdbarch_convert_from_func_ptr_addr (gdbarch,
|
||
+ linux_convert_from_func_ptr_addr);
|
||
}
|
||
|
||
/* Provide a prototype to silence -Wmissing-prototypes. */
|