From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 3216 invoked by alias); 31 May 2012 18:18:21 -0000 Received: (qmail 3205 invoked by uid 22791); 31 May 2012 18:18:19 -0000 X-SWARE-Spam-Status: No, hits=-5.0 required=5.0 tests=AWL,BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,KHOP_RCVD_TRUST,KHOP_THREADED,RCVD_IN_DNSWL_LOW,RCVD_IN_HOSTKARMA_YE,TW_EG X-Spam-Check-By: sourceware.org Received: from mail-qa0-f41.google.com (HELO mail-qa0-f41.google.com) (209.85.216.41) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 31 May 2012 18:18:04 +0000 Received: by qabg27 with SMTP id g27so3298198qab.0 for ; Thu, 31 May 2012 11:18:03 -0700 (PDT) MIME-Version: 1.0 Received: by 10.224.33.8 with SMTP id f8mr1137850qad.11.1338488283034; Thu, 31 May 2012 11:18:03 -0700 (PDT) Received: by 10.229.192.129 with HTTP; Thu, 31 May 2012 11:18:02 -0700 (PDT) In-Reply-To: References: <20120511181737.GP29339@adacore.com> <201205202043.q4KKhRGw022215@glazunov.sibelius.xs4all.nl> <201205202138.q4KLcWBf011913@glazunov.sibelius.xs4all.nl> <201205282026.q4SKQ737007589@glazunov.sibelius.xs4all.nl> Date: Thu, 31 May 2012 18:18:00 -0000 Message-ID: Subject: Re: x32 ABI Support (was Re: Three weeks to branching (gdb 7.5 release)) From: "H.J. Lu" To: Mark Kettenis Cc: gdb-patches@sourceware.org Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable 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/msg01098.txt.bz2 On Mon, May 28, 2012 at 2:18 PM, H.J. Lu wrote: > On Mon, May 28, 2012 at 1:26 PM, Mark Kettenis = wrote: >>> Date: Sun, 20 May 2012 15:48:54 -0700 >>> From: "H.J. Lu" >>> >>> Does this one look OK. =A0I extracted x32_init_abi from amd64_x32_init_= abi >>> since amd64_x32_linux_init_abi can't call amd64_init_abi after >>> calling amd64_linux_init_abi. >> >> I guess multiple-inheritance is a bad idea, even when implemented in C ;) >> >> I really do think that amd64_x32_linux_init_abi() should call >> amd64_x32_init_abi(). =A0That way it is immediately obvious that the OS-= specific ABI inherits everything from the generic ABI. > > X32 kernel interface are highly OS specific. =A0Different OSes can implem= ent > very different kernel interfaces. =A0The only generic x32 bits are > > =A0struct gdbarch_tdep *tdep =3D gdbarch_tdep (gdbarch); > > =A0tdep->num_dword_regs =3D 17; > > =A0set_tdesc_pseudo_register_type (gdbarch, amd64_x32_pseudo_register_typ= e); > > =A0set_gdbarch_long_bit (gdbarch, 32); > =A0set_gdbarch_ptr_bit (gdbarch, 32); > > They are the same for all x32 OSes since they are determined by > hardware, not OS. > >> In order too avoid too much code duplication, the common bits should >> be split out from amd64_linux_init_abi() into a seperate function that >> gets called from both amd64_linux_init_abi() and >> amd64_x32_linux_init_abi(). =A0As I wrote earlier, it isn't entirely >> obvious that everything in amd64_linix_init_abi() applies to the x32 >> ABI. =A0So we should be conservative in moving stuff into the common >> function. =A0In fact it might be a good idea to start out with something >> like the attached diff, and gradually move things over. > > Linux x32 kernel interface shares > 90% of Linux amd64 kernel > interface (309 system calls out of 337 are the same). =A0See > 64-bit system call table in Linux kernel 3.4: > > http://git.kernel.org/?p=3Dlinux/kernel/git/stable/linux-stable.git;a=3Db= lob;f=3Darch/x86/syscalls/syscall_64.tbl;h=3Ddd29a9ea27c560a9d2fcb6e1c2983f= 8b8e9be407;hb=3DHEAD > > I believe we should start with sharing everything between Linux/x32 > and Linux/amd64. =A0We can update x32 part as we go. > >> Cheers, >> >> Mark >> >> Index: amd64-linux-tdep.c >> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D >> RCS file: /cvs/src/src/gdb/amd64-linux-tdep.c,v >> retrieving revision 1.50 >> diff -u -p -r1.50 amd64-linux-tdep.c >> --- amd64-linux-tdep.c =A012 May 2012 08:54:03 -0000 =A0 =A0 =A01.50 >> +++ amd64-linux-tdep.c =A028 May 2012 20:24:28 -0000 >> @@ -1298,8 +1298,6 @@ amd64_linux_init_abi (struct gdbarch_inf >> >> =A0 gdb_assert (tdesc_data); >> >> - =A0linux_init_abi (info, gdbarch); >> - >> =A0 tdep->gregset_reg_offset =3D amd64_linux_gregset_reg_offset; >> =A0 tdep->gregset_num_regs =3D ARRAY_SIZE (amd64_linux_gregset_reg_offse= t); >> =A0 tdep->sizeof_gregset =3D 27 * 8; >> @@ -1323,6 +1321,8 @@ amd64_linux_init_abi (struct gdbarch_inf >> =A0 if (!valid_p) >> =A0 =A0 return; >> >> + =A0linux_init_abi (info, gdbarch); >> + >> =A0 tdep->sigtramp_p =3D amd64_linux_sigtramp_p; >> =A0 tdep->sigcontext_addr =3D amd64_linux_sigcontext_addr; >> =A0 tdep->sc_reg_offset =3D amd64_linux_sc_reg_offset; >> @@ -1543,6 +1543,44 @@ amd64_linux_init_abi (struct gdbarch_inf >> >> =A0 tdep->i386_syscall_record =3D amd64_linux_syscall_record; >> =A0} >> + >> +static void >> +amd64_x32_linux_init_abi(struct gdbarch_info info, struct gdbarch *gdba= rch) >> +{ >> + =A0struct gdbarch_tdep *tdep =3D gdbarch_tdep (gdbarch); >> + =A0const struct target_desc *tdesc =3D info.target_desc; >> + >> + =A0gdb_assert (tdesc_data); >> + >> + =A0tdep->gregset_reg_offset =3D amd64_linux_gregset_reg_offset; >> + =A0tdep->gregset_num_regs =3D ARRAY_SIZE (amd64_linux_gregset_reg_offs= et); >> + =A0tdep->sizeof_gregset =3D 27 * 8; >> + >> + =A0amd64_x32_init_abi (info, gdbarch); >> + >> + =A0/* Reserve a number for orig_rax. =A0*/ >> + =A0set_gdbarch_num_regs (gdbarch, AMD64_LINUX_NUM_REGS); >> + >> + =A0if (! tdesc_has_registers (tdesc)) >> + =A0 =A0tdesc =3D tdesc_x32_linux; >> + =A0tdep->tdesc =3D tdesc; >> + >> + =A0feature =3D tdesc_find_feature (tdesc, "org.gnu.gdb.i386.linux"); >> + =A0if (feature =3D=3D NULL) >> + =A0 =A0return; >> + >> + =A0valid_p =3D tdesc_numbered_register (feature, tdesc_data, >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0AMD64_LINUX_ORIG_RAX_REGNUM, >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0"orig_rax"); >> + =A0if (!valid_p) >> + =A0 =A0return; >> + >> + =A0linux_init_abi (info, gdbarch); >> + >> + =A0/* GNU/Linux uses SVR4-style shared libraries. =A0*/ >> + =A0set_solib_svr4_fetch_link_map_offsets >> + =A0 =A0(gdbarch, svr4_ilp32_fetch_link_map_offsets); >> +} > > These won't work for x32. =A0We have to copy almost everything in > amd64_linux_init_abi. > >> +void >> +amd64_x32_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) >> +{ >> + =A0struct gdbarch_tdep *tdep =3D gdbarch_tdep (gdbarch); >> + =A0const struct target_desc *tdesc =3D info.target_desc; >> + >> + =A0amd64_init_abi (info, gdbarch); >> + >> + =A0if (! tdesc_has_registers (tdesc)) >> + =A0 =A0tdesc =3D tdesc_x32; >> + =A0tdep->tdesc =3D tdesc; >> + >> + =A0tdep->num_dword_regs =3D 17; >> + =A0set_tdesc_pseudo_register_type (gdbarch, amd64_x32_pseudo_register_= type); >> + >> + =A0set_gdbarch_long_bit (gdbarch, 32); >> + =A0set_gdbarch_ptr_bit (gdbarch, 32); >> +} >> > > I think this is the wrong approach for x32 support. We should > break amd64_x32_init_abi into 2 parts: > > 1. OS specific part. =A0It should be private to amd64-tdep.c. > 2. Generic part. =A0It should be exported from amd64-tdep.c and can > be used by all x32 OSes. > > Thanks. > > Here is the updated patch. I added amd64_x32_init for generic x32 setting. It can be used by all x32 init_abi functions. Since tdep->tdesc can't be changed after being used, I renamed amd64_init_abi/amd64_init_abi to amd64_init/amd64_linux_init to take an argument to set tdep->tdesc properly. OK for trunk? Thanks. --=20 H.J. --- 2012-05-31 Mark Kettenis H.J. Lu * amd64-linux-tdep.c (amd64_linux_init_abi): Renamed to ... (amd64_linux_init): This. Add an argument, amd64_linux_tdesc. (amd64_linux_init_abi): Call amd64_linux_init. (amd64_x32_linux_init_abi): New function. (_initialize_amd64_linux_tdep): Register bfd_mach_x64_32 with amd64_x32_linux_init_abi. * amd64-tdep.c (amd64_dword_names): Add "eip". (amd64_x32_pseudo_register_type): New function. (amd64_x32_init): Likewise. (amd64_x32_init_abi): Likewise. (amd64_init_abi): Renamed to ... (amd64_init): This. Add an argument, amd64_tdesc. (amd64_init_abi): Call amd64_init. * amd64-tdep.h (amd64_x32_init_abi): New prototype. (amd64_x32_init): Likewise. * i386-tdep.c (i386_pseudo_register_type): Make it global. * i386-tdep.h (i386_pseudo_register_type): New prototype. diff --git a/gdb/amd64-linux-tdep.c b/gdb/amd64-linux-tdep.c index 42dc89a..23bf318 100644 --- a/gdb/amd64-linux-tdep.c +++ b/gdb/amd64-linux-tdep.c @@ -1288,7 +1288,8 @@ amd64_linux_core_read_description (struct gdbarch *gdbarch, } static void -amd64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +amd64_linux_init (struct gdbarch_info info, struct gdbarch *gdbarch, + const struct target_desc *amd64_linux_tdesc) { struct gdbarch_tdep *tdep =3D gdbarch_tdep (gdbarch); const struct target_desc *tdesc =3D info.target_desc; @@ -1310,9 +1311,10 @@ amd64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) set_gdbarch_num_regs (gdbarch, AMD64_LINUX_NUM_REGS); if (! tdesc_has_registers (tdesc)) - tdesc =3D tdesc_amd64_linux; + tdesc =3D amd64_linux_tdesc; tdep->tdesc =3D tdesc; + /* tdep->tdesc can't be changed after being used here. */ feature =3D tdesc_find_feature (tdesc, "org.gnu.gdb.i386.linux"); if (feature =3D=3D NULL) return; @@ -1543,6 +1545,24 @@ amd64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) tdep->i386_syscall_record =3D amd64_linux_syscall_record; } + +static void +amd64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +{ + amd64_linux_init (info, gdbarch, tdesc_amd64_linux); +} + +static void +amd64_x32_linux_init_abi (struct gdbarch_info info, + struct gdbarch *gdbarch) +{ + amd64_linux_init (info, gdbarch, tdesc_x32_linux); + amd64_x32_init (gdbarch); + + /* GNU/Linux uses SVR4-style shared libraries. */ + set_solib_svr4_fetch_link_map_offsets + (gdbarch, svr4_ilp32_fetch_link_map_offsets); +} /* Provide a prototype to silence -Wmissing-prototypes. */ @@ -1553,6 +1573,8 @@ _initialize_amd64_linux_tdep (void) { gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64, GDB_OSABI_LINUX, amd64_linux_init_abi); + gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x64_32, + GDB_OSABI_LINUX, amd64_x32_linux_init_abi); /* Initialize the Linux target description. */ initialize_tdesc_amd64_linux (); diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c index df91a51..47f8019 100644 --- a/gdb/amd64-tdep.c +++ b/gdb/amd64-tdep.c @@ -258,9 +258,32 @@ static const char *amd64_word_names[] =3D static const char *amd64_dword_names[] =3D { "eax", "ebx", "ecx", "edx", "esi", "edi", "ebp", "esp", - "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d" + "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d", + "eip" }; +/* Return the GDB type object for the "standard" data type of data in + register REGNUM. Only used for x32. */ + +static struct type * +amd64_x32_pseudo_register_type (struct gdbarch *gdbarch, int regnum) +{ + /* Use pointer types for ebp, esp and eip registers in x32. */ + struct gdbarch_tdep *tdep =3D gdbarch_tdep (gdbarch); + switch (regnum - tdep->eax_regnum) + { + default: + break; + case AMD64_RBP_REGNUM: /* ebp */ + case AMD64_RSP_REGNUM: /* esp */ + return builtin_type (gdbarch)->builtin_data_ptr; + case AMD64_RIP_REGNUM: /* eip */ + return builtin_type (gdbarch)->builtin_func_ptr; + } + + return i386_pseudo_register_type (gdbarch, regnum); +} + /* Return the name of register REGNUM. */ static const char * @@ -2606,8 +2629,9 @@ static const int amd64_record_regmap[] =3D AMD64_DS_REGNUM, AMD64_ES_REGNUM, AMD64_FS_REGNUM, AMD64_GS_REGNUM }; -void -amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +static void +amd64_init (struct gdbarch_info info, struct gdbarch *gdbarch, + const struct target_desc *amd64_tdesc) { struct gdbarch_tdep *tdep =3D gdbarch_tdep (gdbarch); const struct target_desc *tdesc =3D info.target_desc; @@ -2617,12 +2641,13 @@ amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) tdep->sizeof_fpregset =3D I387_SIZEOF_FXSAVE; if (! tdesc_has_registers (tdesc)) - tdesc =3D tdesc_amd64; + tdesc =3D amd64_tdesc; tdep->tdesc =3D tdesc; tdep->num_core_regs =3D AMD64_NUM_GREGS + I387_NUM_REGS; tdep->register_names =3D amd64_register_names; + /* tdep->tdesc can't be changed after being used here. */ if (tdesc_find_feature (tdesc, "org.gnu.gdb.i386.avx") !=3D NULL) { tdep->ymmh_register_names =3D amd64_ymmh_names; @@ -2730,6 +2755,32 @@ amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) i386_stap_parse_special_token); } +void +amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +{ + amd64_init (info, gdbarch, tdesc_amd64); +} + +void +amd64_x32_init (struct gdbarch *gdbarch) +{ + struct gdbarch_tdep *tdep =3D gdbarch_tdep (gdbarch); + + tdep->num_dword_regs =3D 17; + + set_tdesc_pseudo_register_type (gdbarch, amd64_x32_pseudo_register_type); + + set_gdbarch_long_bit (gdbarch, 32); + set_gdbarch_ptr_bit (gdbarch, 32); +} + +void +amd64_x32_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +{ + amd64_init (info, gdbarch, tdesc_x32); + amd64_x32_init (gdbarch); +} + /* Provide a prototype to silence -Wmissing-prototypes. */ void _initialize_amd64_tdep (void); diff --git a/gdb/amd64-tdep.h b/gdb/amd64-tdep.h index 1ed109c..ce47ae7 100644 --- a/gdb/amd64-tdep.h +++ b/gdb/amd64-tdep.h @@ -80,6 +80,9 @@ extern void amd64_displaced_step_fixup (struct gdbarch *gdbarch, struct regcache *regs); extern void amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdba= rch); +extern void amd64_x32_init_abi (struct gdbarch_info info, + struct gdbarch *gdbarch); +extern void amd64_x32_init (struct gdbarch *gdbarch); /* Fill register REGNUM in REGCACHE with the appropriate floating-point or SSE register value from *FXSAVE. If REGNUM is diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c index 5b04505..6333556 100644 --- a/gdb/i386-tdep.c +++ b/gdb/i386-tdep.c @@ -2780,7 +2780,7 @@ i386_mmx_type (struct gdbarch *gdbarch) /* Return the GDB type object for the "standard" data type of data in register REGNUM. */ -static struct type * +struct type * i386_pseudo_register_type (struct gdbarch *gdbarch, int regnum) { if (i386_mmx_regnum_p (gdbarch, regnum)) diff --git a/gdb/i386-tdep.h b/gdb/i386-tdep.h index f297ae7..a12b1f5 100644 --- a/gdb/i386-tdep.h +++ b/gdb/i386-tdep.h @@ -307,6 +307,7 @@ extern int i386_dword_regnum_p (struct gdbarch *gdbarch, int regnum); extern int i386_xmm_regnum_p (struct gdbarch *gdbarch, int regnum); extern int i386_ymm_regnum_p (struct gdbarch *gdbarch, int regnum); +extern struct type *i386_pseudo_register_type (struct gdbarch *, int); extern const char *i386_pseudo_register_name (struct gdbarch *gdbarch, int regnum);