static
Addr setup_client_stack( void* init_sp,
char** orig_envp,
- const struct exeinfo *info,
+ const ExeInfo* info,
UInt** client_auxv,
Addr clstack_end,
SizeT clstack_max_size )
/* Load the client whose name is VG_(argv_the_exename). */
-static void load_client ( /*OUT*/struct exeinfo* info,
- /*OUT*/Addr* client_eip)
+static void load_client ( /*OUT*/ExeInfo* info,
+ /*OUT*/Addr* client_ip,
+ /*OUT*/Addr* client_toc)
{
HChar* exe_name;
Int ret;
VG_(cl_exec_fd) = res.val;
/* Copy necessary bits of 'info' that were filled in */
- *client_eip = info->init_eip;
+ *client_ip = info->init_ip;
+ *client_toc = info->init_toc;
VG_(brk_base) = VG_(brk_limit) = VG_PGROUNDUP(info->brkbase);
}
*/
static void init_thread1state ( Addr client_ip,
Addr client_sp,
- Addr entry,
+ Addr client_toc,
/*inout*/ ThreadArchState* arch )
{
#if defined(VGA_x86)
/* Put essential stuff into the new state. */
arch->vex.guest_GPR1 = client_sp;
- arch->vex.guest_GPR2 = ((ULong*)entry)[1]; // TOC ptr
+ arch->vex.guest_GPR2 = client_toc;
arch->vex.guest_CIA = client_ip;
#else
# error Unknown arch
Int main(Int argc, HChar **argv, HChar **envp)
{
- HChar* toolname = "memcheck"; // default to Memcheck
- HChar** env = NULL;
- Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
- Addr initial_client_IP = 0;
- Addr initial_client_SP = 0;
- Addr clstack_top = 0;
- SizeT clstack_max_size = 0;
+ HChar* toolname = "memcheck"; // default to Memcheck
+ HChar** env = NULL;
+ Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
+ Addr initial_client_IP = 0;
+ Addr initial_client_SP = 0;
+ Addr initial_client_TOC = 0;
+ Addr clstack_top = 0;
+ SizeT clstack_max_size = 0;
UInt* client_auxv;
Int loglevel, i;
Bool logging_to_fd;
struct vki_rlimit zero = { 0, 0 };
- struct exeinfo info;
+ ExeInfo info;
//============================================================
//
if (VG_(args_the_exename) == NULL)
missing_prog();
- load_client(&info, &initial_client_IP);
+ load_client(&info, &initial_client_IP, &initial_client_TOC);
}
//--------------------------------------------------------------
VG_(debugLog)(2, "main",
"Client info: "
- "initial_IP=%p initial_SP=%p brk_base=%p\n",
+ "initial_IP=%p initial_SP=%p initial_TOC=%p brk_base=%p\n",
(void*)initial_client_IP,
(void*)initial_client_SP,
+ (void*)initial_client_TOC,
(void*)VG_(brk_base) );
}
// setup_scheduler() [for the rest of state 1 stuff]
//--------------------------------------------------------------
VG_(debugLog)(1, "main", "Initialise thread 1's state\n");
- init_thread1state( initial_client_IP, initial_client_SP,
- info.entry,
+ init_thread1state( initial_client_IP,
+ initial_client_SP,
+ initial_client_TOC,
&VG_(threads)[1].arch);
//--------------------------------------------------------------
sp++;
sp++;
-#if defined(VGA_ppc32)
+#if defined(VGA_ppc32) || defined(VGA_ppc64)
# if defined AT_IGNOREPPC
while (*sp == AT_IGNOREPPC) // skip AT_IGNOREPPC entries
sp += 2;
- The entry point in INFO is set to the interpreter's entry point,
and we're done. */
-static Int load_ELF(Int fd, const char *name, /*MOD*/struct exeinfo *info)
+static Int load_ELF(Int fd, const HChar* name, /*MOD*/ExeInfo* info)
{
SysRes sres;
struct elfinfo *e;
TOC entry contains three words; the first word is the function
address, the second word is the TOC ptr (r2), and the third word
is the static chain value. */
- info->init_eip = ((ULong*)entry)[0];
+ info->init_ip = ((ULong*)entry)[0];
+ info->init_toc = ((ULong*)entry)[1];
#else
- info->init_eip = (Addr)entry;
+ info->init_ip = (Addr)entry;
+ info->init_toc = 0; /* meaningless on this platform */
#endif
VG_(free)(e->p);
VG_(free)(e);
}
// Forward declaration.
-static Int do_exec_inner(const char *exe, struct exeinfo *info);
+static Int do_exec_inner(const HChar* exe, ExeInfo* info);
/* returns: 0 = success, non-0 is failure */
-static Int load_script(Int fd, const char *name, struct exeinfo *info)
+static Int load_script(Int fd, const HChar* name, ExeInfo* info)
{
Char hdr[VKI_PAGE_SIZE];
Int len = VKI_PAGE_SIZE;
} ExeFormat;
// Check the file looks executable.
-SysRes VG_(pre_exec_check)(const Char* exe_name, Int* out_fd)
+SysRes VG_(pre_exec_check)(const HChar* exe_name, Int* out_fd)
{
Int fd, ret;
SysRes res;
// We can execute only ELF binaries or scripts that begin with "#!". (Not,
// for example, scripts that don't begin with "#!"; see the VG_(do_exec)()
// invocation from m_main.c for how that's handled.)
-static Int do_exec_inner(const char *exe, struct exeinfo *info)
+static Int do_exec_inner(const HChar *exe, ExeInfo* info)
{
SysRes res;
Int fd;
// bash as a guide). It's worth noting that the shell can execute some
// things that VG_(do_exec)() (which subsitutes for the kernel's exec())
// will refuse to (eg. scripts lacking a "#!" prefix).
-static Int do_exec_shell_followup(Int ret, Char* exe_name,
- struct exeinfo* info)
+static Int do_exec_shell_followup(Int ret, HChar* exe_name,
+ ExeInfo* info)
{
Char* default_interp_name = "/bin/sh";
SysRes res;
// See ume.h for an indication of which entries of 'info' are inputs, which
// are outputs, and which are both.
/* returns: 0 = success, non-0 is failure */
-Int VG_(do_exec)(const char *exe_name, struct exeinfo *info)
+Int VG_(do_exec)(const HChar* exe_name, ExeInfo* info)
{
Int ret;
// Info needed to load and run a program. IN/INOUT/OUT refers to the
// inputs/outputs of do_exec().
-struct exeinfo
-{
- char** argv; // IN: the original argv
-
- Addr exe_base; // INOUT: lowest (allowed) address of exe
- Addr exe_end; // INOUT: highest (allowed) address
-
- Addr phdr; // OUT: address phdr was mapped at
- int phnum; // OUT: number of phdrs
- Addr interp_base; // OUT: where interpreter (ld.so) was mapped
- Addr entry; // OUT: entrypoint in main executable
- Addr init_eip; // OUT: initial eip
- Addr brkbase; // OUT: base address of brk segment
-
- // These are the extra args added by #! scripts
- char* interp_name; // OUT: the interpreter name
- char* interp_args; // OUT: the args for the interpreter
-};
+typedef
+ struct {
+ HChar** argv; // IN: the original argv
+
+ Addr exe_base; // INOUT: lowest (allowed) address of exe
+ Addr exe_end; // INOUT: highest (allowed) address
+
+ Addr phdr; // OUT: address phdr was mapped at
+ Int phnum; // OUT: number of phdrs
+ Addr interp_base; // OUT: where interpreter (ld.so) was mapped
+ Addr entry; // OUT: entrypoint in main executable
+ Addr init_ip; // OUT: address of first instruction to execute
+ Addr brkbase; // OUT: base address of brk segment
+ Addr init_toc; // OUT: address of table-of-contents, on
+ // platforms for which that makes sense
+ // (ppc64-linux only)
+
+ // These are the extra args added by #! scripts
+ HChar* interp_name; // OUT: the interpreter name
+ HChar* interp_args; // OUT: the args for the interpreter
+ }
+ ExeInfo;
// Do a number of appropriate checks to see if the file looks executable by
// the kernel: ie. it's a file, it's readable and executable, and it's in
// either ELF or "#!" format. On success, 'out_fd' gets the fd of the file
// if it's non-NULL. Otherwise the fd is closed.
-extern SysRes VG_(pre_exec_check)(const Char* exe_name, Int* out_fd);
+extern SysRes VG_(pre_exec_check)(const HChar* exe_name, Int* out_fd);
// Does everything short of actually running 'exe': finds the file,
// checks execute permissions, sets up interpreter if program is a script,
// reads headers, maps file into memory, and returns important info about
// the program.
-extern Int VG_(do_exec)(const char *exe, struct exeinfo *info);
+extern Int VG_(do_exec)(const HChar* exe, ExeInfo* info);
/*------------------------------------------------------------*/
/*--- Finding and dealing with auxv ---*/