|
From: <sv...@va...> - 2005-09-29 11:10:03
|
Author: sewardj
Date: 2005-09-29 12:09:56 +0100 (Thu, 29 Sep 2005)
New Revision: 4819
Log:
Make ppc32-linux build again following aspacem merge. Doesn't work, thou=
gh:
programs crash before reaching main. I don't know why.
Modified:
trunk/coregrind/m_debugger.c
trunk/coregrind/m_dispatch/dispatch-ppc32.S
trunk/coregrind/m_libcproc.c
trunk/coregrind/m_machine.c
trunk/coregrind/m_main.c
trunk/coregrind/m_sigframe/sigframe-ppc32-linux.c
trunk/coregrind/m_syswrap/syswrap-ppc32-linux.c
trunk/coregrind/m_trampoline.S
trunk/coregrind/m_translate.c
trunk/coregrind/pub_core_machine.h
trunk/coregrind/vki_unistd-ppc32-linux.h
Modified: trunk/coregrind/m_debugger.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_debugger.c 2005-09-29 10:24:17 UTC (rev 4818)
+++ trunk/coregrind/m_debugger.c 2005-09-29 11:09:56 UTC (rev 4819)
@@ -36,6 +36,7 @@
#include "pub_core_libcprint.h"
#include "pub_core_libcproc.h"
#include "pub_core_libcsignal.h"
+#include "pub_core_libcassert.h" // I_die_here
#include "pub_core_options.h"
=20
#define WIFSTOPPED(status) (((status) & 0xff) =3D=3D 0x7f)
Modified: trunk/coregrind/m_dispatch/dispatch-ppc32.S
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=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_dispatch/dispatch-ppc32.S 2005-09-29 10:24:17 UTC (=
rev 4818)
+++ trunk/coregrind/m_dispatch/dispatch-ppc32.S 2005-09-29 11:09:56 UTC (=
rev 4819)
@@ -92,8 +92,8 @@
=20
/* set host AltiVec control word to the default mode expected=20
by VEX-generated code. */
- lis 3,VG_(have_altivec_ppc)@ha
- lwz 3,VG_(have_altivec_ppc)@l(3)
+ lis 3,VG_(have_altivec_ppc32)@ha
+ lwz 3,VG_(have_altivec_ppc32)@l(3)
cmplwi 3,0
beq L1
/* generate vector {0x0,0x0,0x0,0x00010000} */
Modified: trunk/coregrind/m_libcproc.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_libcproc.c 2005-09-29 10:24:17 UTC (rev 4818)
+++ trunk/coregrind/m_libcproc.c 2005-09-29 11:09:56 UTC (rev 4819)
@@ -397,7 +397,7 @@
platform. */
Int VG_(getgroups)( Int size, UInt* list )
{
-# if defined(VGP_x86_linux)
+# if defined(VGP_x86_linux) || defined(VGP_ppc32_linux)
Int i;
SysRes sres;
UShort list16[32];
Modified: trunk/coregrind/m_machine.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_machine.c 2005-09-29 10:24:17 UTC (rev 4818)
+++ trunk/coregrind/m_machine.c 2005-09-29 11:09:56 UTC (rev 4819)
@@ -215,29 +215,30 @@
// Architecture specifics
=20
#if defined(VGA_ppc32)
-// PPC: what is the cache line size (for dcbz etc) ? This info is
-// harvested on Linux at startup from the AT_SYSINFO entries. 0 means
-// not-yet-set.
+/* PPC: what is the cache line size (for dcbz etc) ? This info is
+ harvested on Linux at startup from the AT_SYSINFO entries. 0 means
+ not-yet-set. */
Int VG_(cache_line_size_ppc32) =3D 0;
-// Altivec enabled? Harvested on startup from the AT_HWCAP entry
-Int VG_(have_altivec_ppc) =3D 0;
+
+/* Altivec enabled? Harvested on startup from the AT_HWCAP entry. */
+Int VG_(have_altivec_ppc32) =3D 0;
#endif
=20
-// X86: set to 1 if the host is able to do {ld,st}mxcsr (load/store
-// the SSE control/status register. For most modern CPUs this will be
-// 1. It is set to 1, if possible, by m_translate.getArchAndArchInfo.
-// The value is read by m_dispatch.dispatch-x86.S, which is why it
-// is an Int rather than a Bool.
-//
-// Ugly hack: this has to start as 0 and be set to 1 in the normal
-// case, rather than the other way round, because the dispatch
-// loop needs it, and it runs before the first translation is=20
-// made. Yet it is the act of making that first translation which
-// causes getArchAndArchInfo to set this value to its final value.
-// So it is necessary to start this value off at 0 as only that
-// guarantees that the dispatch loop will not SIGILL on its first
-// attempt.
+
#if defined(VGA_x86)
+/* X86: set to 1 if the host is able to do {ld,st}mxcsr (load/store
+ the SSE control/status register. For most modern CPUs this will be
+ 1. It is set to 1, if possible, by m_translate.getArchAndArchInfo.
+ The value is read by m_dispatch.dispatch-x86.S, which is why it is
+ an Int rather than a Bool.
+
+ Ugly hack: this has to start as 0 and be set to 1 in the normal
+ case, rather than the other way round, because the dispatch loop
+ needs it, and it runs before the first translation is made. Yet it
+ is the act of making that first translation which causes
+ getArchAndArchInfo to set this value to its final value. So it is
+ necessary to start this value off at 0 as only that guarantees that
+ the dispatch loop will not SIGILL on its first attempt. */
Int VG_(have_mxcsr_x86) =3D 0;
#endif
=20
Modified: trunk/coregrind/m_main.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_main.c 2005-09-29 10:24:17 UTC (rev 4818)
+++ trunk/coregrind/m_main.c 2005-09-29 11:09:56 UTC (rev 4819)
@@ -142,7 +142,8 @@
}
VG_(free)(preload_tool_path);
=20
- VG_(debugLog)(1, "main", "preload_string =3D %s\n", preload_string);
+ VG_(debugLog)(2, "main", "preload_string:\n");
+ VG_(debugLog)(2, "main", " \"%s\"\n", preload_string);
=20
/* Count the original size of the env */
envc =3D 0;
@@ -546,11 +547,11 @@
case AT_HWCAP:
# if defined(VGP_ppc32_linux)
/* Acquire altivecness info */
- VG_(debugLog)(1, "main", "PPC32 hwcaps: 0x%x\n",=20
+ VG_(debugLog)(2, "main", "PPC32 hwcaps: 0x%x\n",=20
(UInt)auxv->u.a_val);
if (auxv->u.a_val & 0x10000000)
VG_(have_altivec_ppc32) =3D 1;
- VG_(debugLog)(1, "main", "PPC32 AltiVec support: %u\n",=20
+ VG_(debugLog)(2, "main", "PPC32 AltiVec support: %u\n",=20
VG_(have_altivec_ppc32));
# endif
break;
@@ -562,7 +563,7 @@
/* acquire cache info */
if (auxv->u.a_val > 0) {
VG_(cache_line_size_ppc32) =3D auxv->u.a_val;
- VG_(debugLog)(1, "main",=20
+ VG_(debugLog)(2, "main",=20
"PPC32 cache line size %u (type %u)\n",=20
(UInt)auxv->u.a_val, (UInt)auxv->a_type =
);
}
@@ -1846,7 +1847,7 @@
static Addr* get_seg_starts ( /*OUT*/Int* n_acquired )
{
Addr* starts;
- Int n_starts, r;
+ Int n_starts, r =3D 0;
=20
n_starts =3D 1;
while (True) {
@@ -2094,7 +2095,7 @@
=20
VG_(debugLog)(2, "main",
"Client info: "
- "entry=3D%p client_SP=3D%p brkbase=3D%p\n",
+ "initial_IP=3D%p initial_SP=3D%p brk_base=3D%p\n"=
,
(void*)initial_client_IP,=20
(void*)initial_client_SP,
(void*)VG_(brk_base) );
@@ -2208,7 +2209,7 @@
// p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
//--------------------------------------------------------------
VG_(debugLog)(1, "main", "Process Valgrind's command line options, "
- " setup logging\n");
+ "setup logging\n");
logging_to_fd =3D process_cmd_line_options(client_auxv, toolname);
=20
//--------------------------------------------------------------
@@ -2734,7 +2735,8 @@
*/
=20
/* The kernel hands control to _start, which extracts the initial
- stack pointer and calls onwards to _start_in_C. This also switches t=
he new stack. */
+ stack pointer and calls onwards to _start_in_C. This also switches
+ the new stack. */
#if defined(VGP_x86_linux)
asm("\n"
"\t.globl _start\n"
@@ -2769,6 +2771,30 @@
"\tcall _start_in_C\n"
"\thlt\n"
);
+#elif defined(VGP_ppc32_linux)
+asm("\n"
+ "\t.globl _start\n"
+ "\t.type _start,@function\n"
+ "_start:\n"
+ /* set up the new stack in r16 */
+ "\tlis 16,vgPlain_interim_stack@ha\n"
+ "\tla 16,vgPlain_interim_stack@l(16)\n"
+ "\tlis 17,("VG_STRINGIFY(VG_STACK_GUARD_SZB)" >> 16)\n"
+ "\tori 17,17,("VG_STRINGIFY(VG_STACK_GUARD_SZB)" & 0xFFFF)\n"
+ "\tlis 18,("VG_STRINGIFY(VG_STACK_ACTIVE_SZB)" >> 16)\n"
+ "\tori 18,18,("VG_STRINGIFY(VG_STACK_ACTIVE_SZB)" & 0xFFFF)\n"
+ "\tadd 16,17,16\n"
+ "\tadd 16,18,16\n"
+ "\trlwinm 16,16,0,0,27\n"
+ /* now r16 =3D &vgPlain_interim_stack + VG_STACK_GUARD_SZB +
+ VG_STACK_ACTIVE_SZB rounded down to the nearest 16-byte
+ boundary. And r1 is the original SP. Set the SP to r16 and
+ call _start_in_C, passing it the initial SP. */
+ "\tmr 3,1\n"
+ "\tmr 1,16\n"
+ "\tbl _start_in_C\n"
+ "\ttrap\n"
+);
#else
#error "_start: needs implementation on this platform"
#endif
Modified: trunk/coregrind/m_sigframe/sigframe-ppc32-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_sigframe/sigframe-ppc32-linux.c 2005-09-29 10:24:17=
UTC (rev 4818)
+++ trunk/coregrind/m_sigframe/sigframe-ppc32-linux.c 2005-09-29 11:09:56=
UTC (rev 4819)
@@ -171,7 +171,7 @@
(Addr)&mc->mc_pad, sizeof(mc->mc_pad) );
/* invalidate any translation of this area */
VG_(discard_translations)( (Addr64)(Addr)&mc->mc_pad,=20
- sizeof(mc->mc_pad) ); =20
+ sizeof(mc->mc_pad), "stack_mcontext" ); =20
=20
/* set the signal handler to return to the trampoline */
SET_SIGNAL_LR(tst, (Addr) &mc->mc_pad[0]);
@@ -493,17 +493,16 @@
static Bool extend ( ThreadState *tst, Addr addr, SizeT size )
{
ThreadId tid =3D tst->tid;
- Segment *stackseg =3D NULL;
+ NSegment *stackseg =3D NULL;
=20
if (VG_(extend_stack)(addr, tst->client_stack_szB)) {
- stackseg =3D VG_(find_segment)(addr);
+ stackseg =3D VG_(am_find_nsegment)(addr);
if (0 && stackseg)
VG_(printf)("frame=3D%p seg=3D%p-%p\n",
- addr, stackseg->addr, stackseg->addr+stackseg->len);
+ addr, stackseg->start, stackseg->end);
}
=20
- if (stackseg =3D=3D NULL=20
- || (stackseg->prot & (VKI_PROT_READ|VKI_PROT_WRITE)) =3D=3D 0) {
+ if (stackseg =3D=3D NULL || !stackseg->hasR || !stackseg->hasW) {
VG_(message)(
Vg_UserMsg,
"Can't extend stack to %p during signal delivery for thread %d:=
",
Modified: trunk/coregrind/m_syswrap/syswrap-ppc32-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_syswrap/syswrap-ppc32-linux.c 2005-09-29 10:24:17 U=
TC (rev 4818)
+++ trunk/coregrind/m_syswrap/syswrap-ppc32-linux.c 2005-09-29 11:09:56 U=
TC (rev 4819)
@@ -58,71 +58,46 @@
Note. Why is this stuff here?
------------------------------------------------------------------ */
=20
-/*=20
- Allocate a stack for this thread.
- They're allocated lazily, but never freed.
- */
-#define FILL 0xdeadbeef
+/* Allocate a stack for this thread. They're allocated lazily, and
+ never freed. */
=20
-// Valgrind's stack size, in words.
-#define STACK_SIZE_W 16384
+/* Allocate a stack for this thread, if it doesn't already have one.
+ Returns the initial stack pointer value to use, or 0 if allocation
+ failed. */
=20
-static UWord* allocstack(ThreadId tid)
+static Addr allocstack ( ThreadId tid )
{
- ThreadState *tst =3D VG_(get_ThreadState)(tid);
- UWord *sp;
+ ThreadState* tst =3D VG_(get_ThreadState)(tid);
+ VgStack* stack;
+ Addr initial_SP;
=20
- if (tst->os_state.valgrind_stack_base =3D=3D 0) {
- void *stk =3D VG_(mmap)(0, STACK_SIZE_W * sizeof(UWord) + VKI_PAGE=
_SIZE,
- VKI_PROT_READ|VKI_PROT_WRITE,
- VKI_MAP_PRIVATE|VKI_MAP_ANONYMOUS,
- SF_VALGRIND,
- -1, 0);
+ /* Either the stack_base and stack_init_SP are both zero (in which
+ case a stack hasn't been allocated) or they are both non-zero,
+ in which case it has. */
=20
- if (stk !=3D (void *)-1) {
- VG_(mprotect)(stk, VKI_PAGE_SIZE, VKI_PROT_NONE); /* guard page=
*/
- tst->os_state.valgrind_stack_base =3D ((Addr)stk) + VKI_PAGE_SI=
ZE;
- tst->os_state.valgrind_stack_szB =3D STACK_SIZE_W * sizeof(UWo=
rd);
- } else=20
- return (UWord*)-1;
- }
+ if (tst->os_state.valgrind_stack_base =3D=3D 0)
+ vg_assert(tst->os_state.valgrind_stack_init_SP =3D=3D 0);
=20
- for (sp =3D (UWord*) tst->os_state.valgrind_stack_base;
- sp < (UWord*)(tst->os_state.valgrind_stack_base +=20
- tst->os_state.valgrind_stack_szB);=20
- sp++)
- *sp =3D FILL;
- /* sp is left at top of stack */
+ if (tst->os_state.valgrind_stack_base !=3D 0)
+ vg_assert(tst->os_state.valgrind_stack_init_SP !=3D 0);
=20
- if (0)
- VG_(printf)("stack for tid %d at %p (%x); sp=3D%p\n",
- tid, tst->os_state.valgrind_stack_base,=20
- *(UWord*)(tst->os_state.valgrind_stack_base), sp);
+ /* If no stack is present, allocate one. */
=20
- vg_assert(VG_IS_16_ALIGNED(sp));
+ if (tst->os_state.valgrind_stack_base =3D=3D 0) {
+ stack =3D VG_(am_alloc_VgStack)( &initial_SP );
+ if (stack) {
+ tst->os_state.valgrind_stack_base =3D (Addr)stack;
+ tst->os_state.valgrind_stack_init_SP =3D initial_SP;
+ }
+ }
=20
- return sp;
-}
-
-/* NB: this is identical the the amd64 version. */
-/* Return how many bytes of this stack have not been used */
-SSizeT VG_(stack_unused)(ThreadId tid)
-{
- ThreadState *tst =3D VG_(get_ThreadState)(tid);
- UWord* p;
- =20
- for (p =3D (UWord*)tst->os_state.valgrind_stack_base;=20
- p && (p < (UWord*)(tst->os_state.valgrind_stack_base +
- tst->os_state.valgrind_stack_szB));=20
- p++)
- if (*p !=3D FILL)
- break;
- =20
if (0)
- VG_(printf)("p=3D%p %x tst->os_state.valgrind_stack_base=3D%p\n",
- p, *p, tst->os_state.valgrind_stack_base);
- =20
- return ((Addr)p) - tst->os_state.valgrind_stack_base;
+ VG_(printf)( "stack for tid %d at %p; init_SP=3D%p\n",
+ tid,=20
+ (void*)tst->os_state.valgrind_stack_base,=20
+ (void*)tst->os_state.valgrind_stack_init_SP );
+ =20
+ return tst->os_state.valgrind_stack_init_SP;
}
=20
=20
@@ -162,6 +137,7 @@
( * VG_(address_of_m_main_shutdown_actions_NORETURN) ) (tid, src);
=20
} else {
+
VG_(debugLog)(1, "syswrap-ppc32-linux",=20
"run_a_thread_NORETURN(tid=3D%lld): "
"not last one standing\n",
@@ -254,21 +230,27 @@
);
=20
=20
-/*
- Allocate a stack for the main thread, and run it all the way to the
- end. =20
- */
+/* Allocate a stack for the main thread, and run it all the way to the
+ end. Although we already have a working VgStack
+ (VG_(interim_stack)) it's better to allocate a new one, so that
+ overflow detection works uniformly for all threads.
+*/
void VG_(main_thread_wrapper_NORETURN)(ThreadId tid)
{
VG_(debugLog)(1, "syswrap-ppc32-linux",=20
"entering VG_(main_thread_wrapper_NORETURN)\n");
=20
- UWord* sp =3D allocstack(tid);
+ Addr sp =3D allocstack(tid);
=20
/* make a stack frame */
sp -=3D 16;
+ sp &=3D ~0xF;
*(UWord *)sp =3D 0;
=20
+ /* If we can't even allocate the first thread's stack, we're hosed.
+ Give up. */
+ vg_assert2(sp !=3D 0, "Cannot allocate main thread's stack.");
+
/* shouldn't be any other threads around yet */
vg_assert( VG_(count_living_threads)() =3D=3D 1 );
=20
@@ -426,7 +408,7 @@
ThreadState* ctst =3D VG_(get_ThreadState)(ctid);
ULong word64;
UWord* stack;
- Segment* seg;
+ NSegment* seg;
SysRes res;
vki_sigset_t blockall, savedmask;
=20
@@ -435,7 +417,7 @@
vg_assert(VG_(is_running_thread)(ptid));
vg_assert(VG_(is_valid_tid)(ctid));
=20
- stack =3D allocstack(ctid);
+ stack =3D (UWord*)allocstack(ctid);
if (stack =3D=3D NULL) {
res =3D VG_(mk_SysRes_Error)( VKI_ENOMEM );
goto out;
@@ -486,14 +468,14 @@
memory mappings and try to derive some useful information. We
assume that esp starts near its highest possible value, and can
only go down to the start of the mmaped segment. */
- seg =3D VG_(find_segment)(sp);
- if (seg) {
+ seg =3D VG_(am_find_nsegment)(sp);
+ if (seg && seg->kind !=3D SkResvn) {
ctst->client_stack_highest_word =3D (Addr)VG_PGROUNDUP(sp);
- ctst->client_stack_szB =3D ctst->client_stack_highest_word - seg-=
>addr;
+ ctst->client_stack_szB =3D ctst->client_stack_highest_word - seg->=
start;
=20
if (debug)
VG_(printf)("\ntid %d: guessed client stack range %p-%p\n",
- ctid, seg->addr, VG_PGROUNDUP(sp));
+ ctid, seg->start, VG_PGROUNDUP(sp));
} else {
VG_(message)(Vg_UserMsg, "!? New thread %d starts with R1(%p) unma=
pped\n",
ctid, sp);
@@ -526,6 +508,7 @@
=20
VG_(sigprocmask)(VKI_SIG_SETMASK, &savedmask, NULL);
=20
+ out:
if (res.isError) {
/* clone failed */
VG_(cleanup_thread)(&ctst->arch);
@@ -583,330 +566,6 @@
=20
=20
/* ---------------------------------------------------------------------
- LDT/GDT simulation
- ------------------------------------------------------------------ */
-#warning "Do we need all this LDT/GDT garbage on ppc32? Surely not."
-
-/* 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, us=
ing
-//.. the Linux kernel's logic (cut-n-paste of code in
-//.. linux/kernel/ldt.c). */
-//..=20
-//.. 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));
-//..=20
-//.. if (0)
-//.. VG_(printf)("translate_to_hw_format: base %p, limit %d\n",=20
-//.. inn->base_addr, inn->limit );
-//..=20
-//.. /* 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;
-//.. }
-//.. }
-//..=20
-//.. 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);
-//..=20
-//.. /* Install the new entry ... */
-//.. install:
-//.. out->LdtEnt.Words.word1 =3D entry_1;
-//.. out->LdtEnt.Words.word2 =3D entry_2;
-//.. }
-//..=20
-//..=20
-//.. /*
-//.. * linux/kernel/ldt.c
-//.. *
-//.. * Copyright (C) 1992 Krishna Balasubramanian and Linus Torvalds
-//.. * Copyright (C) 1999 Ingo Molnar <mi...@re...>
-//.. */
-//..=20
-//.. /*
-//.. * 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;
-//..=20
-//.. if (0)
-//.. VG_(printf)("read_ldt: tid =3D %d, ptr =3D %p, bytecount =3D =
%d\n",
-//.. tid, ptr, bytecount );
-//..=20
-//.. vg_assert(sizeof(HWord) =3D=3D sizeof(VexGuestX86SegDescr*));
-//.. vg_assert(8 =3D=3D sizeof(VexGuestX86SegDescr));
-//..=20
-//.. 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;
-//..=20
-//.. size =3D VEX_GUEST_X86_LDT_NENT * sizeof(VexGuestX86SegDescr);
-//.. if (size > bytecount)
-//.. size =3D bytecount;
-//..=20
-//.. err =3D size;
-//.. for (i =3D 0; i < size; i++)
-//.. ptr[i] =3D ldt[i];
-//..=20
-//.. out:
-//.. return err;
-//.. }
-//..=20
-//..=20
-//.. static
-//.. Int write_ldt ( ThreadId tid, void* ptr, UInt bytecount, Int oldmod=
e )
-//.. {
-//.. Int error;
-//.. VexGuestX86SegDescr* ldt;
-//.. vki_modify_ldt_t* ldt_info;=20
-//..=20
-//.. if (0)
-//.. VG_(printf)("write_ldt: tid =3D %d, ptr =3D %p, "
-//.. "bytecount =3D %d, oldmode =3D %d\n",
-//.. tid, ptr, bytecount, oldmode );
-//..=20
-//.. vg_assert(8 =3D=3D sizeof(VexGuestX86SegDescr));
-//.. vg_assert(sizeof(HWord) =3D=3D sizeof(VexGuestX86SegDescr*));
-//..=20
-//.. ldt =3D (VexGuestX86SegDescr*)VG_(threads)[tid].arch.vex.gu=
est_LDT;
-//.. ldt_info =3D (vki_modify_ldt_t*)ptr;
-//..=20
-//.. error =3D -VKI_EINVAL;
-//.. if (bytecount !=3D sizeof(vki_modify_ldt_t))
-//.. goto out;
-//..=20
-//.. 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;
-//.. }
-//..=20
-//.. /* If this thread doesn't have an LDT, we'd better allocate it
-//.. now. */
-//.. if (ldt =3D=3D (HWord)NULL) {
-//.. ldt =3D VG_(alloc_zeroed_x86_LDT)();
-//.. VG_(threads)[tid].arch.vex.guest_LDT =3D (HWord)ldt;
-//.. }
-//..=20
-//.. /* Install the new entry ... */
-//.. translate_to_hw_format ( ldt_info, &ldt[ldt_info->entry_number],=
oldmode );
-//.. error =3D 0;
-//..=20
-//.. out:
-//.. return error;
-//.. }
-//..=20
-//..=20
-//.. Int VG_(sys_modify_ldt) ( ThreadId tid,
-//.. Int func, void* ptr, UInt bytecount )
-//.. {
-//.. Int ret =3D -VKI_ENOSYS;
-//..=20
-//.. 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;
-//.. }
-//..=20
-//..=20
-//.. Int VG_(sys_set_thread_area) ( ThreadId tid,
-//.. vki_modify_ldt_t* info )
-//.. {
-//.. Int idx;
-//.. VexGuestX86SegDescr* gdt;
-//..=20
-//.. vg_assert(8 =3D=3D sizeof(VexGuestX86SegDescr));
-//.. vg_assert(sizeof(HWord) =3D=3D sizeof(VexGuestX86SegDescr*));
-//..=20
-//.. if (info =3D=3D NULL)
-//.. return -VKI_EFAULT;
-//..=20
-//.. gdt =3D (VexGuestX86SegDescr*)VG_(threads)[tid].arch.vex.guest_G=
DT;
-//..=20
-//.. /* If the thread doesn't have a GDT, allocate it now. */
-//.. if (!gdt) {
-//.. gdt =3D VG_(alloc_zeroed_x86_GDT)();
-//.. VG_(threads)[tid].arch.vex.guest_GDT =3D (HWord)gdt;
-//.. }
-//..=20
-//.. idx =3D info->entry_number;
-//..=20
-//.. 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;
-//.. }
-//..=20
-//.. 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;
-//.. }
-//..=20
-//.. translate_to_hw_format(info, &gdt[idx], 0);
-//..=20
-//.. 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) );
-//..=20
-//.. return 0;
-//.. }
-//..=20
-//..=20
-//.. Int VG_(sys_get_thread_area) ( ThreadId tid,
-//.. vki_modify_ldt_t* info )
-//.. {
-//.. Int idx;
-//.. VexGuestX86SegDescr* gdt;
-//..=20
-//.. vg_assert(sizeof(HWord) =3D=3D sizeof(VexGuestX86SegDescr*));
-//.. vg_assert(8 =3D=3D sizeof(VexGuestX86SegDescr));
-//..=20
-//.. if (info =3D=3D NULL)
-//.. return -VKI_EFAULT;
-//..=20
-//.. idx =3D info->entry_number;
-//..=20
-//.. if (idx < 0 || idx >=3D VEX_GUEST_X86_GDT_NENT)
-//.. return -VKI_EINVAL;
-//..=20
-//.. gdt =3D (VexGuestX86SegDescr*)VG_(threads)[tid].arch.vex.guest_G=
DT;
-//..=20
-//.. /* If the thread doesn't have a GDT, allocate it now. */
-//.. if (!gdt) {
-//.. gdt =3D VG_(alloc_zeroed_x86_GDT)();
-//.. VG_(threads)[tid].arch.vex.guest_GDT =3D (HWord)gdt;
-//.. }
-//..=20
-//.. 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 ) ^ 0=
x1;
-//.. 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;
-//..=20
-//.. return 0;
-//.. }
-
-
-
-/* ---------------------------------------------------------------------
More thread stuff
------------------------------------------------------------------ */
=20
@@ -1451,14 +1110,16 @@
=20
if (ARG1 & VKI_CLONE_PARENT_SETTID) {
PRE_MEM_WRITE("clone(parent_tidptr)", ARG3, sizeof(Int));
- if (!VG_(is_addressable)(ARG3, sizeof(Int), VKI_PROT_WRITE)) {
+ if (!VG_(am_is_valid_for_client)(ARG3, sizeof(Int),=20
+ VKI_PROT_WRITE)) {
SET_STATUS_Failure( VKI_EFAULT );
return;
}
}
if (ARG1 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID)) {
PRE_MEM_WRITE("clone(child_tidptr)", ARG5, sizeof(Int));
- if (!VG_(is_addressable)(ARG5, sizeof(Int), VKI_PROT_WRITE)) {
+ if (!VG_(am_is_valid_for_client)(ARG5, sizeof(Int),=20
+ VKI_PROT_WRITE)) {
SET_STATUS_Failure( VKI_EFAULT );
return;
}
@@ -2068,11 +1729,7 @@
//.. // (__NR_reboot, sys_reboot), // 88 */Li=
nux
//.. // (__NR_readdir, old_readdir), // 89 -- s=
uperseded
=20
-<<<<<<< .working
- LINXY(__NR_mmap, sys_mmap2), // 90
-=3D=3D=3D=3D=3D=3D=3D
- GENX_(__NR_mmap, sys_mmap2), // 90
->>>>>>> .merge-right.r4787
+ LINX_(__NR_mmap, sys_mmap2), // 90
GENXY(__NR_munmap, sys_munmap), // 91
//.. GENX_(__NR_truncate, sys_truncate), // 92
GENX_(__NR_ftruncate, sys_ftruncate), // 93
@@ -2198,11 +1855,7 @@
GENX_(__NR_vfork, sys_fork), // 189
GENXY(__NR_ugetrlimit, sys_getrlimit), // 190
//__NR_readahead // 191 ppc/Linux only?
-<<<<<<< .working
- LINXY(__NR_mmap2, sys_mmap2), // 192
-=3D=3D=3D=3D=3D=3D=3D
- GENX_(__NR_mmap2, sys_mmap2), // 192
->>>>>>> .merge-right.r4787
+ LINX_(__NR_mmap2, sys_mmap2), // 192
//.. GENX_(__NR_truncate64, sys_truncate64), // 193
//.. GENX_(__NR_ftruncate64, sys_ftruncate64), // 194
//.. =20
Modified: trunk/coregrind/m_trampoline.S
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=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_trampoline.S 2005-09-29 10:24:17 UTC (rev 4818)
+++ trunk/coregrind/m_trampoline.S 2005-09-29 11:09:56 UTC (rev 4819)
@@ -36,6 +36,9 @@
Replacements for some functions to do with vsyscalls and signals.
This code runs on the simulated CPU.
*/
+=09
+/*---------------------- x86-linux ----------------------*/
+#if defined(VGP_x86_linux)
=20
# define UD2_16 ud2 ; ud2 ; ud2 ; ud2 ;ud2 ; ud2 ; ud2 ; ud2
# define UD2_64 UD2_16 ; UD2_16 ; UD2_16 ; UD2_16
@@ -45,9 +48,6 @@
=20
/* a leading page of unexecutable code */
UD2_PAGE
-=09
-/*---------------- x86-linux ----------------*/
-#if defined(VGP_x86_linux)
=20
.global VG_(trampoline_stuff_start)
VG_(trampoline_stuff_start):
@@ -77,11 +77,28 @@
.global VG_(trampoline_stuff_end)
VG_(trampoline_stuff_end):
=20
+ /* and a trailing page of unexecutable code */
+ UD2_PAGE
+
+# undef UD2_16
+# undef UD2_64
+# undef UD2_256
+# undef UD2_1024
+# undef UD2_PAGE
=09
-/*---------------- amd64-linux ----------------*/
+/*---------------------- amd64-linux ----------------------*/
#else
#if defined(VGP_amd64_linux)
=20
+# define UD2_16 ud2 ; ud2 ; ud2 ; ud2 ;ud2 ; ud2 ; ud2 ; ud2
+# define UD2_64 UD2_16 ; UD2_16 ; UD2_16 ; UD2_16
+# define UD2_256 UD2_64 ; UD2_64 ; UD2_64 ; UD2_64
+# define UD2_1024 UD2_256 ; UD2_256 ; UD2_256 ; UD2_256
+# define UD2_PAGE UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024 =20
+
+ /* a leading page of unexecutable code */
+ UD2_PAGE
+
.global VG_(trampoline_stuff_start)
VG_(trampoline_stuff_start):
=20
@@ -108,11 +125,28 @@
.global VG_(trampoline_stuff_end)
VG_(trampoline_stuff_end):
=20
+ /* and a trailing page of unexecutable code */
+ UD2_PAGE
=20
+# undef UD2_16
+# undef UD2_64
+# undef UD2_256
+# undef UD2_1024
+# undef UD2_PAGE
+
/*---------------- ppc32-linux ----------------*/
#else
#if defined(VGP_ppc32_linux)
=20
+# define UD2_16 trap ; trap ; trap; trap
+# define UD2_64 UD2_16 ; UD2_16 ; UD2_16 ; UD2_16
+# define UD2_256 UD2_64 ; UD2_64 ; UD2_64 ; UD2_64
+# define UD2_1024 UD2_256 ; UD2_256 ; UD2_256 ; UD2_256
+# define UD2_PAGE UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024 =20
+
+ /* a leading page of unexecutable code */
+ UD2_PAGE
+
.global VG_(trampoline_stuff_start)
VG_(trampoline_stuff_start):
=20
@@ -138,6 +172,11 @@
.global VG_(trampoline_stuff_end)
VG_(trampoline_stuff_end):
=20
+# undef UD2_16
+# undef UD2_64
+# undef UD2_256
+# undef UD2_1024
+# undef UD2_PAGE
=20
/*---------------- unknown ----------------*/
#else
@@ -147,16 +186,7 @@
#endif
#endif
=20
- /* and a trailing page of unexecutable code */
- UD2_PAGE
=20
-# undef UD2_16
-# undef UD2_64
-# undef UD2_256
-# undef UD2_1024
-# undef UD2_PAGE
-
-
/* Let the linker know we don't need an executable stack */
.section .note.GNU-stack,"",@progbits
=09
Modified: trunk/coregrind/m_translate.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_translate.c 2005-09-29 10:24:17 UTC (rev 4818)
+++ trunk/coregrind/m_translate.c 2005-09-29 11:09:56 UTC (rev 4819)
@@ -115,8 +115,8 @@
=20
#elif defined(VGA_ppc32)
*vex_arch =3D VexArchPPC32;
- vai->subarch =3D VG_(have_altivec_ppc) ? VexSubArchPPC32_AV
- : VexSubArchPPC32_noAV;
+ vai->subarch =3D VG_(have_altivec_ppc32) ? VexSubArchPPC32_AV
+ : VexSubArchPPC32_noAV;
vai->ppc32_cache_line_szB =3D VG_(cache_line_size_ppc32);
return True;
=20
Modified: trunk/coregrind/pub_core_machine.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_machine.h 2005-09-29 10:24:17 UTC (rev 4818)
+++ trunk/coregrind/pub_core_machine.h 2005-09-29 11:09:56 UTC (rev 4819)
@@ -84,7 +84,7 @@
// entries.
extern Int VG_(cache_line_size_ppc32);
// Altivec enabled? Harvested on startup from the AT_HWCAP entry
-extern Int VG_(have_altivec_ppc);
+extern Int VG_(have_altivec_ppc32);
#endif
=20
// X86: set to 1 if the host is able to do {ld,st}mxcsr (load/store
Modified: trunk/coregrind/vki_unistd-ppc32-linux.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/vki_unistd-ppc32-linux.h 2005-09-29 10:24:17 UTC (rev=
4818)
+++ trunk/coregrind/vki_unistd-ppc32-linux.h 2005-09-29 11:09:56 UTC (rev=
4819)
@@ -55,7 +55,7 @@
#define __NR_setuid 23
#define __NR_getuid 24
//#define __NR_stime 25
-//#define __NR_ptrace 26
+#define __NR_ptrace 26
#define __NR_alarm 27
//#define __NR_oldfstat 28
#define __NR_pause 29
|