From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 20170 invoked by alias); 21 May 2012 00:36:04 -0000 Received: (qmail 20036 invoked by uid 22791); 21 May 2012 00:36:00 -0000 X-SWARE-Spam-Status: No, hits=-2.0 required=5.0 tests=BAYES_00,KHOP_RCVD_UNTRUST,RCVD_IN_DNSWL_LOW,RCVD_IN_HOSTKARMA_YE,TW_GJ X-Spam-Check-By: sourceware.org Received: from mail-yx0-f169.google.com (HELO mail-yx0-f169.google.com) (209.85.213.169) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 21 May 2012 00:35:34 +0000 Received: by yenm7 with SMTP id m7so4732052yen.0 for ; Sun, 20 May 2012 17:35:33 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=message-id:subject:from:to:date:organization:content-type:x-mailer :content-transfer-encoding:mime-version:x-gm-message-state; bh=aGtfSc2hm/GN3lB8Ok5BRSeVrhHd2+ypOIlrYNANQHE=; b=jsh38WQtq8w9Z2s6sO7TV7HZYUIkCf1G1mYrqb+WSU7INso+nsPQokO/Swr3yN27op RFUStscuQR7xlycGv4uURHImVYIcGKuPW5H3gMnhv+QLhMOU1leQlzNertdztXdjejWo yOLtcZBwhj3kI/wGjMFQ9dVkSb7TCOulTwLC4H5DtKxL2wirNOHl+5vxHtNefGASfsQt k2xWWrobCq15Ks7et4NTR4urknGCWjvY1OgdXhJ3JHNX0uSd/IoVwsNhBLGp8QC/qPLg i1oOP31TNFVEInBajZRvG4tXgGdQEaPrjj7SzaI6LclAFnVc+nmSRsy1vzuaKnZYmYf+ 4s/g== Received: by 10.236.155.74 with SMTP id i50mr21464798yhk.2.1337560533623; Sun, 20 May 2012 17:35:33 -0700 (PDT) Received: from [192.168.1.50] ([177.96.98.200]) by mx.google.com with ESMTPS id d21sm69838220yhl.9.2012.05.20.17.35.30 (version=SSLv3 cipher=OTHER); Sun, 20 May 2012 17:35:32 -0700 (PDT) Message-ID: <1337560528.4363.13.camel@hactar> Subject: [patch] Support bionic's jmp_buf. From: Thiago Jung Bauermann To: gdb-patches ml Date: Mon, 21 May 2012 00:36:00 -0000 Content-Type: text/plain; charset="ISO-8859-1" Content-Transfer-Encoding: 7bit Mime-Version: 1.0 X-Gm-Message-State: ALoCoQniHsFplNMD8pAM75lFtHK0kMlARN8S92AWFDFM6WOLwjNvsbYsoOQyhIAP8fZt11j2jBB4 X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2012-05/txt/msg00758.txt.bz2 Hello, Android uses a libc (bionic) which is derived from BSD instead of glibc, and stores the PC value at a different location in the jump buffer than regular arm-linux. Also, since there's no PC mangling this code works even without SystemTap probes. I'm using the ELF interpreter field to identify an Android binary (the program loader is /system/bin/linker). Also, I had to change gdbarch_tdep->jb_pc to a function so that the code to determine which kind of program we are dealing with runs when the value is actually needed. This is because by the time arm_linux_init_abi is called exec_bfd hasn't been set yet so there's no way to peek at the ELF interpreter field. This patch fixes gdb.base/longjmp.exp. There are no regressions on arm-linux native, arm-linux remote or i386-linux native. Ok? -- []'s Thiago Jung Bauermann Linaro Toolchain Working Group 2012-05-20 Thiago Jung Bauermann Support bionic's jmp_buf. * arm-linux-tdep.c (ARM_LINUX_JB_PC_ANDROID): New macro. (is_target_linux_android): New function. (arm_linux_jb_pc): Likewise. (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. * solib-svr4.c (find_program_interpreter): Remove static keyword. 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..b9d67b0 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,54 @@ arm_stap_parse_special_token (struct gdbarch *gdbarch, return 1; } +/* Determines whether the inferior is an Android application. */ + +static int +is_target_linux_android (void) +{ + int ret = 0; + gdb_byte *interp; + + interp = find_elf_program_interpreter (); + if (interp) + { + ret = !strcmp (interp, "/system/bin/linker"); + xfree (interp); + } + + return ret; +} + +/* 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 (is_target_linux_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 +1261,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 df5dea7..d1aa6b5 100644 --- a/gdb/arm-tdep.c +++ b/gdb/arm-tdep.c @@ -9083,12 +9083,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; @@ -10132,7 +10133,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. */ @@ -10236,7 +10237,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/solib-svr4.c b/gdb/solib-svr4.c index 69d3cb5..24f224f 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; @@ -1520,7 +1520,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 */