|
From: <sv...@va...> - 2005-05-15 20:52:11
|
Author: njn
Date: 2005-05-15 21:52:04 +0100 (Sun, 15 May 2005)
New Revision: 3726
Removed:
trunk/coregrind/amd64-linux/ldt.c
trunk/coregrind/amd64/amd64_private.h
trunk/coregrind/x86-linux/ldt.c
trunk/coregrind/x86/x86_private.h
Modified:
trunk/coregrind/amd64-linux/Makefile.am
trunk/coregrind/amd64-linux/core_platform.h
trunk/coregrind/amd64/Makefile.am
trunk/coregrind/amd64/state.c
trunk/coregrind/core.h
trunk/coregrind/m_syscalls/syscalls-amd64-linux.c
trunk/coregrind/m_syscalls/syscalls-x86-linux.c
trunk/coregrind/pub_core_syscalls.h
trunk/coregrind/vg_scheduler.c
trunk/coregrind/vg_signals.c
trunk/coregrind/x86-linux/Makefile.am
trunk/coregrind/x86-linux/core_platform.h
trunk/coregrind/x86/Makefile.am
trunk/coregrind/x86/state.c
Log:
Improved structure of LDT-related code:
- one declarations from core.h removed, one moved to within m_syscalls.
- all the x86 LDT stuff made local to m_syscalls. x86-linux/ldt.c remove=
d
as a result. x86/state.c slimmed down, too. x86/x86_private.h removed
too.
- all the AMD64 LDT stuff was deleted, since it was all commented out. I=
t
can be added back in later in the appropriate places if necessary.
Thus amd64-linux/ldt.c and amd64/amd64_private.h were removed.
- other minor naming changes
I hope I didn't break AMD64 compilation.
Modified: trunk/coregrind/amd64/Makefile.am
=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
--- trunk/coregrind/amd64/Makefile.am 2005-05-15 18:51:47 UTC (rev 3725)
+++ trunk/coregrind/amd64/Makefile.am 2005-05-15 20:52:04 UTC (rev 3726)
@@ -5,8 +5,7 @@
=20
noinst_HEADERS =3D \
core_arch.h \
- core_arch_asm.h \
- amd64_private.h
+ core_arch_asm.h
=20
noinst_LIBRARIES =3D libarch.a
=20
Deleted: trunk/coregrind/amd64/amd64_private.h
=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
--- trunk/coregrind/amd64/amd64_private.h 2005-05-15 18:51:47 UTC (rev 37=
25)
+++ trunk/coregrind/amd64/amd64_private.h 2005-05-15 20:52:04 UTC (rev 37=
26)
@@ -1,46 +0,0 @@
-
-/*--------------------------------------------------------------------*/
-/*--- Private arch-specific header. amd64/amd64_private.h ---*/
-/*--------------------------------------------------------------------*/
-
-/*
- This file is part of Valgrind, a dynamic binary instrumentation
- framework.
-
- Copyright (C) 2000-2005 Nicholas Nethercote
- nj...@va...
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307, USA.
-
- The GNU General Public License is contained in the file COPYING.
-*/
-
-#ifndef __AMD64_PRIVATE_H
-#define __AMD64_PRIVATE_H
-
-#include "core_arch_asm.h" // arch-specific asm stuff
-#include "tool_arch.h" // arch-specific tool stuff
-
-/* ---------------------------------------------------------------------
- Exports of state.c that are not core-visible
- ------------------------------------------------------------------ */
-
-
-#endif // __AMD64_PRIVATE_H
-
-/*--------------------------------------------------------------------*/
-/*--- end ---*/
-/*--------------------------------------------------------------------*/
Modified: trunk/coregrind/amd64/state.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
--- trunk/coregrind/amd64/state.c 2005-05-15 18:51:47 UTC (rev 3725)
+++ trunk/coregrind/amd64/state.c 2005-05-15 20:52:04 UTC (rev 3726)
@@ -30,7 +30,6 @@
=20
#include "core.h"
#include "pub_core_tooliface.h"
-#include "amd64_private.h"
#include <sys/ptrace.h>
=20
#include "libvex_guest_amd64.h"
@@ -87,36 +86,6 @@
/*--- Thread stuff ---*/
/*------------------------------------------------------------*/
=20
-void VGA_(cleanup_thread) ( ThreadArchState *arch )
-{ =20
- /* TODO: deallocate the thread's LDT / GDT ? */
-} =20
-
-
-void VGA_(setup_child) ( /*OUT*/ ThreadArchState *child,=20
- /*IN*/ ThreadArchState *parent )
-{ =20
- /* We inherit our parent's guest state. */
- child->vex =3D parent->vex;
- child->vex_shadow =3D parent->vex_shadow;
-#if 0
- /* TODO: inherit the thread's LDT / GDT ? */
- /* We inherit our parent's LDT. */
- if (parent->vex.guest_LDT =3D=3D (HWord)NULL) {
- /* We hope this is the common case. */
- child->vex.guest_LDT =3D (HWord)NULL;
- } else {
- /* No luck .. we have to take a copy of the parent's. */
- child->vex.guest_LDT =3D (HWord)VG_(alloc_zeroed_x86_LDT)();
- copy_LDT_from_to( (VexGuestX86SegDescr*)parent->vex.guest_LDT,=20
- (VexGuestX86SegDescr*)child->vex.guest_LDT );
- }
-
- /* We need an empty GDT. */
- child->vex.guest_GDT =3D (HWord)NULL;
-#endif
-} =20
-
void VGA_(mark_from_registers)(ThreadId tid, void (*marker)(Addr))
{
ThreadState *tst =3D VG_(get_ThreadState)(tid);
Modified: trunk/coregrind/amd64-linux/Makefile.am
=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
--- trunk/coregrind/amd64-linux/Makefile.am 2005-05-15 18:51:47 UTC (rev =
3725)
+++ trunk/coregrind/amd64-linux/Makefile.am 2005-05-15 20:52:04 UTC (rev =
3726)
@@ -11,8 +11,7 @@
=20
=20
libplatform_a_SOURCES =3D \
- core_platform.c \
- ldt.c
+ core_platform.c
=20
if USE_PIE
libplatform_a_CFLAGS =3D $(AM_CFLAGS) -fpie
Modified: trunk/coregrind/amd64-linux/core_platform.h
=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
--- trunk/coregrind/amd64-linux/core_platform.h 2005-05-15 18:51:47 UTC (=
rev 3725)
+++ trunk/coregrind/amd64-linux/core_platform.h 2005-05-15 20:52:04 UTC (=
rev 3726)
@@ -36,29 +36,6 @@
//#include "platform_arch.h" // platform-specific tool stuff
=20
/* ---------------------------------------------------------------------
- Exports of vg_ldt.c
- ------------------------------------------------------------------ */
-
-// XXX: eventually all these should be x86-private, and not visible to t=
he
-// core (except maybe do_useseg()?)
-
-#if 0
-/* Simulate the modify_ldt syscall. */
-extern Int VG_(sys_modify_ldt) ( ThreadId tid,
- Int func, void* ptr, UInt bytecount );
-
-/* Simulate the {get,set}_thread_area syscalls. */
-extern Int VG_(sys_set_thread_area) ( ThreadId tid,
- vki_modify_ldt_t* info );
-extern Int VG_(sys_get_thread_area) ( ThreadId tid,
- vki_modify_ldt_t* info );
-
-/* Called from generated code. Given a segment selector and a virtual
- address, return a linear address, and do limit checks too. */
-extern Addr VG_(do_useseg) ( UInt seg_selector, Addr virtual_addr );
-#endif
-
-/* ---------------------------------------------------------------------
ucontext stuff
------------------------------------------------------------------ */
=20
Deleted: trunk/coregrind/amd64-linux/ldt.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
--- trunk/coregrind/amd64-linux/ldt.c 2005-05-15 18:51:47 UTC (rev 3725)
+++ trunk/coregrind/amd64-linux/ldt.c 2005-05-15 20:52:04 UTC (rev 3726)
@@ -1,495 +0,0 @@
-
-/*--------------------------------------------------------------------*/
-/*--- Simulation of Local Descriptor Tables amd64-linux/ldt.c ---*/
-/*--------------------------------------------------------------------*/
-
-/*
- This file is part of Valgrind, a dynamic binary instrumentation
- framework.
-
- Copyright (C) 2000-2005 Julian Seward=20
- js...@ac...
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307, USA.
-
- The GNU General Public License is contained in the file COPYING.
-*/
-
-// XXX: this is copied straight from the x86 code... perhaps they should=
be
-// shared. (Are AMD64 LDTs the same as x86 LDTs? Don't know. --njn)
-
-/* Details of the LDT simulation
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- =20
- When a program runs natively, the linux kernel allows each *thread*
- in it to have its own LDT. Almost all programs never do this --
- it's wildly unportable, after all -- and so the kernel never
- allocates the structure, which is just as well as an LDT occupies
- 64k of memory (8192 entries of size 8 bytes).
-
- A thread may choose to modify its LDT entries, by doing the
- __NR_modify_ldt syscall. In such a situation the kernel will then
- allocate an LDT structure for it. Each LDT entry is basically a
- (base, limit) pair. A virtual address in a specific segment is
- translated to a linear address by adding the segment's base value.
- In addition, the virtual address must not exceed the limit value.
-
- To use an LDT entry, a thread loads one of the segment registers
- (%cs, %ss, %ds, %es, %fs, %gs) with the index of the LDT entry (0
- .. 8191) it wants to use. In fact, the required value is (index <<
- 3) + 7, but that's not important right now. Any normal instruction
- which includes an addressing mode can then be made relative to that
- LDT entry by prefixing the insn with a so-called segment-override
- prefix, a byte which indicates which of the 6 segment registers
- holds the LDT index.
-
- Now, a key constraint is that valgrind's address checks operate in
- terms of linear addresses. So we have to explicitly translate
- virtual addrs into linear addrs, and that means doing a complete
- LDT simulation.
-
- Calls to modify_ldt are intercepted. For each thread, we maintain
- an LDT (with the same normally-never-allocated optimisation that
- the kernel does). This is updated as expected via calls to
- modify_ldt.
-
- When a thread does an amode calculation involving a segment
- override prefix, the relevant LDT entry for the thread is
- consulted. It all works.
-
- There is a conceptual problem, which appears when switching back to
- native execution, either temporarily to pass syscalls to the
- kernel, or permanently, when debugging V. Problem at such points
- is that it's pretty pointless to copy the simulated machine's
- segment registers to the real machine, because we'd also need to
- copy the simulated LDT into the real one, and that's prohibitively
- expensive.
-
- Fortunately it looks like no syscalls rely on the segment regs or
- LDT being correct, so we can get away with it. Apart from that the
- simulation is pretty straightforward. All 6 segment registers are
- tracked, although only %ds, %es, %fs and %gs are allowed as
- prefixes. Perhaps it could be restricted even more than that -- I
- am not sure what is and isn't allowed in user-mode.
-*/
-
-#include "core.h"
-
-#if 0
-/* Maximum number of LDT entries supported (by the x86). */
-#define VG_M_LDT_ENTRIES 8192
-/* The size of each LDT entry =3D=3D sizeof(VgLdtEntry) */
-#define VG_LDT_ENTRY_SIZE 8
-
-/* Allocate and deallocate LDTs for threads. */
-
-/* Create an LDT. If the parent_ldt is NULL, zero out the
- new one. If non-NULL, copy the parent. */
-VgLdtEntry* VG_(allocate_LDT_for_thread) ( VgLdtEntry* parent_ldt )
-{
- UInt nbytes, i;
- VgLdtEntry* ldt;
-
- if (0)
- VG_(printf)("allocate_LDT_for_thread: parent =3D %p\n", parent_ldt=
);
- vg_assert(VG_LDT_ENTRY_SIZE =3D=3D sizeof(VgLdtEntry));
- nbytes =3D VG_M_LDT_ENTRIES * VG_LDT_ENTRY_SIZE;
-=20
- if (parent_ldt =3D=3D NULL) {
- /* Allocate a new zeroed-out one. */
- ldt =3D (VgLdtEntry*)VG_(arena_calloc)(VG_AR_CORE, nbytes, 1);
- } else {
- ldt =3D (VgLdtEntry*)VG_(arena_malloc)(VG_AR_CORE, nbytes);
- for (i =3D 0; i < VG_M_LDT_ENTRIES; i++)
- ldt[i] =3D parent_ldt[i];
- }
-
- return ldt;
-}
-
-/* Free an LDT created by the above function. */
-void VG_(deallocate_LDT_for_thread) ( VgLdtEntry* ldt )
-{
- if (0)
- VG_(printf)("deallocate_LDT_for_thread: ldt =3D %p\n", ldt );
- if (ldt !=3D NULL)
- VG_(arena_free)(VG_AR_CORE, ldt);
-}
-
-
-/* Clear a TLS array. */
-void VG_(clear_TLS_for_thread) ( VgLdtEntry* tls )
-{
- VgLdtEntry* tlsp;
-
- if (0)
- VG_(printf)("clear_TLS_for_thread\n" );
-
- for (tlsp =3D tls; tlsp < tls + VKI_GDT_ENTRY_TLS_ENTRIES; tlsp++) {
- tlsp->LdtEnt.Words.word1 =3D 0;
- tlsp->LdtEnt.Words.word2 =3D 0;
- }
-
- return;
-}
-
-
-/* Fish the base field out of an VgLdtEntry. This is the only part we
- are particularly interested in. */
-
-static=20
-void *wine_ldt_get_base( const VgLdtEntry *ent )
-{
- return (void *)(ent->LdtEnt.Bits.BaseLow |
- ((unsigned long)ent->LdtEnt.Bits.BaseMid) << 16 |
- ((unsigned long)ent->LdtEnt.Bits.BaseHi) << 24);
-}
-
-static=20
-unsigned int wine_ldt_get_limit( const VgLdtEntry *ent )
-{
- unsigned int limit =3D ent->LdtEnt.Bits.LimitLow=20
- | (ent->LdtEnt.Bits.LimitHi << 16);
- if (ent->LdtEnt.Bits.Granularity) limit =3D (limit << 12) | 0xfff;
- return limit;
-}
-
-
-#if 0
-/* Actually _DO_ the segment translation. This is the whole entire
- point of this accursed, overcomplicated, baroque, pointless
- segment-override-and-LDT/GDT garbage foisted upon us all by Intel,
- in its infinite wisdom.=20
-
- THIS IS CALLED FROM GENERATED CODE (AND SO RUNS ON REAL CPU).=20
-*/
-Addr VG_(do_useseg) ( UInt seg_selector, Addr virtual_addr )
-{
- UInt table;
- Addr base;
- UInt limit;
-
- if (0)=20
- VG_(printf)("do_useseg: seg_selector =3D %p, vaddr =3D %p\n",=20
- seg_selector, virtual_addr);
-
- seg_selector &=3D 0x0000FFFF;
- =20
- /* Sanity check the segment selector. Ensure that RPL=3D11b (least
- privilege). This forms the bottom 2 bits of the selector. */
- if ((seg_selector & 3) !=3D 3) {
- VG_(synth_fault)(VG_(get_current_tid)());
- return 0;
- }
-
- /* Extract the table number */
- table =3D (seg_selector & 4) >> 2;
-
- /* Convert the segment selector onto a table index */
- seg_selector >>=3D 3;
-
- if (table =3D=3D 0) {
- VgLdtEntry* the_tls;
-
- vg_assert(seg_selector >=3D VKI_GDT_ENTRY_TLS_MIN && seg_selector =
<=3D VKI_GDT_ENTRY_TLS_MAX);
-
- /* Come up with a suitable GDT entry. We look at the thread's TLS
- array, which is pointed to by a VG_(baseBlock) entry. */
- the_tls =3D (VgLdtEntry*)VG_(baseBlock)[VGOFF_(tls_ptr)];
- base =3D (Addr)wine_ldt_get_base ( &the_tls[seg_selector-VKI_GDT_E=
NTRY_TLS_MIN] );
- limit =3D (UInt)wine_ldt_get_limit ( &the_tls[seg_selector-VKI_GDT=
_ENTRY_TLS_MIN] );
- } else {
- VgLdtEntry* the_ldt;
-
- vg_assert(seg_selector >=3D 0 && seg_selector < 8192);
-
- /* Come up with a suitable LDT entry. We look at the thread's LDT=
,
- which is pointed to by a VG_(baseBlock) entry. If null, we will
- use an implied zero-entry -- although this usually implies the
- program is in deep trouble, since it is using LDT entries which
- it probably hasn't set up. */
- the_ldt =3D (VgLdtEntry*)VG_(baseBlock)[VGOFF_(ldt)];
- if (the_ldt =3D=3D NULL) {
- base =3D 0;
- limit =3D 0;
- VG_(message)(
- Vg_UserMsg,
- "Warning: segment-override prefix encountered, but thread has no LD=
T"
- );
- } else {
- base =3D (Addr)wine_ldt_get_base ( &the_ldt[seg_selector] );
- limit =3D (UInt)wine_ldt_get_limit ( &the_ldt[seg_selector] );
- }
- }
-
- /* Note, this check is just slightly too slack. Really it should
- be "if (virtual_addr + size - 1 >=3D limit)," but we don't have the
- size info to hand. Getting it could be significantly complex. */
- if (virtual_addr >=3D limit) {
- VG_(message)(
- Vg_UserMsg,
- "Warning: segment access: virtual addr %d exceeds segment limit=
of %d",
- virtual_addr, limit
- );
- }
-
- if (0)=20
- VG_(printf)("do_useseg: base =3D %p, addr =3D %p\n",=20
- base, base + virtual_addr);
-
- return base + virtual_addr;
-}
-#endif
-
-/* Translate a struct modify_ldt_ldt_s to an VgLdtEntry, using the
- Linux kernel's logic (cut-n-paste of code in linux/kernel/ldt.c). */
-
-static
-void translate_to_hw_format ( /* IN */ vki_modify_ldt_t* inn,
- /* OUT */ VgLdtEntry* out,
- Int oldmode )
-{
- UInt entry_1, entry_2;
-
- if (0)
- VG_(printf)("translate_to_hw_format: base %p, limit %d\n",=20
- inn->base_addr, inn->limit );
-
- /* Allow LDTs to be cleared by the user. */
- if (inn->base_addr =3D=3D 0 && inn->limit =3D=3D 0) {
- if (oldmode ||
- (inn->contents =3D=3D 0 &&
- inn->read_exec_only =3D=3D 1 &&
- inn->seg_32bit =3D=3D 0 &&
- inn->limit_in_pages =3D=3D 0 &&
- inn->seg_not_present =3D=3D 1 &&
- inn->useable =3D=3D 0 )) {
- entry_1 =3D 0;
- entry_2 =3D 0;
- goto install;
- }
- }
-
- entry_1 =3D ((inn->base_addr & 0x0000ffff) << 16) |
- (inn->limit & 0x0ffff);
- entry_2 =3D (inn->base_addr & 0xff000000) |
- ((inn->base_addr & 0x00ff0000) >> 16) |
- (inn->limit & 0xf0000) |
- ((inn->read_exec_only ^ 1) << 9) |
- (inn->contents << 10) |
- ((inn->seg_not_present ^ 1) << 15) |
- (inn->seg_32bit << 22) |
- (inn->limit_in_pages << 23) |
- 0x7000;
- if (!oldmode)
- entry_2 |=3D (inn->useable << 20);
-
- /* Install the new entry ... */
- install:
- out->LdtEnt.Words.word1 =3D entry_1;
- out->LdtEnt.Words.word2 =3D entry_2;
-}
-
-
-/*
- * linux/kernel/ldt.c
- *
- * Copyright (C) 1992 Krishna Balasubramanian and Linus Torvalds
- * Copyright (C) 1999 Ingo Molnar <mi...@re...>
- */
-
-/*
- * read_ldt() is not really atomic - this is not a problem since
- * synchronization of reads and writes done to the LDT has to be
- * assured by user-space anyway. Writes are atomic, to protect
- * the security checks done on new descriptors.
- */
-static
-Int read_ldt ( ThreadId tid, UChar* ptr, UInt bytecount )
-{
- Int err;
- UInt i, size;
- Char* ldt;
-
- if (0)
- VG_(printf)("read_ldt: tid =3D %d, ptr =3D %p, bytecount =3D %d\n"=
,
- tid, ptr, bytecount );
-
- ldt =3D (Char*)(VG_(threads)[tid].arch.ldt);
- err =3D 0;
- if (ldt =3D=3D NULL)
- /* LDT not allocated, meaning all entries are null */
- goto out;
-
- size =3D VG_M_LDT_ENTRIES * VG_LDT_ENTRY_SIZE;
- if (size > bytecount)
- size =3D bytecount;
-
- err =3D size;
- for (i =3D 0; i < size; i++)
- ptr[i] =3D ldt[i];
-
- out:
- return err;
-}
-
-
-static
-Int write_ldt ( ThreadId tid, void* ptr, UInt bytecount, Int oldmode )
-{
- Int error;
- VgLdtEntry* ldt;
- vki_modify_ldt_t* ldt_info;=20
-
- if (0)
- VG_(printf)("write_ldt: tid =3D %d, ptr =3D %p, "
- "bytecount =3D %d, oldmode =3D %d\n",
- tid, ptr, bytecount, oldmode );
-
- ldt =3D VG_(threads)[tid].arch.ldt;
- ldt_info =3D (vki_modify_ldt_t*)ptr;
-
- error =3D -VKI_EINVAL;
- if (bytecount !=3D sizeof(vki_modify_ldt_t))
- goto out;
-
- error =3D -VKI_EINVAL;
- if (ldt_info->entry_number >=3D VG_M_LDT_ENTRIES)
- goto out;
- if (ldt_info->contents =3D=3D 3) {
- if (oldmode)
- goto out;
- if (ldt_info->seg_not_present =3D=3D 0)
- goto out;
- }
-
- /* If this thread doesn't have an LDT, we'd better allocate it
- now. */
- if (ldt =3D=3D NULL) {
- ldt =3D VG_(allocate_LDT_for_thread)( NULL );
- VG_(threads)[tid].arch.ldt =3D ldt;
- }
-
- /* Install the new entry ... */
- translate_to_hw_format ( ldt_info, &ldt[ldt_info->entry_number], oldm=
ode );
- error =3D 0;
-
- out:
- return error;
-}
-
-
-Int VG_(sys_modify_ldt) ( ThreadId tid,
- Int func, void* ptr, UInt bytecount )
-{
- Int ret =3D -VKI_ENOSYS;
-
- switch (func) {
- case 0:
- ret =3D read_ldt(tid, ptr, bytecount);
- break;
- case 1:
- ret =3D write_ldt(tid, ptr, bytecount, 1);
- break;
- case 2:
- VG_(unimplemented)("sys_modify_ldt: func =3D=3D 2");
- /* god knows what this is about */
- /* ret =3D read_default_ldt(ptr, bytecount); */
- /*UNREACHED*/
- break;
- case 0x11:
- ret =3D write_ldt(tid, ptr, bytecount, 0);
- break;
- }
- return ret;
-}
-
-
-Int VG_(sys_set_thread_area) ( ThreadId tid,
- vki_modify_ldt_t* info )
-{
- Int idx;
-
- if (info =3D=3D NULL)
- return -VKI_EFAULT;
-
- idx =3D info->entry_number;
-
- if (idx =3D=3D -1) {
- for (idx =3D 0; idx < VKI_GDT_ENTRY_TLS_ENTRIES; idx++) {
- VgLdtEntry* tls =3D VG_(threads)[tid].arch.tls + idx;
-
- if (tls->LdtEnt.Words.word1 =3D=3D 0 && tls->LdtEnt.Words.word2=
=3D=3D 0)
- break;
- }
-
- if (idx =3D=3D VKI_GDT_ENTRY_TLS_ENTRIES)
- return -VKI_ESRCH;
- } else if (idx < VKI_GDT_ENTRY_TLS_MIN || idx > VKI_GDT_ENTRY_TLS_MAX=
) {
- return -VKI_EINVAL;
- } else {
- idx =3D info->entry_number - VKI_GDT_ENTRY_TLS_MIN;
- }
-
- translate_to_hw_format(info, VG_(threads)[tid].arch.tls + idx, 0);
-
- VG_TRACK( pre_mem_write, Vg_CoreSysCall, tid,
- "set_thread_area(info->entry)",
- (Addr) & info->entry_number, sizeof(unsigned int) );
- info->entry_number =3D idx + VKI_GDT_ENTRY_TLS_MIN;
- VG_TRACK( post_mem_write, Vg_CoreSysCall, tid,
- (Addr) & info->entry_number, sizeof(unsigned int) );
-
- return 0;
-}
-
-
-Int VG_(sys_get_thread_area) ( ThreadId tid,
- vki_modify_ldt_t* info )
-{
- Int idx;
- VgLdtEntry* tls;
-
- if (info =3D=3D NULL)
- return -VKI_EFAULT;
-
- idx =3D info->entry_number;
-
- if (idx < VKI_GDT_ENTRY_TLS_MIN || idx > VKI_GDT_ENTRY_TLS_MAX)
- return -VKI_EINVAL;
-
- tls =3D VG_(threads)[tid].arch.tls + idx - VKI_GDT_ENTRY_TLS_MIN;
-
- info->base_addr =3D ( tls->LdtEnt.Bits.BaseHi << 24 ) |
- ( tls->LdtEnt.Bits.BaseMid << 16 ) |
- tls->LdtEnt.Bits.BaseLow;
- info->limit =3D ( tls->LdtEnt.Bits.LimitHi << 16 ) |
- tls->LdtEnt.Bits.LimitLow;
- info->seg_32bit =3D tls->LdtEnt.Bits.Default_Big;
- info->contents =3D ( tls->LdtEnt.Bits.Type >> 2 ) & 0x3;
- info->read_exec_only =3D ( tls->LdtEnt.Bits.Type & 0x1 ) ^ 0x1;
- info->limit_in_pages =3D tls->LdtEnt.Bits.Granularity;
- info->seg_not_present =3D tls->LdtEnt.Bits.Pres ^ 0x1;
- info->useable =3D tls->LdtEnt.Bits.Sys;
- info->reserved =3D 0;
-
- return 0;
-}
-#endif
-
-/*--------------------------------------------------------------------*/
-/*--- end ---*/
-/*--------------------------------------------------------------------*/
Modified: trunk/coregrind/core.h
=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
--- trunk/coregrind/core.h 2005-05-15 18:51:47 UTC (rev 3725)
+++ trunk/coregrind/core.h 2005-05-15 20:52:04 UTC (rev 3726)
@@ -805,10 +805,6 @@
Addr esp_at_startup,
/*MOD*/ ThreadArchState* arch );
=20
-// Thread stuff
-extern void VGA_(cleanup_thread) ( ThreadArchState* );
-extern void VGA_(setup_child) ( ThreadArchState*, ThreadArchState* );
-
// OS/Platform-specific thread clear (after thread exit)
extern void VGA_(os_state_clear)(ThreadState *);
=20
Modified: trunk/coregrind/m_syscalls/syscalls-amd64-linux.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
--- trunk/coregrind/m_syscalls/syscalls-amd64-linux.c 2005-05-15 18:51:47=
UTC (rev 3725)
+++ trunk/coregrind/m_syscalls/syscalls-amd64-linux.c 2005-05-15 20:52:04=
UTC (rev 3726)
@@ -45,7 +45,7 @@
=20
=20
/* ---------------------------------------------------------------------
- Stacks, thread wrappers, clone
+ Stacks, thread wrappers
Note. Why is this stuff here?
------------------------------------------------------------------ */
=20
@@ -107,7 +107,7 @@
get called multiple times.
*/
/* NB: this is identical to the x86 version */
-void VGA_(interrupted_syscall)(ThreadId tid,=20
+void VGP_(interrupted_syscall)(ThreadId tid,=20
struct vki_ucontext *uc,
Bool restart)
{
@@ -301,9 +301,14 @@
VG_(core_panic)("Thread exit failed?\n");
}
=20
-/*=20
+/* ---------------------------------------------------------------------
clone() handling
+ ------------------------------------------------------------------ */
=20
+// forward declaration
+static void setup_child ( ThreadArchState*, ThreadArchState* );
+
+/*=20
When a client clones, we need to keep track of the new thread. This =
means:
1. allocate a ThreadId+ThreadState+stack for the the thread
=20
@@ -348,7 +353,7 @@
If the clone call specifies a NULL rsp for the new thread, then
it actually gets a copy of the parent's rsp.
*/
- VGA_(setup_child)( &ctst->arch, &ptst->arch );
+ setup_child( &ctst->arch, &ptst->arch );
=20
VGP_SET_SYSCALL_RESULT(ctst->arch, 0);
if (rsp !=3D 0)
@@ -401,7 +406,7 @@
=20
if (ret < 0) {
/* clone failed */
- VGA_(cleanup_thread)(&ctst->arch);
+ VGP_(cleanup_thread)(&ctst->arch);
ctst->status =3D VgTs_Empty;
}
=20
@@ -451,6 +456,22 @@
}
=20
/* ---------------------------------------------------------------------
+ More thread stuff
+ ------------------------------------------------------------------ */
+
+void VGP_(cleanup_thread) ( ThreadArchState *arch )
+{ =20
+} =20
+
+void setup_child ( /*OUT*/ ThreadArchState *child,=20
+ /*IN*/ ThreadArchState *parent )
+{ =20
+ /* We inherit our parent's guest state. */
+ child->vex =3D parent->vex;
+ child->vex_shadow =3D parent->vex_shadow;
+} =20
+
+/* ---------------------------------------------------------------------
PRE/POST wrappers for AMD64/Linux-specific syscalls
------------------------------------------------------------------ */
=20
Modified: trunk/coregrind/m_syscalls/syscalls-x86-linux.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
--- trunk/coregrind/m_syscalls/syscalls-x86-linux.c 2005-05-15 18:51:47 U=
TC (rev 3725)
+++ trunk/coregrind/m_syscalls/syscalls-x86-linux.c 2005-05-15 20:52:04 U=
TC (rev 3726)
@@ -43,7 +43,7 @@
=20
=20
/* ---------------------------------------------------------------------
- Stacks, thread wrappers, clone
+ Stacks, thread wrappers
Note. Why is this stuff here?
------------------------------------------------------------------ */
=20
@@ -105,7 +105,7 @@
get called multiple times.
*/
/* NB: this is identical to the amd64 version */
-void VGA_(interrupted_syscall)(ThreadId tid,=20
+void VGP_(interrupted_syscall)(ThreadId tid,=20
struct vki_ucontext *uc,
Bool restart)
{
@@ -299,9 +299,15 @@
VG_(core_panic)("Thread exit failed?\n");
}
=20
-/*=20
+/* ---------------------------------------------------------------------
clone() handling
+ ------------------------------------------------------------------ */
=20
+// forward declarations
+static void setup_child ( ThreadArchState*, ThreadArchState* );
+static Int sys_set_thread_area ( ThreadId, vki_modify_ldt_t* );
+
+/*=20
When a client clones, we need to keep track of the new thread. This =
means:
1. allocate a ThreadId+ThreadState+stack for the the thread
=20
@@ -346,7 +352,7 @@
If the clone call specifies a NULL esp for the new thread, then
it actually gets a copy of the parent's esp.
*/
- VGA_(setup_child)( &ctst->arch, &ptst->arch );
+ setup_child( &ctst->arch, &ptst->arch );
=20
VGP_SET_SYSCALL_RESULT(ctst->arch, 0);
if (esp !=3D 0)
@@ -386,7 +392,7 @@
tlsinfo, tlsinfo->entry_number, tlsinfo->base_addr, tlsinfo->limi=
t,
ptst->arch.vex.guest_ESP,
ctst->arch.vex.guest_FS, ctst->arch.vex.guest_GS);
- ret =3D VG_(sys_set_thread_area)(ctid, tlsinfo);
+ ret =3D sys_set_thread_area(ctid, tlsinfo);
=20
if (ret !=3D 0)
goto out;
@@ -406,7 +412,7 @@
out:
if (ret < 0) {
/* clone failed */
- VGA_(cleanup_thread)(&ctst->arch);
+ VGP_(cleanup_thread)(&ctst->arch);
ctst->status =3D VgTs_Empty;
}
=20
@@ -456,6 +462,411 @@
}
=20
/* ---------------------------------------------------------------------
+ LDT/GDT simulation
+ ------------------------------------------------------------------ */
+
+/* Details of the LDT simulation
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ =20
+ When a program runs natively, the linux kernel allows each *thread*
+ in it to have its own LDT. Almost all programs never do this --
+ it's wildly unportable, after all -- and so the kernel never
+ allocates the structure, which is just as well as an LDT occupies
+ 64k of memory (8192 entries of size 8 bytes).
+
+ A thread may choose to modify its LDT entries, by doing the
+ __NR_modify_ldt syscall. In such a situation the kernel will then
+ allocate an LDT structure for it. Each LDT entry is basically a
+ (base, limit) pair. A virtual address in a specific segment is
+ translated to a linear address by adding the segment's base value.
+ In addition, the virtual address must not exceed the limit value.
+
+ To use an LDT entry, a thread loads one of the segment registers
+ (%cs, %ss, %ds, %es, %fs, %gs) with the index of the LDT entry (0
+ .. 8191) it wants to use. In fact, the required value is (index <<
+ 3) + 7, but that's not important right now. Any normal instruction
+ which includes an addressing mode can then be made relative to that
+ LDT entry by prefixing the insn with a so-called segment-override
+ prefix, a byte which indicates which of the 6 segment registers
+ holds the LDT index.
+
+ Now, a key constraint is that valgrind's address checks operate in
+ terms of linear addresses. So we have to explicitly translate
+ virtual addrs into linear addrs, and that means doing a complete
+ LDT simulation.
+
+ Calls to modify_ldt are intercepted. For each thread, we maintain
+ an LDT (with the same normally-never-allocated optimisation that
+ the kernel does). This is updated as expected via calls to
+ modify_ldt.
+
+ When a thread does an amode calculation involving a segment
+ override prefix, the relevant LDT entry for the thread is
+ consulted. It all works.
+
+ There is a conceptual problem, which appears when switching back to
+ native execution, either temporarily to pass syscalls to the
+ kernel, or permanently, when debugging V. Problem at such points
+ is that it's pretty pointless to copy the simulated machine's
+ segment registers to the real machine, because we'd also need to
+ copy the simulated LDT into the real one, and that's prohibitively
+ expensive.
+
+ Fortunately it looks like no syscalls rely on the segment regs or
+ LDT being correct, so we can get away with it. Apart from that the
+ simulation is pretty straightforward. All 6 segment registers are
+ tracked, although only %ds, %es, %fs and %gs are allowed as
+ prefixes. Perhaps it could be restricted even more than that -- I
+ am not sure what is and isn't allowed in user-mode.
+*/
+
+/* Translate a struct modify_ldt_ldt_s to a VexGuestX86SegDescr, using
+ the Linux kernel's logic (cut-n-paste of code in
+ linux/kernel/ldt.c). */
+
+static
+void translate_to_hw_format ( /* IN */ vki_modify_ldt_t* inn,
+ /* OUT */ VexGuestX86SegDescr* out,
+ Int oldmode )
+{
+ UInt entry_1, entry_2;
+ vg_assert(8 =3D=3D sizeof(VexGuestX86SegDescr));
+
+ if (0)
+ VG_(printf)("translate_to_hw_format: base %p, limit %d\n",=20
+ inn->base_addr, inn->limit );
+
+ /* Allow LDTs to be cleared by the user. */
+ if (inn->base_addr =3D=3D 0 && inn->limit =3D=3D 0) {
+ if (oldmode ||
+ (inn->contents =3D=3D 0 &&
+ inn->read_exec_only =3D=3D 1 &&
+ inn->seg_32bit =3D=3D 0 &&
+ inn->limit_in_pages =3D=3D 0 &&
+ inn->seg_not_present =3D=3D 1 &&
+ inn->useable =3D=3D 0 )) {
+ entry_1 =3D 0;
+ entry_2 =3D 0;
+ goto install;
+ }
+ }
+
+ entry_1 =3D ((inn->base_addr & 0x0000ffff) << 16) |
+ (inn->limit & 0x0ffff);
+ entry_2 =3D (inn->base_addr & 0xff000000) |
+ ((inn->base_addr & 0x00ff0000) >> 16) |
+ (inn->limit & 0xf0000) |
+ ((inn->read_exec_only ^ 1) << 9) |
+ (inn->contents << 10) |
+ ((inn->seg_not_present ^ 1) << 15) |
+ (inn->seg_32bit << 22) |
+ (inn->limit_in_pages << 23) |
+ 0x7000;
+ if (!oldmode)
+ entry_2 |=3D (inn->useable << 20);
+
+ /* Install the new entry ... */
+ install:
+ out->LdtEnt.Words.word1 =3D entry_1;
+ out->LdtEnt.Words.word2 =3D entry_2;
+}
+
+/* Create a zeroed-out GDT. */
+static VexGuestX86SegDescr* alloc_zeroed_x86_GDT ( void )
+{
+ Int nbytes =3D VEX_GUEST_X86_GDT_NENT * sizeof(VexGuestX86SegDescr);
+ return VG_(arena_calloc)(VG_AR_CORE, nbytes, 1);
+}
+
+/* Create a zeroed-out LDT. */
+static VexGuestX86SegDescr* alloc_zeroed_x86_LDT ( void )
+{
+ Int nbytes =3D VEX_GUEST_X86_LDT_NENT * sizeof(VexGuestX86SegDescr);
+ return VG_(arena_calloc)(VG_AR_CORE, nbytes, 1);
+}
+
+/* Free up an LDT or GDT allocated by the above fns. */
+static void free_LDT_or_GDT ( VexGuestX86SegDescr* dt )
+{
+ vg_assert(dt);
+ VG_(arena_free)(VG_AR_CORE, (void*)dt);
+}
+
+/* Copy contents between two existing LDTs. */
+static void copy_LDT_from_to ( VexGuestX86SegDescr* src,
+ VexGuestX86SegDescr* dst )
+{
+ Int i;
+ vg_assert(src);
+ vg_assert(dst);
+ for (i =3D 0; i < VEX_GUEST_X86_LDT_NENT; i++)
+ dst[i] =3D src[i];
+}
+
+/* Free this thread's DTs, if it has any. */
+static void deallocate_LGDTs_for_thread ( VexGuestX86State* vex )
+{
+ vg_assert(sizeof(HWord) =3D=3D sizeof(void*));
+
+ if (0)
+ VG_(printf)("deallocate_LGDTs_for_thread: "
+ "ldt =3D 0x%x, gdt =3D 0x%x\n",=20
+ vex->guest_LDT, vex->guest_GDT );
+
+ if (vex->guest_LDT !=3D (HWord)NULL) {
+ free_LDT_or_GDT( (VexGuestX86SegDescr*)vex->guest_LDT );
+ vex->guest_LDT =3D (HWord)NULL;
+ }
+
+ if (vex->guest_GDT !=3D (HWord)NULL) {
+ free_LDT_or_GDT( (VexGuestX86SegDescr*)vex->guest_GDT );
+ vex->guest_GDT =3D (HWord)NULL;
+ }
+}
+
+
+/*
+ * linux/kernel/ldt.c
+ *
+ * Copyright (C) 1992 Krishna Balasubramanian and Linus Torvalds
+ * Copyright (C) 1999 Ingo Molnar <mi...@re...>
+ */
+
+/*
+ * read_ldt() is not really atomic - this is not a problem since
+ * synchronization of reads and writes done to the LDT has to be
+ * assured by user-space anyway. Writes are atomic, to protect
+ * the security checks done on new descriptors.
+ */
+static
+Int read_ldt ( ThreadId tid, UChar* ptr, UInt bytecount )
+{
+ Int err;
+ UInt i, size;
+ UChar* ldt;
+
+ if (0)
+ VG_(printf)("read_ldt: tid =3D %d, ptr =3D %p, bytecount =3D %d\n"=
,
+ tid, ptr, bytecount );
+
+ vg_assert(sizeof(HWord) =3D=3D sizeof(VexGuestX86SegDescr*));
+ vg_assert(8 =3D=3D sizeof(VexGuestX86SegDescr));
+
+ ldt =3D (Char*)(VG_(threads)[tid].arch.vex.guest_LDT);
+ err =3D 0;
+ if (ldt =3D=3D NULL)
+ /* LDT not allocated, meaning all entries are null */
+ goto out;
+
+ size =3D VEX_GUEST_X86_LDT_NENT * sizeof(VexGuestX86SegDescr);
+ if (size > bytecount)
+ size =3D bytecount;
+
+ err =3D size;
+ for (i =3D 0; i < size; i++)
+ ptr[i] =3D ldt[i];
+
+ out:
+ return err;
+}
+
+
+static
+Int write_ldt ( ThreadId tid, void* ptr, UInt bytecount, Int oldmode )
+{
+ Int error;
+ VexGuestX86SegDescr* ldt;
+ vki_modify_ldt_t* ldt_info;=20
+
+ if (0)
+ VG_(printf)("write_ldt: tid =3D %d, ptr =3D %p, "
+ "bytecount =3D %d, oldmode =3D %d\n",
+ tid, ptr, bytecount, oldmode );
+
+ vg_assert(8 =3D=3D sizeof(VexGuestX86SegDescr));
+ vg_assert(sizeof(HWord) =3D=3D sizeof(VexGuestX86SegDescr*));
+
+ ldt =3D (VexGuestX86SegDescr*)VG_(threads)[tid].arch.vex.guest_L=
DT;
+ ldt_info =3D (vki_modify_ldt_t*)ptr;
+
+ error =3D -VKI_EINVAL;
+ if (bytecount !=3D sizeof(vki_modify_ldt_t))
+ goto out;
+
+ error =3D -VKI_EINVAL;
+ if (ldt_info->entry_number >=3D VEX_GUEST_X86_LDT_NENT)
+ goto out;
+ if (ldt_info->contents =3D=3D 3) {
+ if (oldmode)
+ goto out;
+ if (ldt_info->seg_not_present =3D=3D 0)
+ goto out;
+ }
+
+ /* If this thread doesn't have an LDT, we'd better allocate it
+ now. */
+ if (ldt =3D=3D (HWord)NULL) {
+ ldt =3D alloc_zeroed_x86_LDT();
+ VG_(threads)[tid].arch.vex.guest_LDT =3D (HWord)ldt;
+ }
+
+ /* Install the new entry ... */
+ translate_to_hw_format ( ldt_info, &ldt[ldt_info->entry_number], oldm=
ode );
+ error =3D 0;
+
+ out:
+ return error;
+}
+
+
+static Int sys_modify_ldt ( ThreadId tid,
+ Int func, void* ptr, UInt bytecount )
+{
+ Int ret =3D -VKI_ENOSYS;
+
+ switch (func) {
+ case 0:
+ ret =3D read_ldt(tid, ptr, bytecount);
+ break;
+ case 1:
+ ret =3D write_ldt(tid, ptr, bytecount, 1);
+ break;
+ case 2:
+ VG_(unimplemented)("sys_modify_ldt: func =3D=3D 2");
+ /* god knows what this is about */
+ /* ret =3D read_default_ldt(ptr, bytecount); */
+ /*UNREACHED*/
+ break;
+ case 0x11:
+ ret =3D write_ldt(tid, ptr, bytecount, 0);
+ break;
+ }
+ return ret;
+}
+
+
+static Int sys_set_thread_area ( ThreadId tid, vki_modify_ldt_t* info )
+{
+ Int idx;
+ VexGuestX86SegDescr* gdt;
+
+ vg_assert(8 =3D=3D sizeof(VexGuestX86SegDescr));
+ vg_assert(sizeof(HWord) =3D=3D sizeof(VexGuestX86SegDescr*));
+
+ if (info =3D=3D NULL)
+ return -VKI_EFAULT;
+
+ gdt =3D (VexGuestX86SegDescr*)VG_(threads)[tid].arch.vex.guest_GDT;
+
+ /* If the thread doesn't have a GDT, allocate it now. */
+ if (!gdt) {
+ gdt =3D alloc_zeroed_x86_GDT();
+ VG_(threads)[tid].arch.vex.guest_GDT =3D (HWord)gdt;
+ }
+
+ idx =3D info->entry_number;
+
+ if (idx =3D=3D -1) {
+ /* Find and use the first free entry. */
+ for (idx =3D 0; idx < VEX_GUEST_X86_GDT_NENT; idx++) {
+ if (gdt[idx].LdtEnt.Words.word1 =3D=3D 0=20
+ && gdt[idx].LdtEnt.Words.word2 =3D=3D 0)
+ break;
+ }
+
+ if (idx =3D=3D VEX_GUEST_X86_GDT_NENT)
+ return -VKI_ESRCH;
+ } else if (idx < 0 || idx >=3D VEX_GUEST_X86_GDT_NENT) {
+ return -VKI_EINVAL;
+ }
+
+ translate_to_hw_format(info, &gdt[idx], 0);
+
+ VG_TRACK( pre_mem_write, Vg_CoreSysCall, tid,
+ "set_thread_area(info->entry)",
+ (Addr) & info->entry_number, sizeof(unsigned int) );
+ info->entry_number =3D idx;
+ VG_TRACK( post_mem_write, Vg_CoreSysCall, tid,
+ (Addr) & info->entry_number, sizeof(unsigned int) );
+
+ return 0;
+}
+
+
+static Int sys_get_thread_area ( ThreadId tid, vki_modify_ldt_t* info )
+{
+ Int idx;
+ VexGuestX86SegDescr* gdt;
+
+ vg_assert(sizeof(HWord) =3D=3D sizeof(VexGuestX86SegDescr*));
+ vg_assert(8 =3D=3D sizeof(VexGuestX86SegDescr));
+
+ if (info =3D=3D NULL)
+ return -VKI_EFAULT;
+
+ idx =3D info->entry_number;
+
+ if (idx < 0 || idx >=3D VEX_GUEST_X86_GDT_NENT)
+ return -VKI_EINVAL;
+
+ gdt =3D (VexGuestX86SegDescr*)VG_(threads)[tid].arch.vex.guest_GDT;
+
+ /* If the thread doesn't have a GDT, allocate it now. */
+ if (!gdt) {
+ gdt =3D alloc_zeroed_x86_GDT();
+ VG_(threads)[tid].arch.vex.guest_GDT =3D (HWord)gdt;
+ }
+
+ info->base_addr =3D ( gdt[idx].LdtEnt.Bits.BaseHi << 24 ) |
+ ( gdt[idx].LdtEnt.Bits.BaseMid << 16 ) |
+ gdt[idx].LdtEnt.Bits.BaseLow;
+ info->limit =3D ( gdt[idx].LdtEnt.Bits.LimitHi << 16 ) |
+ gdt[idx].LdtEnt.Bits.LimitLow;
+ info->seg_32bit =3D gdt[idx].LdtEnt.Bits.Default_Big;
+ info->contents =3D ( gdt[idx].LdtEnt.Bits.Type >> 2 ) & 0x3;
+ info->read_exec_only =3D ( gdt[idx].LdtEnt.Bits.Type & 0x1 ) ^ 0x1;
+ info->limit_in_pages =3D gdt[idx].LdtEnt.Bits.Granularity;
+ info->seg_not_present =3D gdt[idx].LdtEnt.Bits.Pres ^ 0x1;
+ info->useable =3D gdt[idx].LdtEnt.Bits.Sys;
+ info->reserved =3D 0;
+
+ return 0;
+}
+
+/* ---------------------------------------------------------------------
+ More thread stuff
+ ------------------------------------------------------------------ */
+
+void VGP_(cleanup_thread) ( ThreadArchState* arch )
+{
+ /* Release arch-specific resources held by this thread. */
+ /* On x86, we have to dump the LDT and GDT. */
+ deallocate_LGDTs_for_thread( &arch->vex );
+} =20
+
+
+static void setup_child ( /*OUT*/ ThreadArchState *child,=20
+ /*IN*/ ThreadArchState *parent )
+{
+ /* We inherit our parent's guest state. */
+ child->vex =3D parent->vex;
+ child->vex_shadow =3D parent->vex_shadow;
+ /* We inherit our parent's LDT. */
+ if (parent->vex.guest_LDT =3D=3D (HWord)NULL) {
+ /* We hope this is the common case. */
+ child->vex.guest_LDT =3D (HWord)NULL;
+ } else {
+ /* No luck .. we have to take a copy of the parent's. */
+ child->vex.guest_LDT =3D (HWord)alloc_zeroed_x86_LDT();
+ copy_LDT_from_to( (VexGuestX86SegDescr*)parent->vex.guest_LDT,=20
+ (VexGuestX86SegDescr*)child->vex.guest_LDT );
+ }
+
+ /* We need an empty GDT. */
+ child->vex.guest_GDT =3D (HWord)NULL;
+} =20
+
+/* ---------------------------------------------------------------------
PRE/POST wrappers for x86/Linux-specific syscalls
------------------------------------------------------------------ */
=20
@@ -640,7 +1051,7 @@
PRE_MEM_READ( "modify_ldt(ptr)", ARG2, sizeof(vki_modify_ldt_t) );
}
/* "do" the syscall ourselves; the kernel never sees it */
- SET_RESULT( VG_(sys_modify_ldt)( tid, ARG1, (void*)ARG2, ARG3 ) );
+ SET_RESULT( sys_modify_ldt( tid, ARG1, (void*)ARG2, ARG3 ) );
=20
if (ARG1 =3D=3D 0 && !VG_(is_kerror)(RES) && RES > 0) {
POST_MEM_WRITE( ARG2, RES );
@@ -654,7 +1065,7 @@
PRE_MEM_READ( "set_thread_area(u_info)", ARG1, sizeof(vki_modify_ldt_=
t) );
=20
/* "do" the syscall ourselves; the kernel never sees it */
- SET_RESULT( VG_(sys_set_thread_area)( tid, (void *)ARG1 ) );
+ SET_RESULT( sys_set_thread_area( tid, (void *)ARG1 ) );
}
=20
PRE(sys_get_thread_area, Special)
@@ -664,7 +1075,7 @@
PRE_MEM_WRITE( "get_thread_area(u_info)", ARG1, sizeof(vki_modify_ldt=
_t) );
=20
/* "do" the syscall ourselves; the kernel never sees it */
- SET_RESULT( VG_(sys_get_thread_area)( tid, (void *)ARG1 ) );
+ SET_RESULT( sys_get_thread_area( tid, (void *)ARG1 ) );
=20
if (!VG_(is_kerror)(RES)) {
POST_MEM_WRITE( ARG1, sizeof(vki_modify_ldt_t) );
Modified: trunk/coregrind/pub_core_syscalls.h
=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
--- trunk/coregrind/pub_core_syscalls.h 2005-05-15 18:51:47 UTC (rev 3725=
)
+++ trunk/coregrind/pub_core_syscalls.h 2005-05-15 20:52:04 UTC (rev 3726=
)
@@ -47,10 +47,13 @@
// interrupted with a signal. Returns True if the syscall completed
// (either interrupted or finished normally), or False if it was
// restarted (or the signal didn't actually interrupt a syscall).
-extern void VGA_(interrupted_syscall)(ThreadId tid,
+extern void VGP_(interrupted_syscall)(ThreadId tid,
struct vki_ucontext *uc,
Bool restart);
=20
+// Release resources held by this thread
+extern void VGP_(cleanup_thread) ( ThreadArchState* );
+
extern Bool VG_(is_kerror) ( Word res );
=20
/* Internal atfork handlers */
Modified: trunk/coregrind/vg_scheduler.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
--- trunk/coregrind/vg_scheduler.c 2005-05-15 18:51:47 UTC (rev 3725)
+++ trunk/coregrind/vg_scheduler.c 2005-05-15 20:52:04 UTC (rev 3726)
@@ -551,7 +551,7 @@
vki_sigset_t savedmask;
=20
vg_assert(tid >=3D 0 && tid < VG_N_THREADS);
- VGA_(cleanup_thread)(&VG_(threads)[tid].arch);
+ VGP_(cleanup_thread)(&VG_(threads)[tid].arch);
VG_(threads)[tid].tid =3D tid;
=20
/* Leave the thread in Zombie, so that it doesn't get reallocated
Modified: trunk/coregrind/vg_signals.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
--- trunk/coregrind/vg_signals.c 2005-05-15 18:51:47 UTC (rev 3725)
+++ trunk/coregrind/vg_signals.c 2005-05-15 20:52:04 UTC (rev 3726)
@@ -1651,7 +1651,7 @@
sigNo, tid, info->si_code);
=20
/* Update thread state properly */
- VGA_(interrupted_syscall)(tid, uc,=20
+ VGP_(interrupted_syscall)(tid, uc,=20
!!(scss.scss_per_sig[sigNo].scss_flags & VKI_SA_RESTART));
=20
/* Set up the thread's state to deliver a signal */
Modified: trunk/coregrind/x86/Makefile.am
=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
--- trunk/coregrind/x86/Makefile.am 2005-05-15 18:51:47 UTC (rev 3725)
+++ trunk/coregrind/x86/Makefile.am 2005-05-15 20:52:04 UTC (rev 3726)
@@ -5,8 +5,7 @@
=20
noinst_HEADERS =3D \
core_arch.h \
- core_arch_asm.h \
- x86_private.h
+ core_arch_asm.h
=20
noinst_LIBRARIES =3D libarch.a
=20
Modified: trunk/coregrind/x86/state.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
--- trunk/coregrind/x86/state.c 2005-05-15 18:51:47 UTC (rev 3725)
+++ trunk/coregrind/x86/state.c 2005-05-15 20:52:04 UTC (rev 3726)
@@ -30,7 +30,6 @@
=20
#include "core.h"
#include "pub_core_tooliface.h"
-#include "x86_private.h"
#include "vki_unistd.h"
#include <sys/ptrace.h>
=20
@@ -141,104 +140,10 @@
sizeof(VexGuestArchState));
}
=20
-
/*------------------------------------------------------------*/
-/*--- LDT/GDT stuff ---*/
-/*------------------------------------------------------------*/
-
-/* Create a zeroed-out GDT. */
-
-VexGuestX86SegDescr* VG_(alloc_zeroed_x86_GDT) ( void )
-{
- Int nbytes =3D VEX_GUEST_X86_GDT_NENT * sizeof(VexGuestX86SegDescr);
- return VG_(arena_calloc)(VG_AR_CORE, nbytes, 1);
-}
-
-/* Create a zeroed-out LDT. */
-
-VexGuestX86SegDescr* VG_(alloc_zeroed_x86_LDT) ( void )
-{
- Int nbytes =3D VEX_GUEST_X86_LDT_NENT * sizeof(VexGuestX86SegDescr);
- return VG_(arena_calloc)(VG_AR_CORE, nbytes, 1);
-}
-
-/* Free up an LDT or GDT allocated by the above fns. */
-
-static void free_LDT_or_GDT ( VexGuestX86SegDescr* dt )
-{
- vg_assert(dt);
- VG_(arena_free)(VG_AR_CORE, (void*)dt);
-}
-
-/* Copy contents between two existing LDTs. */
-
-static void copy_LDT_from_to ( VexGuestX86SegDescr* src,
- VexGuestX86SegDescr* dst )
-{
- Int i;
- vg_assert(src);
- vg_assert(dst);
- for (i =3D 0; i < VEX_GUEST_X86_LDT_NENT; i++)
- dst[i] =3D src[i];
-}
-
-/* Free this thread's DTs, if it has any. */
-
-static void deallocate_LGDTs_for_thread ( VexGuestX86State* vex )
-{
- vg_assert(sizeof(HWord) =3D=3D sizeof(void*));
-
- if (0)
- VG_(printf)("deallocate_LGDTs_for_thread: "
- "ldt =3D 0x%x, gdt =3D 0x%x\n",=20
- vex->guest_LDT, vex->guest_GDT );
-
- if (vex->guest_LDT !=3D (HWord)NULL) {
- free_LDT_or_GDT( (VexGuestX86SegDescr*)vex->guest_LDT );
- vex->guest_LDT =3D (HWord)NULL;
- }
-
- if (vex->guest_GDT !=3D (HWord)NULL) {
- free_LDT_or_GDT( (VexGuestX86SegDescr*)vex->guest_GDT );
- vex->guest_GDT =3D (HWord)NULL;
- }
-}
-
-
-/*------------------------------------------------------------*/
/*--- Thread stuff ---*/
/*------------------------------------------------------------*/
=20
-void VGA_(cleanup_thread) ( ThreadArchState* arch )
-{
- /* Release arch-specific resources held by this thread. */
- /* On x86, we have to dump the LDT and GDT. */
- deallocate_LGDTs_for_thread( &arch->vex );
-} =20
-
-
-void VGA_(setup_child) ( /*OUT*/ ThreadArchState *child,=20
- /*IN*/ ThreadArchState *parent )
-{
- /* We inherit our parent's guest state. */
- child->vex =3D parent->vex;
- child->vex_shadow =3D parent->vex_shadow;
- /* We inherit our parent's LDT. */
- if (parent->vex.guest_LDT =3D=3D (HWord)NULL) {
- /* We hope this is the common case. */
- child->vex.guest_LDT =3D (HWord)NULL;
- } else {
- /* No luck .. we have to take a copy of the parent's. */
- child->vex.guest_LDT =3D (HWord)VG_(alloc_zeroed_x86_LDT)();
- copy_LDT_from_to( (VexGuestX86SegDescr*)parent->vex.guest_LDT,=20
- (VexGuestX86SegDescr*)child->vex.guest_LDT );
- }
-
- /* We need an empty GDT. */
- child->vex.guest_GDT =3D (HWord)NULL;
-} =20
-
-
void VGA_(mark_from_registers)(ThreadId tid, void (*marker)(Addr))
{
ThreadState *tst =3D VG_(get_ThreadState)(tid);
Deleted: trunk/coregrind/x86/x86_private.h
=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
--- trunk/coregrind/x86/x86_private.h 2005-05-15 18:51:47 UTC (rev 3725)
+++ trunk/coregrind/x86/x86_private.h 2005-05-15 20:52:04 UTC (rev 3726)
@@ -1,52 +0,0 @@
-
-/*--------------------------------------------------------------------*/
-/*--- Private arch-specific header. x86/x86_private.h ---*/
-/*--------------------------------------------------------------------*/
-
-/*
- This file is part of Valgrind, a dynamic binary instrumentation
- framework.
-
- Copyright (C) 2000-2005 Nicholas Nethercote
- nj...@va...
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307, USA.
-
- The GNU General Public License is contained in the file COPYING.
-*/
-
-#ifndef __X86_PRIVATE_H
-#define __X86_PRIVATE_H
-
-#include "core_arch_asm.h" // arch-specific asm stuff
-#include "tool_arch.h" // arch-specific tool stuff
-
-#include "libvex_guest_x86.h" // for VexGuestX86SegDescr
-
-/* ---------------------------------------------------------------------
- Exports of state.c that are not core-visible
- ------------------------------------------------------------------ */
-
-/* Create LDT/GDT arrays, as specified in libvex_guest_x86.h. */
-extern VexGuestX86SegDescr* VG_(alloc_zeroed_x86_GDT) ( void );
-extern VexGuestX86SegDescr* VG_(alloc_zeroed_x86_LDT) ( void );
-
-
-#endif // __X86_PRIVATE_H
-
-/*--------------------------------------------------------------------*/
-/*--- end ---*/
-/*--------------------------------------------------------------------*/
Modified: trunk/coregrind/x86-linux/Makefile.am
=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
--- trunk/coregrind/x86-linux/Makefile.am 2005-05-15 18:51:47 UTC (rev 37=
25)
+++ trunk/coregrind/x86-linux/Makefile.am 2005-05-15 20:52:04 UTC (rev 37=
26)
@@ -11,8 +11,7 @@
=20
=20
libplatform_a_SOURCES =3D \
- core_platform.c \
- ldt.c
+ core_platform.c
=20
if USE_PIE
libplatform_a_CFLAGS =3D $(AM_CFLAGS) -fpie
Modified: trunk/coregrind/x86-linux/core_platform.h
=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
--- trunk/coregrind/x86-linux/core_platform.h 2005-05-15 18:51:47 UTC (re=
v 3725)
+++ trunk/coregrind/x86-linux/core_platform.h 2005-05-15 20:52:04 UTC (re=
v 3726)
@@ -36,27 +36,6 @@
//#include "platform_arch.h" // platform-specific tool stuff
=20
/* ---------------------------------------------------------------------
- Exports of vg_ldt.c
- ------------------------------------------------------------------ */
-
-// XXX: eventually all these should be x86-private, and not visible to t=
he
-// core (except maybe do_useseg()?)
-
-/* Simulate the modify_ldt syscall. */
-extern Int VG_(sys_modify_ldt) ( ThreadId tid,
- Int func, void* ptr, UInt bytecount );
-
-/* Simulate the {get,set}_thread_area syscalls. */
-extern Int VG_(sys_set_thread_area) ( ThreadId tid,
- vki_modify_ldt_t* info );
-extern Int VG_(sys_get_thread_area) ( ThreadId tid,
- vki_modify_ldt_t* info );
-
-/* Called from generated code. Given a segment selector and a virtual
- address, return a linear address, and do limit checks too. */
-extern Addr VG_(do_useseg) ( UInt seg_selector, Addr virtual_addr );
-
-/* ---------------------------------------------------------------------
ucontext stuff
------------------------------------------------------------------ */
=20
Deleted: trunk/coregrind/x86-linux/ldt.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
--- trunk/coregrind/x86-linux/ldt.c 2005-05-15 18:51:47 UTC (rev 3725)
+++ trunk/coregrind/x86-linux/ldt.c 2005-05-15 20:52:04 UTC (rev 3726)
@@ -1,357 +0,0 @@
-
-/*--------------------------------------------------------------------*/
-/*--- Simulation of Local Descriptor Tables x86-linux/ldt.c ---*/
-/*--------------------------------------------------------------------*/
-
-/*
- This file is part of Valgrind, a dynamic binary instrumentation
- framework.
-
- Copyright (C) 2000-2005 Julian Seward=20
- js...@ac...
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307, USA.
-
- The GNU General Public License is contained in the file COPYING.
-*/
-
-/* Details of the LDT simulation
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- =20
- When a program runs natively, the linux kernel allows each *thread*
- in it to have its own LDT. Almost all programs never do this --
- it's wildly unportable, after all -- and so the kernel never
- allocates the structure, which is just as well as an LDT occupies
- 64k of memory (8192 entries of size 8 bytes).
-
- A thread may choose to modify its LDT entries, by doing the
- __NR_modify_ldt syscall. In such a situation the kernel will then
- allocate an LDT structure for it. Each LDT entry is basically a
- (base, limit) pair. A virtual address in a specific segment is
- translated to a linear address by adding the segment's base value.
- In addition, the virtual address must not exceed the limit value.
-
- To use an LDT entry, a thread loads one of the segment registers
- (%cs, %ss, %ds, %es, %fs, %gs) with the index of the LDT entry (0
- .. 8191) it wants to use. In fact, the required value is (index <<
- 3) + 7, but that's not important right now. Any normal instruction
- which includes an addressing mode can then be made relative to that
- LDT entry by prefixing the insn with a so-called segment-override
- prefix, a byte which indicates which of the 6 segment registers
- holds the LDT index.
-
- Now, a key constraint is that valgrind's address checks operate in
- terms of linear addresses. So we have to explicitly translate
- virtual addrs into linear addrs, and that means doing a complete
- LDT simulation.
-
- Calls to modify_ldt are intercepted. For each thread, we maintain
- an LDT (with the same normally-never-allocated optimisation that
- the kernel does). This is updated as expected via calls to
- modify_ldt.
-
- When a thread does an amode calculation involving a segment
- override prefix, the relevant LDT entry for the thread is
- consulted. It all works.
-
- There is a conceptual problem, which a...
[truncated message content] |