|
From: Jeremy F. <je...@go...> - 2003-12-22 10:43:31
|
CVS commit by fitzhardinge:
Fix nasty use after free bug revealed by last munmap fix.
Unexport split_segment; it isn't needed elsewhere.
(Something still wrong with munmap.)
M +0 -1 vg_include.h 1.163
M +18 -11 vg_memory.c 1.47
M +1 -2 vg_symtab2.c 1.70
--- valgrind/coregrind/vg_include.h #1.162:1.163
@@ -1581,5 +1581,4 @@ extern Addr VG_(find_map_space)(Addr bas
extern Segment *VG_(find_segment)(Addr a);
extern Segment *VG_(next_segment)(Segment *);
-extern Segment *VG_(split_segment)(Addr a);
extern Bool VG_(seg_contains)(const Segment *s, Addr ptr, UInt size);
--- valgrind/coregrind/vg_memory.c #1.46:1.47
@@ -143,4 +143,7 @@ Segment *VG_(split_segment)(Addr a)
ns->len -= delta;
+ if (s->filename != NULL)
+ ns->filename = VG_(arena_strdup)(VG_AR_CORE, s->filename);
+
if (ns->symtab != NULL)
VG_(symtab_incref)(ns->symtab);
@@ -157,15 +160,17 @@ void VG_(unmap_range)(Addr addr, UInt le
Segment *s;
Segment *next;
- static const Bool debug = False || mem_debug;
- Addr end = addr+len;
+ static const Bool debug = True || mem_debug;
+ Addr end;
if (len == 0)
return;
+ len = PGROUNDUP(len);
+ vg_assert(addr == PGROUNDDN(addr));
+
if (debug)
VG_(printf)("unmap_range(%p, %d)\n", addr, len);
- len = PGROUNDUP(addr+len)-PGROUNDDN(addr);
- addr = PGROUNDDN(addr);
+ end = addr+len;
/* Everything must be page-aligned */
@@ -183,5 +188,5 @@ void VG_(unmap_range)(Addr addr, UInt le
if (debug)
VG_(printf)("unmap: addr=%p-%p s=%p ->addr=%p-%p len=%d\n",
- addr, addr+len, s, s->addr, s->addr+s->len, s->len);
+ addr, end, s, s->addr, seg_end, s->len);
if (!VG_(seg_overlaps)(s, addr, len)) {
@@ -218,10 +223,12 @@ void VG_(unmap_range)(Addr addr, UInt le
Int delta = (addr+len) - s->addr;
+ if (debug)
+ VG_(printf)(" case 3: s->addr=%p s->len=%d delta=%d\n", s->addr, s->len, delta);
+
s->addr += delta;
s->offset += delta;
s->len -= delta;
- if (debug)
- VG_(printf)(" case 3: s->addr=%p s->len=%d delta=%d\n", s->addr, s->len, delta);
+ vg_assert(s->len != 0);
} else if (addr > s->addr && end < seg_end) {
/* [addr, addr+len) is contained within a single segment
@@ -246,6 +253,6 @@ void VG_(unmap_range)(Addr addr, UInt le
}
-/* If possible, merge segment with its neighbours - some segments,
- including s, may be destroyed in the process */
+/* Return true if two segments are adjacent and mergable (s1 is
+ assumed to have a lower ->addr than s2) */
static inline Bool neighbours(Segment *s1, Segment *s2)
{
@@ -274,6 +281,6 @@ static inline Bool neighbours(Segment *s
}
-/* Merge segments in the address range if they're adjacent and
- compatible */
+/* If possible, merge segment with its neighbours - some segments,
+ including s, may be destroyed in the process */
static void merge_segments(Addr a, UInt len)
{
--- valgrind/coregrind/vg_symtab2.c #1.69:1.70
@@ -1209,6 +1209,5 @@ SegInfo *VG_(read_seg_symbols) ( Segment
si->size = seg->len;
si->foffset = seg->offset;
- si->filename = VG_(arena_malloc)(VG_AR_SYMTAB, 1 + VG_(strlen)(seg->filename));
- VG_(strcpy)(si->filename, seg->filename);
+ si->filename = VG_(arena_strdup)(VG_AR_SYMTAB, seg->filename);
si->ref = 1;
|
|
From: Tom H. <th...@cy...> - 2003-12-22 10:46:55
|
In message <200...@of...>
Jeremy Fitzhardinge <je...@go...> wrote:
> Fix nasty use after free bug revealed by last munmap fix.
> Unexport split_segment; it isn't needed elsewhere.
> (Something still wrong with munmap.)
I'd just found that and was about to report it ;-)
> - static const Bool debug = False || mem_debug;
> - Addr end = addr+len;
> + static const Bool debug = True || mem_debug;
> + Addr end;
Did you actually mean to commit that?
Tom
--
Tom Hughes (th...@cy...)
Software Engineer, Cyberscience Corporation
http://www.cyberscience.com/
|
|
From: Julian S. <js...@ac...> - 2003-12-22 22:54:10
|
CVS commit by jseward:
De-anonymise a union so as to un-break compilation on gcc-2.95.
M +11 -11 vg_proxylwp.c 1.10
--- valgrind/coregrind/vg_proxylwp.c #1.9:1.10
@@ -197,5 +197,5 @@ struct PX_Reply {
Int syscallno; /* system call completed */
vki_ksiginfo_t siginfo; /* signal */
- };
+ } u;
};
@@ -512,5 +512,5 @@ static Int proxylwp(void *v)
sigreply.tid = px->tid;
sigreply.req = PX_Signal;
- sigreply.siginfo = px->siginfo;
+ sigreply.u.siginfo = px->siginfo;
if (!send_reply(&sigreply)) {
@@ -554,5 +554,5 @@ static Int proxylwp(void *v)
non-restartable syscalls? Does it matter?
*/
- reply.syscallno = tst->syscallno;
+ reply.u.syscallno = tst->syscallno;
tst->m_eax = -VKI_ERESTARTSYS;
@@ -599,5 +599,5 @@ static Int proxylwp(void *v)
reply should already be set up, including return in eax. */
vg_assert(reply.req == PX_RunSyscall);
- vg_assert(reply.syscallno == tst->syscallno);
+ vg_assert(reply.u.syscallno == tst->syscallno);
vg_assert(tst->status == VgTs_WaitSys);
px->state = PXS_IntReply;
@@ -608,5 +608,5 @@ static Int proxylwp(void *v)
back. */
vg_assert(reply.req == PX_RunSyscall);
- vg_assert(reply.syscallno == tst->syscallno);
+ vg_assert(reply.u.syscallno == tst->syscallno);
px->state = PXS_IntReply;
break;
@@ -712,5 +712,5 @@ static Int proxylwp(void *v)
/* Run a syscall for our thread; results will be poked
back into tst */
- reply.syscallno = tst->syscallno;
+ reply.u.syscallno = tst->syscallno;
vg_assert(px->state == PXS_WaitReq ||
@@ -723,5 +723,5 @@ static Int proxylwp(void *v)
*/
px_printf("RunSyscall in SigACK: rejecting syscall %d with ERESTARTSYS\n",
- reply.syscallno);
+ reply.u.syscallno);
tst->m_eax = -VKI_ERESTARTSYS;
} else {
@@ -1151,5 +1151,5 @@ static void sys_wait_results(Bool block,
tst->tid, tst->status);
- vg_assert(res.syscallno == tst->syscallno);
+ vg_assert(res.u.syscallno == tst->syscallno);
vg_assert(tst->status == VgTs_WaitSys);
@@ -1160,10 +1160,10 @@ static void sys_wait_results(Bool block,
if (VG_(clo_trace_signals) || VG_(clo_trace_syscalls))
VG_(message)(Vg_DebugMsg, "sys_wait_results: got PX_Signal for TID %d, signal %d",
- res.tid, res.siginfo.si_signo);
+ res.tid, res.u.siginfo.si_signo);
- vg_assert(res.siginfo.si_signo != 0);
+ vg_assert(res.u.siginfo.si_signo != 0);
if (VG_(threads)[res.tid].proxy &&
!VG_(threads)[res.tid].proxy->terminating)
- VG_(deliver_signal)(res.tid, &res.siginfo, True);
+ VG_(deliver_signal)(res.tid, &res.u.siginfo, True);
break;
|
|
From: Robert W. <rj...@ke...> - 2003-12-18 01:48:37
|
CVS commit by rjwalsh:
Ignore internal Valgrind file descriptors.
M +3 -0 vg_syscalls.c 1.69
--- valgrind/coregrind/vg_syscalls.c #1.68:1.69
@@ -312,4 +312,7 @@ void record_fd_close(Int tid, Int fd)
OpenFd *i = allocated_fds;
+ if (fd > VG_MAX_FD)
+ return; /* Valgrind internal */
+
while(i) {
if(i->fd == fd) {
|
|
From: Jeremy F. <je...@go...> - 2003-12-24 10:11:44
|
CVS commit by fitzhardinge:
Statically allocate a page in the client address space for trampoline
code. Currently this is just for signal returns, but there's the start
of sysinfo/vsyscalls support, as used by the TLS libraries.
M +17 -10 stage2.c 1.3
M +4 -1 ume.c 1.3
M +22 -6 vg_helpers.S 1.26
M +12 -5 vg_include.h 1.164
M +4 -1 vg_main.c 1.133
M +7 -11 vg_memory.c 1.49
M +1 -23 vg_signals.c 1.54
--- valgrind/coregrind/stage2.c #1.2:1.3
@@ -132,4 +132,6 @@ static char *copy_str(char **tab, const
higher address +-----------------+
+ | Trampoline code |
+ +-----------------+
| |
: string table :
@@ -169,4 +171,5 @@ static Addr setup_client_stack(char **or
unsigned stacksize; /* total client stack size */
addr_t cl_esp; /* client stack base (initial esp) */
+ addr_t cl_stacktop; /* top of stack */
/* ==================== compute sizes ==================== */
@@ -216,5 +219,6 @@ static Addr setup_client_stack(char **or
sizeof(char **) + /* terminal NULL */
auxsize + /* auxv */
- ROUNDUP(stringsize, sizeof(int)); /* strings (aligned) */
+ ROUNDUP(stringsize, sizeof(int)) +/* strings (aligned) */
+ VKI_BYTES_PER_PAGE; /* page for trampoline code */
/* cl_esp is the client's stack pointer */
@@ -222,4 +226,9 @@ static Addr setup_client_stack(char **or
cl_esp = ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
+ cl_stacktop = client_end;
+ cl_stacktop -= VKI_BYTES_PER_PAGE;
+
+ kp.cl_tramp_code = cl_stacktop;
+
if (0)
printf("stringsize=%d auxsize=%d stacksize=%d\n",
@@ -226,6 +235,7 @@ static Addr setup_client_stack(char **or
stringsize, auxsize, stacksize);
+
/* base of the string table (aligned) */
- stringbase = strtab = (char *)(client_end - ROUNDUP(stringsize, sizeof(int)));
+ stringbase = strtab = (char *)(cl_stacktop - ROUNDUP(stringsize, sizeof(int)));
kp.clstk_base = PGROUNDDN(cl_esp);
@@ -337,16 +347,13 @@ static Addr setup_client_stack(char **or
break;
-#if 1
case AT_SYSINFO:
- case AT_SYSINFO_EHDR:
- /* trash vsyscalls for now
+ /* Leave this unmolested for now, but we'll update it later
+ when we set up the client trapoline code page */
+ break;
- XXX should probably replace with our own sysinfo page so
- we can intercept sysenter syscalls too - or at least note
- the address so that we can catch jumps here
- */
+ case AT_SYSINFO_EHDR:
+ /* Trash this, because we don't reproduce it */
auxv->a_type = AT_IGNORE;
break;
-#endif
default:
--- valgrind/coregrind/ume.c #1.2:1.3
@@ -323,5 +323,5 @@ ESZ(Addr) mapelf(struct elfinfo *e, ESZ(
fprintf(stderr, "sbrk failed while adjusting brk base: "
"perhaps we hit the datasize ulimit?\n");
- break;
+ return 0;
}
b += delta;
@@ -483,4 +483,7 @@ static int load_ELF(char *hdr, int len,
info->brkbase = mapelf(e, 0, info->setbrk); /* map the executable */
+ if (info->brkbase == 0)
+ return ENOMEM;
+
if (interp != NULL) {
/* reserve a chunk of address space for interpreter */
--- valgrind/coregrind/vg_helpers.S #1.25:1.26
@@ -43,7 +43,11 @@
position-independent.
*/
-.global VG_(signalreturn_bogusRA)
-.global VG_(signalreturn_bogusRA_length)
-VG_(signalreturn_bogusRA):
+.global VG_(trampoline_code_start)
+.global VG_(trampoline_code_length)
+.global VG_(tramp_sigreturn_offset)
+.global VG_(tramp_syscall_offset)
+
+VG_(trampoline_code_start):
+sigreturn_start:
subl $20, %esp # allocate arg block
movl %esp, %edx # %edx == &_zzq_args[0]
@@ -64,7 +68,19 @@
ud2
-VG_(signalreturn_bogusRA_length):
- .long . - VG_(signalreturn_bogusRA)
-
+ # We can point our sysinfo stuff here
+ .align 16
+syscall_start:
+ int $0x80
+ ret
+tramp_code_end:
+
+.data
+VG_(trampoline_code_length):
+ .long tramp_code_end - VG_(trampoline_code_start)
+VG_(tramp_sigreturn_offset):
+ .long sigreturn_start - VG_(trampoline_code_start)
+VG_(tramp_syscall_offset):
+ .long syscall_start - VG_(trampoline_code_start)
+.text
--- valgrind/coregrind/vg_include.h #1.163:1.164
@@ -1342,4 +1342,8 @@ typedef struct {
Addr client_end; /* end of client address space */
Addr client_mapbase; /* base address of !MAP_FIXED mappings */
+ Addr clstk_base; /* lowest address of client stack */
+ Addr clstk_end; /* highest address of client stack */
+ Addr cl_tramp_code; /* syscall+signal trampoline code */
+
Addr shadow_base; /* start of skin's shadow memory */
Addr shadow_end; /* end of skin's shadow memory */
@@ -1347,6 +1352,4 @@ typedef struct {
Addr vg_mmap_end; /* end of Valgrind's mmap area */
Addr vg_end; /* end of Valgrind's memory */
- Addr clstk_base; /* lowest address of client stack */
- Addr clstk_end; /* highest address of client stack */
} KickstartParams;
@@ -1377,4 +1380,6 @@ extern Addr VG_(client_mapbase); /* base
extern Addr VG_(clstk_base); /* client stack range */
extern Addr VG_(clstk_end);
+extern Addr VG_(client_trampoline_code);
+
extern Addr VG_(brk_base); /* start of brk */
extern Addr VG_(brk_limit); /* current brk */
@@ -1743,7 +1748,9 @@ extern void VG_(helper_DAA);
extern void VG_(helper_undefined_instruction);
-/* NOT A FUNCTION; this is a bogus RETURN ADDRESS. */
-extern Char VG_(signalreturn_bogusRA);
-extern Int VG_(signalreturn_bogusRA_length); /* length */
+/* Information about trampoline code (for signal return and syscalls) */
+extern const Char VG_(trampoline_code_start);
+extern const Int VG_(trampoline_code_length);
+extern const Int VG_(tramp_sigreturn_offset);
+extern const Int VG_(tramp_syscall_offset);
/* ---------------------------------------------------------------------
--- valgrind/coregrind/vg_main.c #1.132:1.133
@@ -125,4 +125,5 @@ Addr VG_(client_base); /* client address
Addr VG_(client_end);
Addr VG_(client_mapbase);
+Addr VG_(client_trampoline_code);
Addr VG_(clstk_base);
Addr VG_(clstk_end);
@@ -778,4 +779,5 @@ static void process_cmd_line_options ( c
case VKI_AT_SYSINFO:
VG_(sysinfo_page_exists) = True;
+ auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
VG_(sysinfo_page_addr) = auxp[1];
break;
@@ -1393,4 +1395,5 @@ void VG_(main) ( const KickstartParams *
VG_(clstk_base) = kp->clstk_base;
VG_(clstk_end) = kp->clstk_end;
+ vg_assert(VG_(clstk_end) == VG_(client_end));
VG_(shadow_base) = kp->shadow_base;
@@ -1402,5 +1405,5 @@ void VG_(main) ( const KickstartParams *
VG_(libdir) = kp->libdir;
- vg_assert(VG_(clstk_end) == VG_(client_end));
+ VG_(client_trampoline_code) = kp->cl_tramp_code;
if (0) {
--- valgrind/coregrind/vg_memory.c #1.48:1.49
@@ -469,5 +469,5 @@ void VG_(mprotect_range)(Addr a, UInt le
/* Everything must be page-aligned */
vg_assert((a & (VKI_BYTES_PER_PAGE-1)) == 0);
- vg_assert((len & (VKI_BYTES_PER_PAGE-1)) == 0);
+ len = PGROUNDUP(len);
VG_(split_segment)(a);
@@ -662,14 +662,10 @@ void VG_(init_memory) ( void )
VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
- /* kludge: some newer kernels place a "sysinfo" page up high, with
- vsyscalls in it, and possibly some other stuff in the future. */
- if (VG_(sysinfo_page_exists)) {
- // 2003-Sep-25, njn: Jeremy thinks the sysinfo page probably doesn't
- // have any symbols that need to be loaded. So just treat it like
- // a non-executable page.
- //VG_(new_exeseg_mmap)( VG_(sysinfo_page_addr), 4096 );
- VG_TRACK( new_mem_startup, VG_(sysinfo_page_addr), 4096,
- True, True, True );
- }
+ /* initialize our trampoline page (which is also sysinfo stuff) */
+ VG_(memcpy)((void *)VG_(client_trampoline_code),
+ &VG_(trampoline_code_start),
+ VG_(trampoline_code_length));
+ VG_(mprotect)((void *)VG_(client_trampoline_code), VG_(trampoline_code_length),
+ VKI_PROT_READ|VKI_PROT_EXEC);
}
--- valgrind/coregrind/vg_signals.c #1.53:1.54
@@ -951,6 +951,4 @@ static void synth_ucontext(ThreadId tid,
}
-static Addr signalreturn_stub_addr = 0;
-
/* Set up a stack frame (VgSigContext) for the client's signal
handler. This includes the signal number and a bogus return
@@ -1010,28 +1008,8 @@ void vg_push_signal_frame ( ThreadId tid
== ((Char*)(esp_top_of_frame)) );
- /* if the sigreturn stub isn't in the client address space yet,
- allocate space for it and copy it into place. */
- if (signalreturn_stub_addr == 0) {
- UInt len = PGROUNDUP(VG_(signalreturn_bogusRA_length));
-
- signalreturn_stub_addr = VG_(client_alloc)(0, len,
- VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC,
- 0);
- VG_(memcpy)((void *)signalreturn_stub_addr, &VG_(signalreturn_bogusRA),
- VG_(signalreturn_bogusRA_length));
- VG_(mprotect)((void *)signalreturn_stub_addr, len, VKI_PROT_READ|VKI_PROT_EXEC);
- VG_TRACK(new_mem_mmap, signalreturn_stub_addr, VG_(signalreturn_bogusRA_length),
- True, False, True);
-
- if (VG_(clo_trace_signals))
- VG_(message)(Vg_DebugMsg, "Put sigreturn stub at %p-%p in client address space",
- signalreturn_stub_addr,
- signalreturn_stub_addr + VG_(signalreturn_bogusRA_length));
- }
-
/* retaddr, sigNo, psigInfo, puContext fields are to be written */
VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal handler frame",
(Addr)frame, offsetof(VgSigFrame, handlerArgs) );
- frame->retaddr = (UInt)signalreturn_stub_addr;
+ frame->retaddr = (UInt)VG_(client_trampoline_code)+VG_(tramp_sigreturn_offset);
frame->sigNo = sigNo;
frame->sigNo_private = sigNo;
|
|
From: Julian S. <js...@ac...> - 2004-01-02 11:39:44
|
CVS commit by jseward:
(David Lee, <dav...@te...>)
This patch fixes a semaphore leak within valgrind. If your application
dynamically allocates/releases semaphores, you will very quickly run out.
Also, as a nice side effect, it implements sem_destroy properly.
(me)
Protect sem_getvalue with a lock/unlock of the semaphore's mutex,
like the other routines do.
M +54 -2 vg_libpthread.c 1.142
--- valgrind/coregrind/vg_libpthread.c #1.141:1.142
@@ -2254,4 +2254,5 @@ typedef
pthread_cond_t se_cv;
int count;
+ int waiters;
}
vg_sem_t;
@@ -2288,4 +2289,27 @@ static vg_sem_t* se_remap ( sem_t* orig
}
+static void se_unmap( sem_t* orig )
+{
+ int res, i;
+ res = __pthread_mutex_lock(&se_remap_mx);
+ my_assert(res == 0);
+
+ for (i = 0; i < se_remap_used; i++) {
+ if (se_remap_orig[i] == orig)
+ break;
+ }
+ if (i == se_remap_used) {
+ res = pthread_mutex_unlock(&se_remap_mx);
+ my_assert(res == 0);
+ barf("se_unmap: unmapping invalid semaphore");
+ } else {
+ se_remap_orig[i] = se_remap_orig[--se_remap_used];
+ se_remap_orig[se_remap_used] = 0;
+ memset(&se_remap_new[se_remap_used], 0,
+ sizeof(se_remap_new[se_remap_used]));
+ }
+ res = pthread_mutex_unlock(&se_remap_mx);
+ my_assert(res == 0);
+}
int sem_init(sem_t *sem, int pshared, unsigned int value)
@@ -2318,5 +2342,7 @@ int sem_wait ( sem_t* sem )
my_assert(res == 0);
while (vg_sem->count == 0) {
+ ++vg_sem->waiters;
res = pthread_cond_wait(&vg_sem->se_cv, &vg_sem->se_mx);
+ --vg_sem->waiters;
my_assert(res == 0);
}
@@ -2371,8 +2397,13 @@ int sem_trywait ( sem_t* sem )
int sem_getvalue(sem_t* sem, int * sval)
{
+ int res;
vg_sem_t* vg_sem;
- ensure_valgrind("sem_trywait");
+ ensure_valgrind("sem_getvalue");
vg_sem = se_remap(sem);
+ res = __pthread_mutex_lock(&vg_sem->se_mx);
+ my_assert(res == 0);
*sval = vg_sem->count;
+ res = __pthread_mutex_unlock(&vg_sem->se_mx);
+ my_assert(res == 0);
return 0;
}
@@ -2381,6 +2412,25 @@ int sem_getvalue(sem_t* sem, int * sval)
int sem_destroy(sem_t * sem)
{
- kludged("sem_destroy", "(it always succeeds, even if semaphore waited on)");
/* if someone waiting on this semaphore, errno = EBUSY, return -1 */
+ vg_sem_t* vg_sem;
+ int res;
+ ensure_valgrind("sem_destroy");
+ vg_sem = se_remap(sem);
+ res = __pthread_mutex_lock(&vg_sem->se_mx);
+ my_assert(res == 0);
+ if (vg_sem->waiters > 0)
+ {
+ *(__errno_location()) = EBUSY;
+ res = __pthread_mutex_unlock(&vg_sem->se_mx);
+ my_assert(res == 0);
+ return -1;
+ }
+ res = pthread_cond_destroy(&vg_sem->se_cv);
+ my_assert(res == 0);
+ res = __pthread_mutex_unlock(&vg_sem->se_mx);
+ my_assert(res == 0);
+ res = pthread_mutex_destroy(&vg_sem->se_mx);
+ my_assert(res == 0);
+ se_unmap(sem);
return 0;
}
@@ -2396,5 +2446,7 @@ int sem_timedwait(sem_t* sem, const stru
my_assert(res == 0);
while ( vg_sem->count == 0 && res != ETIMEDOUT ) {
+ ++vg_sem->waiters;
res = pthread_cond_timedwait(&vg_sem->se_cv, &vg_sem->se_mx, abstime);
+ --vg_sem->waiters;
}
if ( vg_sem->count > 0 ) {
|
|
From: Dirk M. <mu...@kd...> - 2004-01-02 22:50:33
|
CVS commit by mueller:
movntpd/movntps support (patch by Tom Hughes)
CCMAIL: 697...@bu...
M +21 -0 vg_to_ucode.c 1.118
--- valgrind/coregrind/vg_to_ucode.c #1.117:1.118
@@ -4373,4 +4373,25 @@ static Addr disInstr ( UCodeBlock* cb, A
}
+ /* MOVNTPS -- 16-byte store with temporal hint (which we
+ ignore). */
+ if (insn[0] == 0x0F
+ && insn[1] == 0x2B) {
+ eip = dis_SSE2_load_store_or_mov
+ (cb, sorb, eip+2, 16, True /* is_store */, "movntps",
+ insn[0], insn[1] );
+ goto decode_success;
+ }
+
+ /* MOVNTPD -- 16-byte store with temporal hint (which we
+ ignore). */
+ if (sz == 2
+ && insn[0] == 0x0F
+ && insn[1] == 0x2B) {
+ eip = dis_SSE3_load_store_or_mov
+ (cb, sorb, eip+2, 16, True /* is_store */, "movntpd",
+ 0x66, insn[0], insn[1] );
+ goto decode_success;
+ }
+
/* MOVD -- 4-byte move between xmmregs and (ireg or memory). */
if (sz == 2
|
|
From: Dirk M. <mu...@kd...> - 2004-01-02 22:53:04
|
CVS commit by mueller:
add support for mincore syscall, patch by Tom Hughes
CCMAIL: 697...@bu...
M +15 -0 vg_syscalls.c 1.73
--- valgrind/coregrind/vg_syscalls.c #1.72:1.73
@@ -3635,4 +3635,18 @@ POST(munmap)
}
+PRE(mincore)
+{
+ /* int mincore(void *start, size_t length, unsigned char *vec); */
+ MAYBE_PRINTF("mincore ( %p, %d, %p )\n", arg1,arg2,arg3);
+ SYSCALL_TRACK(pre_mem_write, tid, "mincore(vec)",
+ arg3, (arg2 + 4096 - 1) / 4096);
+}
+
+POST(mincore)
+{
+ if (!VG_(is_kerror)(res))
+ VG_TRACK( post_mem_write, arg3, (arg2 + 4096 - 1) / 4096 );
+}
+
PRE(nanosleep)
{
@@ -5021,4 +5035,5 @@ static const struct sys_info sys_info[]
SYSBA(mprotect, False),
SYSBA(munmap, False),
+ SYSBA(mincore, False),
SYSBA(nanosleep, True),
SYSB_(_newselect, True),
|
|
From: Nicholas N. <nj...@ca...> - 2004-01-04 13:14:21
|
CVS commit by nethercote:
Adding "use strict" and "use warnings", for safety. Required some extra
variable declarations.
M +6 -0 gen_toolint.pl 1.3
--- valgrind/coregrind/gen_toolint.pl #1.2:1.3
@@ -24,4 +24,6 @@
# The GNU General Public License is contained in the file COPYING.
+use strict;
+use warnings;
my $output = shift @ARGV;
@@ -30,4 +32,7 @@
my $include;
my $passcomment = 1;
+my $pre;
+my $post;
+my $generate;
my $struct = "VG_(tool_interface)";
@@ -211,4 +216,5 @@
my $buf;
my $lines;
+my $prefix;
while(<STDIN>) {
|
|
From: Julian S. <js...@ac...> - 2004-01-04 22:50:45
|
CVS commit by jseward:
Handle 'B' (volatile) and 'k' (const) qualifiers in stabs. (Tom
Hughes / Manish Singh). Fixes #71791.
M +7 -0 vg_stabs.c 1.4
--- valgrind/coregrind/vg_stabs.c #1.3:1.4
@@ -651,4 +651,11 @@ static SymType *stabtype_parser(SegInfo
}
+ case 'k': /* const */
+ case 'B': { /* volatile */
+ /* 'k' TYPE */
+ type = stabtype_parser(si, NULL, &p);
+ break;
+ }
+
case 'x': { /* reference to undefined type */
/* 'x' ('s' | 'u' | 'e') NAME ':' */
|
|
From: Jeremy F. <je...@go...> - 2004-01-04 23:10:41
|
CVS commit by fitzhardinge:
Fix do_exec's permission checking.
M +19 -10 ume.c 1.6
--- valgrind/coregrind/ume.c #1.5:1.6
@@ -647,16 +647,25 @@ static int do_exec_inner(const char *exe
}
- if (uid == st.st_uid && !(st.st_mode & S_IXUSR))
- return EACCES;
-
- if (gid == st.st_gid && !(st.st_mode & S_IXGRP))
+ if (uid == st.st_uid) {
+ if (!(st.st_mode & S_IXUSR))
return EACCES;
+ } else {
+ int grpmatch = 0;
+ if (gid == st.st_gid)
+ grpmatch = 1;
+ else
for(i = 0; i < ngrp; i++)
- if (groups[i] == st.st_gid && !(st.st_mode & S_IXGRP))
- return EACCES;
+ if (groups[i] == st.st_gid) {
+ grpmatch = 1;
+ break;
+ }
- if (!(st.st_mode & S_IXOTH))
+ if (grpmatch) {
+ if (!(st.st_mode & S_IXGRP))
return EACCES;
+ } else if (!(st.st_mode & S_IXOTH))
+ return EACCES;
+ }
}
|
|
From: Jeremy F. <je...@go...> - 2004-01-04 23:53:29
|
CVS commit by fitzhardinge:
Fix problem with trace-children=yes when using a tool which replaces
malloc. The problem was that LD_PRELOAD was being left set with
our replacement .so files, which meant they were being applied to
stage1/stage2. This caused malloc to fail and a subsequent SIGSEGV.
This change unconditionally removes all of Valgrind's special environment
before each execve, since it will be replaced as needed by the child
Valgrind.
M +7 -3 vg_syscalls.c 1.75
--- valgrind/coregrind/vg_syscalls.c #1.74:1.75
@@ -1768,7 +1768,9 @@ PRE(execve)
VG_(nuke_all_threads_except)( VG_INVALID_THREADID );
- if (!VG_(clo_trace_children)) {
+ {
/* Make the LD_LIBRARY_PATH/LD_PRELOAD disappear so that the
- child doesn't get our libpthread and other stuff */
+ child doesn't get our libpthread and other stuff. This is
+ done unconditionally, since if we are tracing the child,
+ stage1/2 will set up the appropriate client environment. */
Int i;
Char** envp = (Char**)arg3;
@@ -1801,5 +1803,7 @@ PRE(execve)
/* XXX if variable becomes empty, remove it completely? */
}
- } else {
+ }
+
+ if (VG_(clo_trace_children)) {
/* If we're tracing the children, then we need to start it
with our starter+arguments.
|
|
From: Jeremy F. <je...@go...> - 2004-01-06 00:16:00
|
CVS commit by fitzhardinge:
Move logfile fd into safe range.
M +1 -1 vg_main.c 1.136
--- valgrind/coregrind/vg_main.c #1.135:1.136
@@ -1069,5 +1069,5 @@ static void process_cmd_line_options ( c
VKI_S_IRUSR|VKI_S_IWUSR);
if (eventually_logfile_fd >= 0) {
- VG_(clo_logfile_fd) = eventually_logfile_fd;
+ VG_(clo_logfile_fd) = VG_(safe_fd)(eventually_logfile_fd);
break;
} else {
|
|
From: Jeremy F. <je...@go...> - 2004-01-06 00:18:54
|
CVS commit by fitzhardinge:
Make --gdb-attach=yes work properly; rather than trying to attach gdb
to itself, Valgrind forks a child, and uses ptrace to manipulate its
state into what the client state would be at that point, and attaches
gdb to that. In addition to giving gdb clean state to inspect, it
also stops mistakes in gdb (eg, continuing) from killing your target.
It also makes gdb strictly read-only; any state changes made from within
gdb will not be reflected in the running client. Patch from Tom Hughes.
M +2 -15 vg_errcontext.c 1.49
M +2 -10 vg_include.h 1.167
M +87 -21 vg_main.c 1.137
M +1 -2 vg_signals.c 1.56
M +0 -82 vg_startup.S 1.22
--- valgrind/coregrind/vg_errcontext.c #1.48:1.49
@@ -254,19 +254,6 @@ void do_actions_on_error(Error* err, Boo
VG_(is_action_requested)( "Attach to GDB", & VG_(clo_GDB_attach) ))
{
- Addr m_eip, m_esp, m_ebp;
-
- if (VG_(is_running_thread)( err->tid )) {
- m_eip = VG_(baseBlock)[VGOFF_(m_eip)];
- m_esp = VG_(baseBlock)[VGOFF_(m_esp)];
- m_ebp = VG_(baseBlock)[VGOFF_(m_ebp)];
- } else {
- ThreadState* tst = & VG_(threads)[ err->tid ];
- m_eip = tst->m_eip;
- m_esp = tst->m_esp;
- m_ebp = tst->m_ebp;
- }
- VG_(printf)("starting gdb with eip=%p esp=%p ebp=%p\n",
- m_eip, m_esp, m_ebp);
- VG_(swizzle_esp_then_start_GDB)( m_eip, m_esp, m_ebp );
+ VG_(printf)("starting gdb\n");
+ VG_(start_GDB)( err->tid );
}
/* Or maybe we want to generate the error's suppression? */
--- valgrind/coregrind/vg_include.h #1.166:1.167
@@ -1451,9 +1451,6 @@ extern Addr VG_(sysinfo_page_addr);
extern void VG_(mash_colon_env)(Char *varp, const Char *pattern);
-/* Something of a function looking for a home ... start up GDB. This
- is called from VG_(swizzle_esp_then_start_GDB) and so runs on the
- *client's* stack. This is necessary to give GDB the illusion that
- the client program really was running on the real cpu. */
-extern void VG_(start_GDB_whilst_on_client_stack) ( void );
+/* Something of a function looking for a home ... start up GDB. */
+extern void VG_(start_GDB) ( Int tid );
/* VG_(bbs_done) in include/vg_skin.h */
@@ -1683,9 +1680,4 @@ extern Int VG_(clone) ( Int (*fn)(void *
extern void VG_(switch_to_real_CPU) ( void );
-extern void VG_(swizzle_esp_then_start_GDB) ( Addr m_eip_at_error,
- Addr m_esp_at_error,
- Addr m_ebp_at_error );
-
-
/* ---------------------------------------------------------------------
Exports of vg_dispatch.S
--- valgrind/coregrind/vg_main.c #1.136:1.137
@@ -32,4 +32,11 @@
#include "vg_include.h"
+#include <stdlib.h>
+#include <sys/ptrace.h>
+#include <sys/signal.h>
+#include <sys/user.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
/* ---------------------------------------------------------------------
Compute offsets into baseBlock. See comments in vg_include.h.
@@ -1746,16 +1753,70 @@ void VG_(mash_colon_env)(Char *varp, con
}
-/* RUNS ON THE CLIENT'S STACK, but on the real CPU. Start GDB and get
- it to attach to this process. Called if the user requests this
- service after an error has been shown, so she can poke around and
- look at parameters, memory, etc. You can't meaningfully get GDB to
- continue the program, though; to continue, quit GDB. */
-void VG_(start_GDB_whilst_on_client_stack) ( void )
+/* Start GDB and get it to attach to this process. Called if the user
+ requests this service after an error has been shown, so she can
+ poke around and look at parameters, memory, etc. You can't
+ meaningfully get GDB to continue the program, though; to continue,
+ quit GDB. */
+void VG_(start_GDB) ( Int tid )
{
+ Int pid;
+
+ if ((pid = fork()) == 0)
+ {
+ ptrace(PTRACE_TRACEME, 0, NULL, NULL);
+ VG_(kkill)(VG_(getpid)(), VKI_SIGSTOP);
+ }
+ else if (pid > 0)
+ {
+ struct user_regs_struct regs;
+ Int status;
Int res;
- UChar buf[100];
+
+ if (VG_(is_running_thread)( tid )) {
+ regs.xcs = VG_(baseBlock)[VGOFF_(m_cs)];
+ regs.xss = VG_(baseBlock)[VGOFF_(m_ss)];
+ regs.xds = VG_(baseBlock)[VGOFF_(m_ds)];
+ regs.xes = VG_(baseBlock)[VGOFF_(m_es)];
+ regs.xfs = VG_(baseBlock)[VGOFF_(m_fs)];
+ regs.xgs = VG_(baseBlock)[VGOFF_(m_gs)];
+ regs.eax = VG_(baseBlock)[VGOFF_(m_eax)];
+ regs.ebx = VG_(baseBlock)[VGOFF_(m_ebx)];
+ regs.ecx = VG_(baseBlock)[VGOFF_(m_ecx)];
+ regs.edx = VG_(baseBlock)[VGOFF_(m_edx)];
+ regs.esi = VG_(baseBlock)[VGOFF_(m_esi)];
+ regs.edi = VG_(baseBlock)[VGOFF_(m_edi)];
+ regs.ebp = VG_(baseBlock)[VGOFF_(m_ebp)];
+ regs.esp = VG_(baseBlock)[VGOFF_(m_esp)];
+ regs.eflags = VG_(baseBlock)[VGOFF_(m_eflags)];
+ regs.eip = VG_(baseBlock)[VGOFF_(m_eip)];
+ } else {
+ ThreadState* tst = & VG_(threads)[ tid ];
+
+ regs.xcs = tst->m_cs;
+ regs.xss = tst->m_ss;
+ regs.xds = tst->m_ds;
+ regs.xes = tst->m_es;
+ regs.xfs = tst->m_fs;
+ regs.xgs = tst->m_gs;
+ regs.eax = tst->m_eax;
+ regs.ebx = tst->m_ebx;
+ regs.ecx = tst->m_ecx;
+ regs.edx = tst->m_edx;
+ regs.esi = tst->m_esi;
+ regs.edi = tst->m_edi;
+ regs.ebp = tst->m_ebp;
+ regs.esp = tst->m_esp;
+ regs.eflags = tst->m_eflags;
+ regs.eip = tst->m_eip;
+ }
+
+ if ((res = VG_(waitpid)(pid, &status, 0)) == pid &&
+ WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP &&
+ ptrace(PTRACE_SETREGS, pid, NULL, ®s) == 0 &&
+ ptrace(PTRACE_DETACH, pid, NULL, SIGSTOP) == 0) {
+ UChar buf[VG_(strlen)(VG_(clo_GDB_path)) + 100];
VG_(sprintf)(buf, "%s -nw /proc/%d/fd/%d %d",
- VG_(clo_GDB_path), VG_(getpid)(), VG_(clexecfd), VG_(getpid)());
+ VG_(clo_GDB_path), VG_(main_pid), VG_(clexecfd), pid);
VG_(message)(Vg_UserMsg, "starting GDB with cmd: %s", buf);
res = VG_(system)(buf);
@@ -1768,4 +1829,9 @@ void VG_(start_GDB_whilst_on_client_stac
VG_(message)(Vg_UserMsg, "");
}
+ }
+
+ VG_(kkill)(pid, VKI_SIGKILL);
+ VG_(waitpid)(pid, &status, 0);
+ }
}
--- valgrind/coregrind/vg_signals.c #1.55:1.56
@@ -1393,6 +1393,5 @@ static void vg_default_action(const vki_
if (VG_(is_action_requested)( "Attach to GDB", & VG_(clo_GDB_attach) )) {
- ThreadState* tst = & VG_(threads)[ tid ];
- VG_(swizzle_esp_then_start_GDB)( tst->m_eip, tst->m_esp, tst->m_ebp );
+ VG_(start_GDB)( tid );
}
--- valgrind/coregrind/vg_startup.S #1.21:1.22
@@ -81,86 +81,4 @@
-/*------------------------------------------------------------*/
-/*--- A function to temporarily copy %ESP/%EBP into ---*/
-/*--- %esp/%ebp and then start up GDB. ---*/
-/*------------------------------------------------------------*/
-
-/*
-extern void VG_(swizzle_esp_then_start_GDB) ( Addr m_eip_at_error,
- Addr m_esp_at_error,
- Addr m_ebp_at_error );
-*/
-
-/*--- This is clearly not re-entrant! ---*/
-.data
-vg_ebp_saved_over_GDB_start:
- .long 0
-vg_esp_saved_over_GDB_start:
- .long 0
-.text
-
-.type VG_(swizzle_esp_then_start_GDB),@function
-.global VG_(swizzle_esp_then_start_GDB)
-VG_(swizzle_esp_then_start_GDB):
-#ifdef HAVE_GAS_CFI
- .cfi_startproc
-#endif
- pushal
-
- # remember the simulators current stack/frame pointers
- movl %ebp, vg_ebp_saved_over_GDB_start
- movl %esp, vg_esp_saved_over_GDB_start
-
- # get args into regs
- movl 44(%esp), %eax # client %EBP
- movl 40(%esp), %ebx # client %ESP
- movl 36(%esp), %ecx # client %EIP
-
- # Now that we dont need to refer to simulators stack any more,
- # put %ESP into %esp
- movl %ebx, %esp
-
- ### %esp now refers to clients stack
- ### mess with the clients stack to make it look as if it
- ### called this procedure, since otherwise it will look to gdb
- ### as if the top (currently executing) stack frame of the
- ### client is missing.
-
- # push %EIP. This is a faked-up return address.
- pushl %ecx
-
- # push %EBP. This is a faked %ebp-chain pointer.
- pushl %eax
-#ifdef HAVE_GAS_CFI
- .cfi_adjust_cfa_offset 0x4
-#endif
-
- movl %esp, %ebp
-#ifdef HAVE_GAS_CFI
- .cfi_def_cfa_register ebp
-#endif
-
- call VG_(start_GDB_whilst_on_client_stack)
-
- # restore the simulators stack/frame pointer
- movl vg_ebp_saved_over_GDB_start, %ebp
- movl vg_esp_saved_over_GDB_start, %esp
-#ifdef HAVE_GAS_CFI
- .cfi_adjust_cfa_offset -0x4
-#endif
-
- popal
- ret
-#ifdef HAVE_GAS_CFI
- .cfi_endproc
-#endif
-
-# gcc puts this construction at the end of every function. I think it
-# allows the linker to figure out the size of the function. So we do
-# the same, in the vague hope that it might help GDBs navigation.
-.Lend_of_swizzle:
- .size VG_(swizzle_esp_then_start_GDB), .Lend_of_swizzle-VG_(swizzle_esp_then_start_GDB)
-
-
##--------------------------------------------------------------------##
##--- end vg_startup.S ---##
|
|
From: Jeremy F. <je...@go...> - 2004-01-07 08:45:19
|
CVS commit by fitzhardinge:
Fix for bug 72006 by Tom Hughes: report proper error returns for mmap()
M +24 -13 vg_syscalls.c 1.76
--- valgrind/coregrind/vg_syscalls.c #1.75:1.76
@@ -3556,4 +3556,5 @@ PRE(mmap2)
POST(mmap2)
{
+ if (!VG_(is_kerror)(res)) {
if (!valid_client_addr(res, arg2, tid, "mmap2")) {
VG_(munmap)((void *)res, arg2);
@@ -3561,4 +3562,5 @@ POST(mmap2)
} else
mmap_segment( (Addr)res, arg2, arg3, arg4, arg5, arg6 * (ULong)VKI_BYTES_PER_PAGE );
+ }
}
@@ -3597,9 +3599,17 @@ PRE(mmap)
if (res != -VKI_ENOMEM) {
- res = (Int)VG_(mmap)((void *)a1, a2, a3, a4 | VKI_MAP_CLIENT, a5, a6);
+ UInt new_arg_block[6];
- if (res == -1)
- res = -VKI_ENOMEM;
- else if (!valid_client_addr(res, a2, tid, "mmap")) {
+ new_arg_block[0] = a1;
+ new_arg_block[1] = a2;
+ new_arg_block[2] = a3;
+ new_arg_block[3] = a4;
+ new_arg_block[4] = a5;
+ new_arg_block[5] = a6;
+
+ res = VG_(do_syscall)(__NR_mmap, new_arg_block);
+
+ if (!VG_(is_kerror)(res)) {
+ if (!valid_client_addr(res, a2, tid, "mmap")) {
VG_(munmap)((void *)res, a2);
res = -VKI_ENOMEM;
@@ -3607,4 +3617,5 @@ PRE(mmap)
mmap_segment( (Addr)res, a2, a3, a4, a5, a6 );
}
+ }
}
|
|
From: Dirk M. <mu...@kd...> - 2004-01-07 19:13:41
|
CVS commit by mueller:
yet another SSE insn (rsqrtss)
M +9 -0 vg_to_ucode.c 1.121
--- valgrind/coregrind/vg_to_ucode.c #1.120:1.121
@@ -4514,4 +4514,13 @@ static Addr disInstr ( UCodeBlock* cb, A
}
+ /* RSQRTSS: square root reciprocal of scalar float. */
+ if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x52) {
+ vg_assert(sz == 4);
+ eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+3, 4,
+ "sqrtss",
+ insn[0], insn[1], insn[2] );
+ goto decode_success;
+ }
+
/* MOVLPS -- 8-byte load/store. How is this different from MOVLPS
? */
|
|
From: Nicholas N. <nj...@ca...> - 2004-01-20 16:17:08
|
CVS commit by nethercote:
From Tom Hughes: patch to report port numbers correctly
M +1 -1 vg_syscalls.c 1.79
--- valgrind/coregrind/vg_syscalls.c #1.78:1.79
@@ -541,5 +541,5 @@ Char *inet2name(struct sockaddr_in *sa,
addr & 0xFF, (addr>>8) & 0xFF,
(addr>>16) & 0xFF, (addr>>24) & 0xFF,
- sa->sin_port);
+ ntohs(sa->sin_port));
}
}
|
|
From: Nicholas N. <nj...@ca...> - 2004-01-20 22:29:30
|
CVS commit by nethercote:
Patch to add support for the alternate MOVQ encoding, from Tom Hughes.
M +8 -1 vg_to_ucode.c 1.123
--- valgrind/coregrind/vg_to_ucode.c #1.122:1.123
@@ -6823,5 +6823,12 @@ static Addr disInstr ( UCodeBlock* cb, A
modrm = getUChar(eip);
if (epartIsReg(modrm)) {
- goto decode_failure;
+ eip++;
+ uInstr1(cb, MMX2, 0,
+ Lit16,
+ (((UShort)(opc)) << 8) | ((UShort)modrm) );
+ if (dis)
+ VG_(printf)("movq %s, %s\n",
+ nameMMXReg(gregOfRM(modrm)),
+ nameMMXReg(eregOfRM(modrm)));
} else {
Int tmpa;
|
|
From: Nicholas N. <nj...@ca...> - 2004-01-24 20:30:14
|
CVS commit by nethercote: Forgot to remove this. R stage2.c 1.7 |
|
From: Jeremy F. <je...@go...> - 2004-01-25 02:39:04
|
CVS commit by fitzhardinge:
Virtualize CPUID. Rather than just using the host CPU's CPUID,
we now completely virtualize it. The feature flags returned are the
intersection of the set the CPU supports, and the set of flags Valgrind
supports. This turns out to be a small number of features, like FPU,
TSC, MMX, SSE, SSE2, FXSR. All mention of things which are only useful
to kernel-mode code are also suppressed. This CPUID doesn't support
any extended feature flags, or extended CPUID operations. It returns a
vendor string of "ValgrindVCPU".
If the host CPU doesn't support CPUID, then we make sure we treat it as
an illegal instruction (I'm not sure if we handle the eflags bit toggle
test right). This is because the CPUID helper doesn't actually use the
cpuid instruction in all cases, so it may succeed where the host CPU
wouldn't (other instructions which depend on feature flags will end up
generating those instructions, so they'll endup generating a SIGILL if
client code uses them on a CPU which doesn't support them).
M +47 -0 vg_constants.h 1.16
M +38 -14 vg_helpers.S 1.29
M +0 -33 vg_include.h 1.173
M +6 -1 vg_to_ucode.c 1.126
--- valgrind/coregrind/vg_constants.h #1.15:1.16
@@ -95,4 +95,51 @@
#define VG_USERREQ__SIGNAL_RETURNS 0x4001
+/* CPU features */
+#define VG_X86_FEAT_FPU (0*32 + 0)
+#define VG_X86_FEAT_VME (0*32 + 1)
+#define VG_X86_FEAT_DE (0*32 + 2)
+#define VG_X86_FEAT_PSE (0*32 + 3)
+#define VG_X86_FEAT_TSC (0*32 + 4)
+#define VG_X86_FEAT_MSR (0*32 + 5)
+#define VG_X86_FEAT_PAE (0*32 + 6)
+#define VG_X86_FEAT_MCE (0*32 + 7)
+#define VG_X86_FEAT_CX8 (0*32 + 8)
+#define VG_X86_FEAT_APIC (0*32 + 9)
+#define VG_X86_FEAT_SEP (0*32 + 11)
+#define VG_X86_FEAT_MTRR (0*32 + 12)
+#define VG_X86_FEAT_PGE (0*32 + 13)
+#define VG_X86_FEAT_MCA (0*32 + 14)
+#define VG_X86_FEAT_CMOV (0*32 + 15)
+#define VG_X86_FEAT_PAT (0*32 + 16)
+#define VG_X86_FEAT_PSE36 (0*32 + 17)
+#define VG_X86_FEAT_CLFSH (0*32 + 19)
+#define VG_X86_FEAT_DS (0*32 + 21)
+#define VG_X86_FEAT_ACPI (0*32 + 22)
+#define VG_X86_FEAT_MMX (0*32 + 23)
+#define VG_X86_FEAT_FXSR (0*32 + 24)
+#define VG_X86_FEAT_SSE (0*32 + 25)
+#define VG_X86_FEAT_SSE2 (0*32 + 26)
+#define VG_X86_FEAT_SS (0*32 + 27)
+#define VG_X86_FEAT_HT (0*32 + 28)
+#define VG_X86_FEAT_TM (0*32 + 29)
+#define VG_X86_FEAT_PBE (0*32 + 31)
+
+#define VG_X86_FEAT_EST (1*32 + 7)
+#define VG_X86_FEAT_TM2 (1*32 + 8)
+#define VG_X86_FEAT_CNXTID (1*32 + 10)
+
+/* Used internally to mark whether CPUID is even implemented */
+#define VG_X86_FEAT_CPUID (2*32 + 0)
+
+/* The set of features we're willing to support for the client */
+#define VG_SUPPORTED_FEATURES \
+ ((1 << VG_X86_FEAT_FPU) | \
+ (1 << VG_X86_FEAT_TSC) | \
+ (1 << VG_X86_FEAT_CMOV) | \
+ (1 << VG_X86_FEAT_MMX) | \
+ (1 << VG_X86_FEAT_FXSR) | \
+ (1 << VG_X86_FEAT_SSE) | \
+ (1 << VG_X86_FEAT_SSE2))
+
/* Various environment variables we pay attention to */
--- valgrind/coregrind/vg_helpers.S #1.28:1.29
@@ -194,5 +194,6 @@
issue a "real" cpuid instruction and then mask out
the bits of the features we do not support currently (3dnow mostly).
-
+ We also claim to not support most CPUID operations.
+
Dirk Mueller <mu...@kd...>
@@ -214,17 +215,37 @@
movl 32(%esp), %eax
- cmpl $0x80000001, %eax
- je cpuid_no3dnow
-
- cpuid
- jmp cpuid__99
-
-cpuid_no3dnow:
- cpuid
+ /* eax==0 - max valid request+processor vendor */
+ cmpl $0, %eax
+ jne 1f
+
+ movl $1, %eax /* only support request 1 */
+ movl valgrind_brand+0, %ebx
+ movl valgrind_brand+4, %edx
+ movl valgrind_brand+8, %ecx
+ jmp 99f
+
+ /* eax==1 - CPU features and model ID */
+1: cmpl $1, %eax
+ jne 2f
+
+ cpuid /* get host CPU's capabilities */
+
+ movl $0111, %eax
+ movl $0, %ebx /* clear APIC id, CLFLUSH size, Brand ID */
+ movl $0, %ecx /* clear extended feature bits */
+ andl $VG_SUPPORTED_FEATURES, %edx /* mask off feature bits we don't support */
+ jmp 99f
+
+ /* eax=0x80000000 - extended cpuid functions */
+2: cmpl $0x80000000, %eax
+ jne 99f
+
+ /* leave eax==0x80000000 - we don't support any other extended operations */
+ movl valgrind_brand+0, %ebx /* AMD load the brand string again - */
+ movl valgrind_brand+4, %edx /* Intel leaves them "reserved" */
+ movl valgrind_brand+8, %ecx
- andl $0x3fffffff, %edx
-
-cpuid__99:
- movl %edx, 20(%esp)
+
+99: movl %edx, 20(%esp)
movl %ecx, 24(%esp)
movl %ebx, 28(%esp)
@@ -236,5 +257,8 @@
popl %eax
ret
-
+.data
+valgrind_brand:
+ .ascii "ValgrindVCPU"
+.text
/* Fetch the FPU status register.
--- valgrind/coregrind/vg_include.h #1.172:1.173
@@ -1137,37 +1137,4 @@ extern Bool VG_(is_chained_jumpsite)
------------------------------------------------------------------ */
-#define VG_X86_FEAT_FPU (0*32 + 0)
-#define VG_X86_FEAT_VME (0*32 + 1)
-#define VG_X86_FEAT_DE (0*32 + 2)
-#define VG_X86_FEAT_PSE (0*32 + 3)
-#define VG_X86_FEAT_TSC (0*32 + 4)
-#define VG_X86_FEAT_MSR (0*32 + 5)
-#define VG_X86_FEAT_PAE (0*32 + 6)
-#define VG_X86_FEAT_MCE (0*32 + 7)
-#define VG_X86_FEAT_CX8 (0*32 + 8)
-#define VG_X86_FEAT_APIC (0*32 + 9)
-#define VG_X86_FEAT_SEP (0*32 + 11)
-#define VG_X86_FEAT_MTRR (0*32 + 12)
-#define VG_X86_FEAT_PGE (0*32 + 13)
-#define VG_X86_FEAT_MCA (0*32 + 14)
-#define VG_X86_FEAT_CMOV (0*32 + 15)
-#define VG_X86_FEAT_PAT (0*32 + 16)
-#define VG_X86_FEAT_PSE36 (0*32 + 17)
-#define VG_X86_FEAT_CLFSH (0*32 + 19)
-#define VG_X86_FEAT_DS (0*32 + 21)
-#define VG_X86_FEAT_ACPI (0*32 + 22)
-#define VG_X86_FEAT_MMX (0*32 + 23)
-#define VG_X86_FEAT_FXSR (0*32 + 24)
-#define VG_X86_FEAT_SSE (0*32 + 25)
-#define VG_X86_FEAT_SSE2 (0*32 + 26)
-#define VG_X86_FEAT_SS (0*32 + 27)
-#define VG_X86_FEAT_HT (0*32 + 28)
-#define VG_X86_FEAT_TM (0*32 + 29)
-#define VG_X86_FEAT_PBE (0*32 + 31)
-
-#define VG_X86_FEAT_EST (1*32 + 7)
-#define VG_X86_FEAT_TM2 (1*32 + 8)
-#define VG_X86_FEAT_CNXTID (1*32 + 10)
-
Bool VG_(cpu_has_feature)(UInt feat);
--- valgrind/coregrind/vg_to_ucode.c #1.125:1.126
@@ -46,5 +46,5 @@
/*------------------------------------------------------------*/
-#define VG_N_FEATURE_WORDS 2
+#define VG_N_FEATURE_WORDS 3
static Int cpuid_level = -2; /* -2 -> not initialized */
@@ -109,4 +109,6 @@ static void get_cpu_features(void)
}
+ cpu_features[2] |= (1 << (VG_X86_FEAT_CPUID%32));
+
cpuid_level = cpuid_eax(0);
@@ -6504,4 +6506,7 @@ static Addr disInstr ( UCodeBlock* cb, A
case 0xA2: /* CPUID */
+ if (!VG_(cpu_has_feature)(VG_X86_FEAT_CPUID))
+ goto decode_failure;
+
t1 = newTemp(cb);
t2 = newTemp(cb);
|
|
From: Dirk M. <dm...@gm...> - 2004-01-25 03:00:30
|
On Sunday 25 January 2004 03:38, Jeremy Fitzhardinge wrote: > to kernel-mode code are also suppressed. This CPUID doesn't support > any extended feature flags, or extended CPUID operations. It returns a > vendor string of "ValgrindVCPU". Euhm, I'm curious: why that? It seems most sensible to me to actually emulate the host we're running on as close as possible, instead of purposefully breaking the emulation by doing stuff like returning a vendor string of "ValgrindVCPU". I'm pretty sure that developers do want to figure out why an application doesn't work when it is not run under valgrind. when it is run under valgrind, the same codepaths should be taken. Its hard to imagine what you were trying to fix here since though. |
|
From: Jeremy F. <je...@go...> - 2004-01-25 03:07:14
|
On Sat, 2004-01-24 at 19:00, Dirk Mueller wrote: > Euhm, I'm curious: why that? > > It seems most sensible to me to actually emulate the host we're running on as > close as possible, instead of purposefully breaking the emulation by doing > stuff like returning a vendor string of "ValgrindVCPU". > > I'm pretty sure that developers do want to figure out why an application > doesn't work when it is not run under valgrind. when it is run under > valgrind, the same codepaths should be taken. > > Its hard to imagine what you were trying to fix here since though. Well, exactly that. We're so far from being like the underlying CPU, there's no point in pretending it is actually the underlying CPU. It still emulates all the important parts of the CPUID instruction, and any program which correctly uses CPUID will be fine. Programs which don't correctly use the CPUID instruction should be given the opportunity to fail so they can be fixed. Also, it means you could use CPUID to implement RUNNING_ON_VALGRIND, which may be useful (for example, if you want to special-case something, without actually having a source dependency on valgrind/*.h). J |
|
From: Tom H. <th...@cy...> - 2004-01-25 09:50:19
|
In message <200...@of...>
Jeremy Fitzhardinge <je...@go...> wrote:
> +/* The set of features we're willing to support for the client */
> +#define VG_SUPPORTED_FEATURES \
> + ((1 << VG_X86_FEAT_FPU) | \
> + (1 << VG_X86_FEAT_TSC) | \
> + (1 << VG_X86_FEAT_CMOV) | \
> + (1 << VG_X86_FEAT_MMX) | \
> + (1 << VG_X86_FEAT_FXSR) | \
> + (1 << VG_X86_FEAT_SSE) | \
> + (1 << VG_X86_FEAT_SSE2))
> +
The CX8 bit should be set as well, as valgrind supports cmpxchg8b.
Tom
--
Tom Hughes (th...@cy...)
Software Engineer, Cyberscience Corporation
http://www.cyberscience.com/
|
|
From: Tom H. <th...@cy...> - 2004-01-25 10:12:33
|
In message <200...@of...>
Jeremy Fitzhardinge <je...@go...> wrote:
> Virtualize CPUID. Rather than just using the host CPU's CPUID,
> we now completely virtualize it. The feature flags returned are the
> intersection of the set the CPU supports, and the set of flags Valgrind
> supports. This turns out to be a small number of features, like FPU,
> TSC, MMX, SSE, SSE2, FXSR. All mention of things which are only useful
> to kernel-mode code are also suppressed. This CPUID doesn't support
> any extended feature flags, or extended CPUID operations. It returns a
> vendor string of "ValgrindVCPU".
We should really handle extended flags and set the MMXEXT bit as we
do support all the MMXEXT instructions on Athlons.
Tom
--
Tom Hughes (th...@cy...)
Software Engineer, Cyberscience Corporation
http://www.cyberscience.com/
|
|
From: Jeremy F. <je...@go...> - 2004-01-25 21:41:36
|
On Sun, 2004-01-25 at 02:12, Tom Hughes wrote: > We should really handle extended flags and set the MMXEXT bit as we > do support all the MMXEXT instructions on Athlons. Oh, I hadn't realized we were supporting some of the AMD extensions. Well, I guess we need to leave the vendor name unmolested. J |