This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: x32 ABI Support (was Re: Three weeks to branching (gdb 7.5 release))


On Thu, May 31, 2012 at 11:18 AM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Mon, May 28, 2012 at 2:18 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
>> On Mon, May 28, 2012 at 1:26 PM, Mark Kettenis <mark.kettenis@xs4all.nl> wrote:
>>>> Date: Sun, 20 May 2012 15:48:54 -0700
>>>> From: "H.J. Lu" <hjl.tools@gmail.com>
>>>>
>>>> Does this one look OK. ?I 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(). ?That way it is immediately obvious that the OS-specific ABI inherits everything from the generic ABI.
>>
>> X32 kernel interface are highly OS specific. ?Different OSes can implement
>> very different kernel interfaces. ?The only generic x32 bits are
>>
>> ?struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
>>
>> ?tdep->num_dword_regs = 17;
>>
>> ?set_tdesc_pseudo_register_type (gdbarch, amd64_x32_pseudo_register_type);
>>
>> ?set_gdbarch_long_bit (gdbarch, 32);
>> ?set_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(). ?As I wrote earlier, it isn't entirely
>>> obvious that everything in amd64_linix_init_abi() applies to the x32
>>> ABI. ?So we should be conservative in moving stuff into the common
>>> function. ?In 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). ?See
>> 64-bit system call table in Linux kernel 3.4:
>>
>> http://git.kernel.org/?p=linux/kernel/git/stable/linux-stable.git;a=blob;f=arch/x86/syscalls/syscall_64.tbl;h=dd29a9ea27c560a9d2fcb6e1c2983f8b8e9be407;hb=HEAD
>>
>> I believe we should start with sharing everything between Linux/x32
>> and Linux/amd64. ?We can update x32 part as we go.
>>
>
>
> 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.
>

Hi Mark,

Do you have a chance to take a look at this?

Thanks.


H.J.
> --
> H.J.
> ---
> 2012-05-31 ?Mark Kettenis ?<kettenis@gnu.org>
> ? ? ? ? ? ?H.J. Lu ?<hongjiu.lu@intel.com>
>
> ? ? ? ?* 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 = gdbarch_tdep (gdbarch);
> ? const struct target_desc *tdesc = 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 = tdesc_amd64_linux;
> + ? ?tdesc = amd64_linux_tdesc;
> ? tdep->tdesc = tdesc;
>
> + ?/* tdep->tdesc can't be changed after being used here. ?*/
> ? feature = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.linux");
> ? if (feature == NULL)
> ? ? return;
> @@ -1543,6 +1545,24 @@ amd64_linux_init_abi (struct gdbarch_info info,
> struct gdbarch *gdbarch)
>
> ? tdep->i386_syscall_record = 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[] =
> ?static const char *amd64_dword_names[] =
> ?{
> ? "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 = 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[] =
> ? 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 = gdbarch_tdep (gdbarch);
> ? const struct target_desc *tdesc = info.target_desc;
> @@ -2617,12 +2641,13 @@ amd64_init_abi (struct gdbarch_info info,
> struct gdbarch *gdbarch)
> ? tdep->sizeof_fpregset = I387_SIZEOF_FXSAVE;
>
> ? if (! tdesc_has_registers (tdesc))
> - ? ?tdesc = tdesc_amd64;
> + ? ?tdesc = amd64_tdesc;
> ? tdep->tdesc = tdesc;
>
> ? tdep->num_core_regs = AMD64_NUM_GREGS + I387_NUM_REGS;
> ? tdep->register_names = amd64_register_names;
>
> + ?/* tdep->tdesc can't be changed after being used here. ?*/
> ? if (tdesc_find_feature (tdesc, "org.gnu.gdb.i386.avx") != NULL)
> ? ? {
> ? ? ? tdep->ymmh_register_names = 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 = gdbarch_tdep (gdbarch);
> +
> + ?tdep->num_dword_regs = 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 *gdbarch);
> +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);


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]