Re: [RFA] i386 segment base support

Hui Zhu
2010-05-21T03:01:58Z

On Thu, May 20, 2010 at 22:39, Mark Kettenis <mark.kettenis@xs4all.nl> wrote:
>> Date: Thu, 20 May 2010 08:54:37 -0400
>> From: Daniel Jacobowitz <dan@codesourcery.com>
>>
>> On Thu, May 20, 2010 at 10:19:54AM +0200, Mark Kettenis wrote:
>> > Sorry, but we still need to discuss what programming model you intend
>> > to support before I will consider looking at diffs.
>> >
>> > Currently, on i386, GDB supports a fully flat 32-bit model, with one
>> > small exception on platforms that support thread-local-storage.  In
>> > that model you can assume that all the segment bases are 0 except for
>> > %gs.  If that's all that people are interested in, I don't think we
>> > should bother with segment bases for %cs, %ds, %es, %fs and %ss.
>> >
>> > If people want to support fully segmented memory in GDB, then what you
>> > propose is probably not enough, at least not for 32-bit mode.
>>
>> This position confuses me.  Isn't "very limited support for segmented
>> memory" better than "no support for segmented memory"?
>
> I'm not taking a position here.  I'm trying to figure out what people
> want out of this.  If it is only about supporting TLS for Linux
> userland binaries we can have a radically simpler solution than when
> people want full fledged kernel-style segment register manipulating
> code to work as well.
>

My trouble is:
Prec is in the arch part, it cannot call target function directly. It
need interface.

I just know 2 ways to handle it:
1. add interface to target.
2. add support to gdbarch.

I am very happy that you said have a simpler way to handle it? Could
you tell me what or where is the simpler way?

Thanks,
Hui

This is what I send before:
http://sourceware.org/ml/gdb-patches/2010-03/msg00839.html
Prec just need the base to get the insn memory operate address. Do
you think we need other message of segment?

If need, do we need divide all message like eflags?

Thanks,
Hui

http://sourceware.org/ml/gdb-patches/2010-04/msg00983.html
Prec must know the each base of segment register.

If you don't like it. What about the old way that I use? It doesn't
add anything to reg list.
But for the each way, we need add interface to the target part that
prec can get the value.

Thanks,
Hui

Follow is why I need it:
Hi,

In before, the prec cannot support the x86 segment register. Because
GDB just have the interface to get the index the segment reg point to,
but cannot get the base in the segment.
Just the OS can get this value.

After I read some code of Linux kernel, I found that some code about
this issue in file common.c and segment.h, the x86-32 struct about it
is:
DEFINE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page) = { .gdt = {
#ifdef CONFIG_X86_64
/*
* We need valid kernel segments for data and code in long mode too
* IRET will check the segment types kkeil 2000/10/28
* Also sysret mandates a special GDT layout
*
* TLS descriptors are currently at a different place compared to i386.
* Hopefully nobody expects them at a fixed place (Wine?)
*/
[GDT_ENTRY_KERNEL32_CS] = GDT_ENTRY_INIT(0xc09b, 0, 0xfffff),
[GDT_ENTRY_KERNEL_CS] = GDT_ENTRY_INIT(0xa09b, 0, 0xfffff),
[GDT_ENTRY_KERNEL_DS] = GDT_ENTRY_INIT(0xc093, 0, 0xfffff),
[GDT_ENTRY_DEFAULT_USER32_CS] = GDT_ENTRY_INIT(0xc0fb, 0, 0xfffff),
[GDT_ENTRY_DEFAULT_USER_DS] = GDT_ENTRY_INIT(0xc0f3, 0, 0xfffff),
[GDT_ENTRY_DEFAULT_USER_CS] = GDT_ENTRY_INIT(0xa0fb, 0, 0xfffff),
#else
[GDT_ENTRY_KERNEL_CS] = GDT_ENTRY_INIT(0xc09a, 0, 0xfffff),
[GDT_ENTRY_KERNEL_DS] = GDT_ENTRY_INIT(0xc092, 0, 0xfffff),
[GDT_ENTRY_DEFAULT_USER_CS] = GDT_ENTRY_INIT(0xc0fa, 0, 0xfffff),
[GDT_ENTRY_DEFAULT_USER_DS] = GDT_ENTRY_INIT(0xc0f2, 0, 0xfffff),
/*
* Segments used for calling PnP BIOS have byte granularity.
* They code segments and data segments have fixed 64k limits,
* the transfer segment sizes are set at run time.
*/
/* 32-bit code */
[GDT_ENTRY_PNPBIOS_CS32 18] = GDT_ENTRY_INIT(0x409a, 0, 0xffff),
/* 16-bit code */
[GDT_ENTRY_PNPBIOS_CS16 19] = GDT_ENTRY_INIT(0x009a, 0, 0xffff),
/* 16-bit data */
[GDT_ENTRY_PNPBIOS_DS] = GDT_ENTRY_INIT(0x0092, 0, 0xffff),
/* 16-bit data */
[GDT_ENTRY_PNPBIOS_TS1] = GDT_ENTRY_INIT(0x0092, 0, 0),
/* 16-bit data */
[GDT_ENTRY_PNPBIOS_TS2] = GDT_ENTRY_INIT(0x0092, 0, 0),
/*
* The APM segments have byte granularity and their bases
* are set at run time. All have 64k limits.
*/
/* 32-bit code */
[GDT_ENTRY_APMBIOS_BASE] = GDT_ENTRY_INIT(0x409a, 0, 0xffff),
/* 16-bit code */
[GDT_ENTRY_APMBIOS_BASE+1] = GDT_ENTRY_INIT(0x009a, 0, 0xffff),
/* data */
[GDT_ENTRY_APMBIOS_BASE+2] = GDT_ENTRY_INIT(0x4092, 0, 0xffff),

[GDT_ENTRY_ESPFIX_SS] = GDT_ENTRY_INIT(0xc092, 0, 0xfffff),
[GDT_ENTRY_PERCPU] = GDT_ENTRY_INIT(0xc092, 0, 0xfffff),
GDT_STACK_CANARY_INIT
#endif
} };

/*
* The layout of the per-CPU GDT under Linux:
*
* 0 - null
* 1 - reserved
* 2 - reserved
* 3 - reserved
*
* 4 - unused <==== new cacheline
* 5 - unused
*
* ------- start of TLS (Thread-Local Storage) segments:
*
* 6 - TLS segment #1 [ glibc's TLS segment ]
* 7 - TLS segment #2 [ Wine's %fs Win32 segment ]
* 8 - TLS segment #3
* 9 - reserved
* 10 - reserved
* 11 - reserved
*
* ------- start of kernel segments:
*
* 12 - kernel code segment <==== new cacheline
* 13 - kernel data segment
* 14 - default user CS
* 15 - default user DS
* 16 - TSS
* 17 - LDT
* 18 - PNPBIOS support (16->32 gate)
* 19 - PNPBIOS support
* 20 - PNPBIOS support
* 21 - PNPBIOS support
* 22 - PNPBIOS support
* 23 - APM BIOS support
* 24 - APM BIOS support
* 25 - APM BIOS support
*
* 26 - ESPFIX small SS
* 27 - per-cpu [ offset to per-cpu data area ]
* 28 - stack_canary-20 [ for stack protector ]
* 29 - unused
* 30 - unused
* 31 - TSS for double fault handler
*/

So, most of base is 0. Just 6 7 8 can be change.

And I found linux kernel x86-32 have system calls set_thread_area and
get_thread_area to set them's value.
I think let inferior call "get_thread_area" is support each target is
more better. But I found ptrace have a interface
PTRACE_GET_THREAD_AREA to get the message of thread_area message and
ps_get_thread_area function of GDB use it.
So I choice call ps_get_thread_area to get the segment base.

For the amd64 linux, I did some small check about it, it didn't affect
by segment register issue most of time. And it have PTRACE_ARCH_PRCTL
to support get base message. When SSE patch is OK. I will add patch
for them.

Thanks,
Hui