This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
Re: [patch] Support bionic's jmp_buf.
- From: Thiago Jung Bauermann <bauerman at br dot ibm dot com>
- To: Pedro Alves <palves at redhat dot com>
- Cc: gdb-patches ml <gdb-patches at sourceware dot org>, Yao Qi <yao at codesourcery dot com>, "Schnell, Fabian" <fabian dot schnell at linux dot intel dot com>
- Date: Wed, 04 Jul 2012 18:07:32 -0300
- Subject: Re: [patch] Support bionic's jmp_buf.
- References: <1337560528.4363.13.camel@hactar> <4FBA2920.4070909@redhat.com> <1337623164.22073.9.camel@hactar> <1340574375.31308.7.camel@hactar> <4FEADDDE.6020904@redhat.com>
On Wed, 2012-06-27 at 11:18 +0100, Pedro Alves wrote:
> On 06/24/2012 10:46 PM, Thiago Jung Bauermann wrote:
> > I submitted a patch to bionic which adds a .note.ABI-tag to Android
> > binaries:
> >
> > https://android-review.googlesource.com/37590
> > The note has a flag which is set to 1 if the binary is for the Android
> > platform.
> >
> > The patch was accepted by the Google engineers and applied to their
> > internal tree. It wasn't merged yet to the AOSP tree because of
> > conflicts with some of their internal patches, but will be in the near
> > future.
>
> Thank you very much for persevering. I think that using "GNU" as
> ABI_VENDOR for Android isn't the best thing to do, but from skimming
> the binutils@ list I see you're already addressing that.
Right. I updated the bionic patch in the link above to
use .note.android.ident, which is similar to .note.netbsd.ident
and .note.openbsd.ident.
This patch uses that note, and also moves is_target_linux_android to
linux-tdep.c. The function is now called linux_is_target_android for
consistency with other functions in that file.
--
[]'s
Thiago Jung Bauermann
IBM Linux Technology Center
2012-07-04 Thiago Jung Bauermann <thiago.bauermann@linaro.org>
Support bionic's jmp_buf.
* arm-linux-tdep.c (ARM_LINUX_JB_PC_ANDROID): New macro.
(arm_linux_jb_pc): New function.
(arm_linux_init_abi): Set tdep->jb_pc to arm_linux_jb_pc
instead of determining the jb_pc value right away.
* arm-tdep.c (arm_get_longjmp_target): Call tdep->jb_pc.
(arm_gdbarch_init): tdep->jb_pc is now a pointer. Assign it
and test its value accordingly.
* arm-tdep.h (struct gdbarch_tdep): Change jb_pc to a
function pointer.
* arm-wince-tdep.c (arm_wince_jb_pc): New function.
(arm_wince_init_abi): Set tdep->jb_pc to arm_wince_jb_pc.
* armnbsd-tdep.c (arm_netbsd_jb_pc): New function.
(arm_netbsd_init_abi_common): Set tdep->jb_pc to arm_netbsd_jb_pc.
* armobsd-tdep.c (arm_obsd_jb_pc): New function.
(armobsd_init_abi): Set tdep->jb_pc to arm_obsd_jb_pc.
* linux-tdep.c (NT_ANDROID_IDENT): New macro.
(linux_is_target_android): New function.
* linux-tdep.h (linux_is_target_android): New prototype.
* osabi.c (check_note): Make function non-static.
* osabi.h (check_note): New prototype.
* solib-svr4.c (find_program_interpreter): Make function non-static.
Rename to ...
(find_elf_program_interpreter): ... this.
* solib-svr4.h (find_program_interpreter): New prototype.
diff --git a/gdb/arm-linux-tdep.c b/gdb/arm-linux-tdep.c
index f4eaa5c..d35cfd3 100644
--- a/gdb/arm-linux-tdep.c
+++ b/gdb/arm-linux-tdep.c
@@ -105,6 +105,7 @@ static const char arm_linux_thumb2_le_breakpoint[] = { 0xf0, 0xf7, 0x00, 0xa0 };
#define ARM_LINUX_JB_ELEMENT_SIZE INT_REGISTER_SIZE
#define ARM_LINUX_JB_PC_FPA 21
#define ARM_LINUX_JB_PC_EABI 9
+#define ARM_LINUX_JB_PC_ANDROID 29
/*
Dynamic Linking on ARM GNU/Linux
@@ -1178,6 +1179,36 @@ arm_stap_parse_special_token (struct gdbarch *gdbarch,
return 1;
}
+/* Implements the gdbarch_tdep.jb_pc function in arm-tdep.h. */
+
+static CORE_ADDR
+arm_linux_jb_pc (struct gdbarch_tdep *tdep)
+{
+ int jb_pc;
+
+ switch (tdep->fp_model)
+ {
+ case ARM_FLOAT_FPA:
+ jb_pc = ARM_LINUX_JB_PC_FPA;
+ break;
+ case ARM_FLOAT_SOFT_FPA:
+ case ARM_FLOAT_SOFT_VFP:
+ case ARM_FLOAT_VFP:
+ jb_pc = ARM_LINUX_JB_PC_EABI;
+ break;
+ default:
+ internal_error
+ (__FILE__, __LINE__,
+ _("arm_linux_init_abi: Floating point model not supported"));
+ break;
+ }
+
+ if (linux_is_target_android ())
+ jb_pc = ARM_LINUX_JB_PC_ANDROID;
+
+ return jb_pc;
+}
+
static void
arm_linux_init_abi (struct gdbarch_info info,
struct gdbarch *gdbarch)
@@ -1212,22 +1243,7 @@ arm_linux_init_abi (struct gdbarch_info info,
if (tdep->fp_model == ARM_FLOAT_AUTO)
tdep->fp_model = ARM_FLOAT_FPA;
- switch (tdep->fp_model)
- {
- case ARM_FLOAT_FPA:
- tdep->jb_pc = ARM_LINUX_JB_PC_FPA;
- break;
- case ARM_FLOAT_SOFT_FPA:
- case ARM_FLOAT_SOFT_VFP:
- case ARM_FLOAT_VFP:
- tdep->jb_pc = ARM_LINUX_JB_PC_EABI;
- break;
- default:
- internal_error
- (__FILE__, __LINE__,
- _("arm_linux_init_abi: Floating point model not supported"));
- break;
- }
+ tdep->jb_pc = arm_linux_jb_pc;
tdep->jb_elt_size = ARM_LINUX_JB_ELEMENT_SIZE;
set_solib_svr4_fetch_link_map_offsets
diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
index 568ace5..f925d44 100644
--- a/gdb/arm-tdep.c
+++ b/gdb/arm-tdep.c
@@ -9086,12 +9086,13 @@ arm_get_longjmp_target (struct frame_info *frame, CORE_ADDR *pc)
struct gdbarch *gdbarch = get_frame_arch (frame);
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- CORE_ADDR jb_addr;
+ CORE_ADDR jb_addr, jb_pc;
char buf[INT_REGISTER_SIZE];
-
+
jb_addr = get_frame_register_unsigned (frame, ARM_A1_REGNUM);
+ jb_pc = tdep->jb_pc (tdep);
- if (target_read_memory (jb_addr + tdep->jb_pc * tdep->jb_elt_size, buf,
+ if (target_read_memory (jb_addr + jb_pc * tdep->jb_elt_size, buf,
INT_REGISTER_SIZE))
return 0;
@@ -10135,7 +10136,7 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
/* This should be low enough for everything. */
tdep->lowest_pc = 0x20;
- tdep->jb_pc = -1; /* Longjump support not enabled by default. */
+ tdep->jb_pc = NULL; /* Longjump support not enabled by default. */
/* The default, for both APCS and AAPCS, is to return small
structures in registers. */
@@ -10239,7 +10240,7 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
if (tdep->fp_model == ARM_FLOAT_AUTO)
tdep->fp_model = ARM_FLOAT_SOFT_FPA;
- if (tdep->jb_pc >= 0)
+ if (tdep->jb_pc != NULL)
set_gdbarch_get_longjmp_target (gdbarch, arm_get_longjmp_target);
/* Floating point sizes and format. */
diff --git a/gdb/arm-tdep.h b/gdb/arm-tdep.h
index 97596d5..b95d548 100644
--- a/gdb/arm-tdep.h
+++ b/gdb/arm-tdep.h
@@ -185,9 +185,9 @@ struct gdbarch_tdep
const char *thumb2_breakpoint;
int thumb2_breakpoint_size;
- int jb_pc; /* Offset to PC value in jump buffer.
- If this is negative, longjmp support
- will be disabled. */
+ /* Return offset to PC value in jump buffer. If this is NULL, longjmp
+ support will be disabled. */
+ CORE_ADDR (*jb_pc) (struct gdbarch_tdep *tdep);
size_t jb_elt_size; /* And the size of each entry in the buf. */
/* Convention for returning structures. */
diff --git a/gdb/arm-wince-tdep.c b/gdb/arm-wince-tdep.c
index 5bc6473..ce04ba0 100644
--- a/gdb/arm-wince-tdep.c
+++ b/gdb/arm-wince-tdep.c
@@ -111,6 +111,14 @@ arm_wince_skip_main_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
return pc;
}
+/* Implements the gdbarch_tdep.jb_pc function in arm-tdep.h. */
+
+static CORE_ADDR
+arm_wince_jb_pc (struct gdbarch_tdep *tdep)
+{
+ return ARM_WINCE_JB_PC;
+}
+
static void
arm_wince_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
{
@@ -124,7 +132,7 @@ arm_wince_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
tdep->fp_model = ARM_FLOAT_SOFT_VFP;
- tdep->jb_pc = ARM_WINCE_JB_PC;
+ tdep->jb_pc = arm_wince_jb_pc;
tdep->jb_elt_size = ARM_WINCE_JB_ELEMENT_SIZE;
/* On ARM WinCE char defaults to signed. */
diff --git a/gdb/armnbsd-tdep.c b/gdb/armnbsd-tdep.c
index 19aa000..144bd85 100644
--- a/gdb/armnbsd-tdep.c
+++ b/gdb/armnbsd-tdep.c
@@ -36,6 +36,14 @@ static const char arm_nbsd_arm_be_breakpoint[] = {0xe6, 0x00, 0x00, 0x11};
static const char arm_nbsd_thumb_le_breakpoint[] = {0xfe, 0xde};
static const char arm_nbsd_thumb_be_breakpoint[] = {0xde, 0xfe};
+/* Implements the gdbarch_tdep.jb_pc function in arm-tdep.h. */
+
+static CORE_ADDR
+arm_netbsd_jb_pc (struct gdbarch_tdep *tdep)
+{
+ return ARM_NBSD_JB_PC;
+}
+
static void
arm_netbsd_init_abi_common (struct gdbarch_info info,
struct gdbarch *gdbarch)
@@ -64,7 +72,7 @@ arm_netbsd_init_abi_common (struct gdbarch_info info,
_("arm_gdbarch_init: bad byte order for float format"));
}
- tdep->jb_pc = ARM_NBSD_JB_PC;
+ tdep->jb_pc = arm_netbsd_jb_pc;
tdep->jb_elt_size = ARM_NBSD_JB_ELEMENT_SIZE;
/* Single stepping. */
diff --git a/gdb/armobsd-tdep.c b/gdb/armobsd-tdep.c
index fab4e42..e48eeaa 100644
--- a/gdb/armobsd-tdep.c
+++ b/gdb/armobsd-tdep.c
@@ -74,6 +74,14 @@ static const struct tramp_frame armobsd_sigframe =
static const char arm_obsd_thumb_le_breakpoint[] = {0xfe, 0xdf};
static const char arm_obsd_thumb_be_breakpoint[] = {0xdf, 0xfe};
+/* Implements the gdbarch_tdep.jb_pc function in arm-tdep.h. */
+
+static CORE_ADDR
+armobsd_jb_pc (struct gdbarch_tdep *tdep)
+{
+ return 24;
+}
+
static void
armobsd_init_abi (struct gdbarch_info info,
struct gdbarch *gdbarch)
@@ -90,7 +98,7 @@ armobsd_init_abi (struct gdbarch_info info,
(gdbarch, svr4_ilp32_fetch_link_map_offsets);
set_gdbarch_skip_solib_resolver (gdbarch, obsd_skip_solib_resolver);
- tdep->jb_pc = 24;
+ tdep->jb_pc = armobsd_jb_pc;
tdep->jb_elt_size = 4;
set_gdbarch_regset_from_core_section
diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c
index b6f2efb..42da96c 100644
--- a/gdb/linux-tdep.c
+++ b/gdb/linux-tdep.c
@@ -30,6 +30,8 @@
#include "elf-bfd.h" /* for elfcore_write_* */
#include "inferior.h"
#include "cli/cli-utils.h"
+#include "osabi.h"
+#include "solib-svr4.h"
#include <ctype.h>
@@ -188,6 +190,49 @@ linux_has_shared_address_space (struct gdbarch *gdbarch)
return target_is_uclinux;
}
+/* Type of the .note.android.ident note. Note vendor is "Android". */
+#define NT_ANDROID_IDENT 1
+
+/* Determines whether the inferior is an Android application. */
+
+int
+linux_is_target_android (void)
+{
+ int ret = 0;
+ gdb_byte *interp;
+
+ if (exec_bfd
+ && bfd_get_flavour (exec_bfd) == bfd_target_elf_flavour)
+ {
+ struct bfd_section *ident;
+
+ ident = bfd_get_section_by_name (exec_bfd, ".note.android.ident");
+ if (ident != NULL)
+ {
+ int sect_size = bfd_section_size (exec_bfd, ident);
+ gdb_byte *note;
+
+ note = alloca (sect_size);
+ bfd_get_section_contents (exec_bfd, ident, note, 0, sect_size);
+
+ /* Android's ident note has one 32-bit integer specifying the
+ API level expected by the application. We don't need to
+ check it yet. */
+ return check_note (exec_bfd, ident, note, "Android", 4,
+ NT_ANDROID_IDENT);
+ }
+ }
+
+ interp = find_elf_program_interpreter ();
+ if (interp)
+ {
+ ret = !strcmp (interp, "/system/bin/linker");
+ xfree (interp);
+ }
+
+ return ret;
+}
+
/* This is how we want PTIDs from core files to be printed. */
static char *
diff --git a/gdb/linux-tdep.h b/gdb/linux-tdep.h
index b211b53..1dab1c7 100644
--- a/gdb/linux-tdep.h
+++ b/gdb/linux-tdep.h
@@ -36,4 +36,6 @@ struct type *linux_get_siginfo_type (struct gdbarch *);
extern void linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch);
+extern int linux_is_target_android (void);
+
#endif /* linux-tdep.h */
diff --git a/gdb/osabi.c b/gdb/osabi.c
index faffe30..9d3eef4 100644
--- a/gdb/osabi.c
+++ b/gdb/osabi.c
@@ -372,7 +372,7 @@ gdbarch_init_osabi (struct gdbarch_info info, struct gdbarch *gdbarch)
/* Return non-zero if NOTE matches NAME, DESCSZ and TYPE. */
-static int
+int
check_note (bfd *abfd, asection *sect, const char *note,
const char *name, unsigned long descsz, unsigned long type)
{
diff --git a/gdb/osabi.h b/gdb/osabi.h
index ced2fa5..ec3b948 100644
--- a/gdb/osabi.h
+++ b/gdb/osabi.h
@@ -54,4 +54,8 @@ const char *gdbarch_osabi_name (enum gdb_osabi);
via bfd_map_over_sections. */
void generic_elf_osabi_sniff_abi_tag_sections (bfd *, asection *, void *);
+/* Return non-zero if NOTE matches NAME, DESCSZ and TYPE. */
+int check_note (bfd *abfd, asection *sect, const char *note,
+ const char *name, unsigned long descsz, unsigned long type);
+
#endif /* OSABI_H */
diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
index 307e483..cd3be82 100644
--- a/gdb/solib-svr4.c
+++ b/gdb/solib-svr4.c
@@ -496,8 +496,8 @@ read_program_header (int type, int *p_sect_size, int *p_arch_size)
/* Return program interpreter string. */
-static gdb_byte *
-find_program_interpreter (void)
+gdb_byte *
+find_elf_program_interpreter (void)
{
gdb_byte *buf = NULL;
@@ -1528,7 +1528,7 @@ enable_break (struct svr4_info *info, int from_tty)
/* Find the program interpreter; if not found, warn the user and drop
into the old breakpoint at symbol code. */
- interp_name = find_program_interpreter ();
+ interp_name = find_elf_program_interpreter ();
if (interp_name)
{
CORE_ADDR load_addr = 0;
diff --git a/gdb/solib-svr4.h b/gdb/solib-svr4.h
index f9a02c9..87f088d 100644
--- a/gdb/solib-svr4.h
+++ b/gdb/solib-svr4.h
@@ -84,4 +84,7 @@ extern struct link_map_offsets *svr4_lp64_fetch_link_map_offsets (void);
SVR4 run time loader. */
int svr4_in_dynsym_resolve_code (CORE_ADDR pc);
+/* Return program interpreter string. */
+gdb_byte *find_elf_program_interpreter (void);
+
#endif /* solib-svr4.h */