|
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;
|