mirror of
https://github.com/Zenithsiz/ftmemsim-valgrind.git
synced 2026-02-04 02:18:37 +00:00
run, though. There are lots of stubs to be filled in. (The asm ones currently just have "swi" in them, which seems to cause seg faults.) Also, some of the macros are decided dubious, especially: ARCH_* are bogus SYSCALL_RET is bogus PLATFORM_SET_SYSCALL_RESULT is bogus not sure about SET_SYSCALL_RETVAL FIRST_STACK_FRAME et al -- bogus? VG_MAX_JUMPS ? And in stage2.lds, the 0x8048000 is almost certainly wrong This required some tweakings of the core: - some of the vki_*.h kernel types were fixed up - had to disable the AM_PROG_CC_C_O macro in configure.in, because automake (autoconf?) didn't like it... - some "#ifdef __x86__" guards were introduced, for nasty x86 things I don't yet know how to factor out (trampoline page muck, sysinfo page muck). - fixed a minor stupidity in vg_proxylwp.c. - moved the ptrace wrapper into the x86-linux part - had to change the intercept mangling scheme, to use 'J' instead of '$' as the escape char because GCC didn't like '$'. This is all very dubious, and only works because none of our intercepted symbols contains a 'J'. To be fixed up ASAP. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@3120
258 lines
6.0 KiB
C
258 lines
6.0 KiB
C
|
|
/*--------------------------------------------------------------------*/
|
|
/*--- ARM-specific libpthread code. arm/libpthread.c ---*/
|
|
/*--------------------------------------------------------------------*/
|
|
|
|
/*
|
|
This file is part of Valgrind, an extensible x86 protected-mode
|
|
emulator for monitoring program execution on x86-Unixes.
|
|
|
|
Copyright (C) 2000-2004 Julian Seward
|
|
jseward@acm.org
|
|
|
|
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.
|
|
*/
|
|
|
|
/* ALL THIS CODE RUNS ON THE SIMULATED CPU.
|
|
|
|
See the comments at the top of coregrind/vg_libpthread.c for some
|
|
caveats.
|
|
*/
|
|
|
|
#include "core.h" /* For the VG_USERREQ__* constants */
|
|
|
|
#define __USE_UNIX98
|
|
#include <pthread.h>
|
|
#undef __USE_UNIX98
|
|
|
|
#define __USE_GNU
|
|
#include <dlfcn.h>
|
|
#undef __USE_GNU
|
|
|
|
#include <errno.h>
|
|
|
|
// Struct used to describe a TDB header, copied from glibc.
|
|
typedef
|
|
struct {
|
|
void *tcb;
|
|
void *dtv;
|
|
void *self;
|
|
int multiple_threads;
|
|
unsigned long sysinfo;
|
|
}
|
|
tcbhead_t;
|
|
|
|
/* ---------------------------------------------------
|
|
Helper functions for running a thread
|
|
and for clearing up afterwards.
|
|
------------------------------------------------ */
|
|
|
|
#if 0
|
|
typedef void *(*__attribute__ ((stdcall)) REGPARM(3) allocate_tls_t) (void *result);
|
|
typedef void (*__attribute__ ((stdcall)) REGPARM(3) deallocate_tls_t) (void *tcb, int dealloc_tcb);
|
|
|
|
static allocate_tls_t allocate_tls = NULL;
|
|
static deallocate_tls_t deallocate_tls = NULL;
|
|
|
|
static int get_gs()
|
|
{
|
|
int gs;
|
|
asm volatile ("movw %%gs, %w0" : "=q" (gs));
|
|
return gs & 0xffff;
|
|
}
|
|
|
|
static void set_gs( int gs )
|
|
{
|
|
I_die_here;
|
|
asm volatile ("movw %w0, %%gs" :: "q" (gs));
|
|
}
|
|
|
|
static void *get_tcb()
|
|
{
|
|
void *tcb;
|
|
asm volatile ("movl %%gs:0, %0" : "=r" (tcb));
|
|
return tcb;
|
|
}
|
|
#endif
|
|
|
|
Bool VGA_(has_tls)(void)
|
|
{
|
|
I_die_here;
|
|
#if 0
|
|
return (get_gs() & 7) == 3;
|
|
#endif
|
|
}
|
|
|
|
|
|
void VGA_(thread_create)(ThreadArchAux *aux)
|
|
{
|
|
I_die_here;
|
|
#if 0
|
|
if (VGA_(has_tls)()) {
|
|
tcbhead_t *tcb = get_tcb();
|
|
|
|
if (allocate_tls == NULL || deallocate_tls == NULL) {
|
|
allocate_tls = (allocate_tls_t)dlsym(RTLD_DEFAULT, "_dl_allocate_tls");
|
|
deallocate_tls = (deallocate_tls_t)dlsym(RTLD_DEFAULT, "_dl_deallocate_tls");
|
|
}
|
|
|
|
my_assert(allocate_tls != NULL);
|
|
|
|
aux->tls_data = allocate_tls(NULL);
|
|
aux->tls_segment = get_gs() >> 3;
|
|
aux->sysinfo = tcb->sysinfo;
|
|
|
|
tcb->multiple_threads = 1;
|
|
} else {
|
|
aux->tls_data = NULL;
|
|
aux->tls_segment = -1;
|
|
aux->sysinfo = 0;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void VGA_(thread_wrapper)(ThreadArchAux *aux)
|
|
{
|
|
I_die_here;
|
|
#if 0
|
|
void* tls_data;
|
|
int tls_segment;
|
|
unsigned long sysinfo;
|
|
|
|
tls_data = aux->tls_data;
|
|
tls_segment = aux->tls_segment;
|
|
sysinfo = aux->sysinfo;
|
|
|
|
if (tls_data) {
|
|
tcbhead_t *tcb = tls_data;
|
|
vki_modify_ldt_t ldt_info;
|
|
|
|
/* Fill in the TCB header */
|
|
tcb->tcb = tcb;
|
|
tcb->self = tcb;
|
|
tcb->multiple_threads = 1;
|
|
tcb->sysinfo = sysinfo;
|
|
|
|
/* Fill in an LDT descriptor */
|
|
ldt_info.entry_number = tls_segment;
|
|
ldt_info.base_addr = (unsigned long)tls_data;
|
|
ldt_info.limit = 0xfffff;
|
|
ldt_info.seg_32bit = 1;
|
|
ldt_info.contents = 0;
|
|
ldt_info.read_exec_only = 0;
|
|
ldt_info.limit_in_pages = 1;
|
|
ldt_info.seg_not_present = 0;
|
|
ldt_info.useable = 1;
|
|
ldt_info.reserved = 0;
|
|
|
|
/* Install the thread area */
|
|
VG_(do_syscall)(__NR_set_thread_area, &ldt_info);
|
|
|
|
/* Setup the GS segment register */
|
|
set_gs(ldt_info.entry_number * 8 + 3);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void VGA_(thread_exit)(void)
|
|
{
|
|
I_die_here;
|
|
#if 0
|
|
/* Free up any TLS data */
|
|
if ((get_gs() & 7) == 3 && pthread_self() > 1) {
|
|
my_assert(deallocate_tls != NULL);
|
|
deallocate_tls(get_tcb(), 1);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/* POSIX spinlocks, taken from glibc linuxthreads/sysdeps/i386 */
|
|
|
|
typedef volatile int pthread_spinlock_t; /* Huh? Guarded by __USE_XOPEN2K */
|
|
|
|
int pthread_spin_init(pthread_spinlock_t *lock, int pshared)
|
|
{
|
|
I_die_here;
|
|
#if 0
|
|
/* We can ignore the `pshared' parameter. Since we are busy-waiting
|
|
all processes which can access the memory location `lock' points
|
|
to can use the spinlock. */
|
|
*lock = 1;
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
int pthread_spin_lock(pthread_spinlock_t *lock)
|
|
{
|
|
I_die_here;
|
|
#if 0
|
|
asm volatile
|
|
("\n"
|
|
"1:\n\t"
|
|
"lock; decl %0\n\t"
|
|
"js 2f\n\t"
|
|
".section .text.spinlock,\"ax\"\n"
|
|
"2:\n\t"
|
|
"cmpl $0,%0\n\t"
|
|
"rep; nop\n\t"
|
|
"jle 2b\n\t"
|
|
"jmp 1b\n\t"
|
|
".previous"
|
|
: "=m" (*lock));
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
int pthread_spin_unlock(pthread_spinlock_t *lock)
|
|
{
|
|
I_die_here;
|
|
#if 0
|
|
asm volatile
|
|
("movl $1,%0"
|
|
: "=m" (*lock));
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
int pthread_spin_destroy(pthread_spinlock_t *lock)
|
|
{
|
|
I_die_here;
|
|
#if 0
|
|
/* Nothing to do. */
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
int pthread_spin_trylock(pthread_spinlock_t *lock)
|
|
{
|
|
I_die_here;
|
|
#if 0
|
|
int oldval;
|
|
|
|
asm volatile
|
|
("xchgl %0,%1"
|
|
: "=r" (oldval), "=m" (*lock)
|
|
: "0" (0));
|
|
return oldval > 0 ? 0 : EBUSY;
|
|
#endif
|
|
}
|
|
|
|
/*--------------------------------------------------------------------*/
|
|
/*--- end ---*/
|
|
/*--------------------------------------------------------------------*/
|