Re: [PATCH 1/9] Support the fs_base and gs_base registers on i386.

Simon Marchi
2019-02-02T15:11:45Z

On 2019-01-28 12:54, John Baldwin wrote:
> On 1/26/19 7:47 PM, Simon Marchi wrote:
>> On 2019-01-22 1:42 p.m., John Baldwin wrote:
>>> As on amd64, these registers hold the base address of the fs and gs
>>> segments, respectively. For i386 these two registers are 32 bits.
>>
>> I just started to look at this, still trying to get my head around it
>> and
>> connect all the dots. Just a silly question for now:
>>
>>> diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c
>>> index d4143ae155..1eb0bcdf17 100644
>>> --- a/gdb/amd64-tdep.c
>>> +++ b/gdb/amd64-tdep.c
>>> @@ -3107,15 +3107,7 @@ amd64_init_abi (struct gdbarch_info info,
>>> struct gdbarch *gdbarch,
>>>
>>> if (tdesc_find_feature (tdesc, "org.gnu.gdb.i386.segments") !=
>>> NULL)
>>> {
>>> - const struct tdesc_feature *feature =
>>> - tdesc_find_feature (tdesc, "org.gnu.gdb.i386.segments");
>>> - struct tdesc_arch_data *tdesc_data_segments =
>>> - (struct tdesc_arch_data *) info.tdep_info;
>>> -
>>> - tdesc_numbered_register (feature, tdesc_data_segments,
>>> - AMD64_FSBASE_REGNUM, "fs_base");
>>> - tdesc_numbered_register (feature, tdesc_data_segments,
>>> - AMD64_GSBASE_REGNUM, "gs_base");
>>> + tdep->fsbase_regnum = AMD64_FSBASE_REGNUM;
>>> }
>>
>> Can you explain what this change does and why it is needed? I am a
>> bit lost.
>>
>> I see you add something equivalent in i386-tdep.c, but as far as I
>> know, they are completely
>> separate.
>
> It took a while for me to understand this as well. :-/
>
> The 64-bit (amd64) and 32-bit (i386) gdbarch's share a fair bit of
> code.
> In particular, the 64-bit gdbarch is "inherited" from the 32-bit one,
> but
> overrides various behaviors. Specifically, see the comment above
> i386_gdbarch_init. amd64_init_abi is called from OSABI specific
> handlers
> part way through i386_gdbarch_init from gdbarch_init_osabi() to apply
> 64-bit overrides.
>
> One of the things that gets overridden is that 32-bit and 64-bit
> gdbarch's
> use different register numbers. This is because 64-bit x86 has r8-15.
> The first 8 registers are the same, but the remaining registers for
> FPU,
> SSE, etc. are all shifted by 8 for amd64. There's a comment that hints
> at
> this in i386-tdep.h:
>
> /* GDB's i386 target supports both the 32-bit Intel Architecture
> (IA-32) and the 64-bit AMD x86-64 architecture. Internally it uses
> a similar register layout for both.
>
> - General purpose registers
> - FPU data registers
> - FPU control registers
> - SSE data registers
> - SSE control register
>
> The general purpose registers for the x86-64 architecture are quite
> different from IA-32. Therefore, gdbarch_fp0_regnum
> determines the register number at which the FPU data registers
> start. The number of FPU data and control registers is the same
> for both architectures. The number of SSE registers however,
> differs and is determined by the num_xmm_regs member of `struct
> gdbarch_tdep'. */
>
> As the comment notes, the way this is handled for the FPU registers is
> that
> tdep->fp0_regnum holds the value of the first FPU register
> (AMD64_ST0_REGNUM
> vs I386_ST0_REGNUM). This same approach is then used for all the other
> shared register banks (tdep->mm0_regnum, ymm0_regnum, zmm0_regnum,
> etc.).
> Helper variables are also used to handle the different numbers of
> SSE/AVX
> registers on 32-bit vs 64-bit.
>
> i386_validate_tdesc_p() is called after gdbarch_init_osabi() to add the
> shared register sets. It checks for each feature being present. If it
> is,
> it first checks to see if the corresponding tdep fields (e.g.
> ymm0_regnum)
> have been set. If they aren't, it sets them to the I386 values. Then
> it
> adds the appropriate registers for each feature. In the case of a
> 64-bit
> architecture, amd64_init_abi() is called from gdbarch_init_osabi()
> before
> i386_validate_tdesc_p() is called. amd64_init_abi() sets the various
> tdep
> variables for any features that are present to the AMD64 values. Then
> when
> i386_validate_tdesc_p() runs, it still adds the registers, but it does
> so
> using the 64-bit register numbers instead of 32-bit register numbers.
>
> When fs_base and gs_base were first added, they were only added on
> amd64,
> so they were not treated as a shared register set. Instead, they were
> just added directly in amd64_init_abi() using the AMD64 register
> numbers.
> This particular part of the patch (along with the change to
> i386_validate_tdesc_p in i386-tdep.c) is changing the fs_base/gs_base
> register set to be a shared register set like FPU, AVX/SSE, etc. It
> does
> this by adding a new tdep->fsbase_regnum to hold the base number of the
> two registers. It then changes amd64_init_abi() to just set the tdep
> field as it does for other register sets and changes
> i386_validate_tdesc_p
> to add the registers at the appropriate register number, defaulting to
> the
> I386 values if the tdep field wasn't set.
>
> Hopefully that isn't too confusing. It took me a while to figure it
> out
> myself.

Thanks for the explanation, it does clear it up.

There was nothing else in this patch that stood out to me.

Simon