diff options
Diffstat (limited to 'coregrind/m_main.c')
-rw-r--r-- | coregrind/m_main.c | 215 |
1 files changed, 165 insertions, 50 deletions
diff --git a/coregrind/m_main.c b/coregrind/m_main.c index 9f98e11a7..1821c9412 100644 --- a/coregrind/m_main.c +++ b/coregrind/m_main.c @@ -7,7 +7,7 @@ This file is part of Valgrind, a dynamic binary instrumentation framework. - Copyright (C) 2000-2013 Julian Seward + Copyright (C) 2000-2015 Julian Seward jseward@acm.org This program is free software; you can redistribute it and/or @@ -133,11 +133,8 @@ static void usage_NORETURN ( Bool debug_help ) " load default suppressions [yes]\n" " --suppressions=<filename> suppress errors described in <filename>\n" " --gen-suppressions=no|yes|all print suppressions for errors? [no]\n" -" --db-attach=no|yes start debugger when errors detected? [no]\n" -" Note: deprecated feature\n" -" --db-command=<command> command to start debugger [%s -nw %%f %%p]\n" " --input-fd=<number> file descriptor for input [0=stdin]\n" -" --dsymutil=no|yes run dsymutil on Mac OS X when helpful? [no]\n" +" --dsymutil=no|yes run dsymutil on Mac OS X when helpful? [yes]\n" " --max-stackframe=<number> assume stack switch for SP changes larger\n" " than <number> bytes [2000000]\n" " --main-stacksize=<number> set size of main thread's stack (in bytes)\n" @@ -163,13 +160,13 @@ static void usage_NORETURN ( Bool debug_help ) " --allow-mismatched-debuginfo=no|yes [no]\n" " for the above two flags only, accept debuginfo\n" " objects that don't \"match\" the main object\n" -" --smc-check=none|stack|all|all-non-file [stack]\n" +" --smc-check=none|stack|all|all-non-file [all-non-file]\n" " checks for self-modifying code: none, only for\n" " code found in stacks, for all code, or for all\n" " code except that from file-backed mappings\n" " --read-inline-info=yes|no read debug info about inlined function calls\n" " and use it to do better stack traces. [yes]\n" -" on Linux/Android for Memcheck/Helgrind/DRD\n" +" on Linux/Android/Solaris for Memcheck/Helgrind/DRD\n" " only. [no] for all other tools and platforms.\n" " --read-var-info=yes|no read debug info on stack and global variables\n" " and use it to print better error messages in\n" @@ -181,7 +178,7 @@ static void usage_NORETURN ( Bool debug_help ) " --run-libc-freeres=no|yes free up glibc memory at exit on Linux? [yes]\n" " --sim-hints=hint1,hint2,... activate unusual sim behaviours [none] \n" " where hint is one of:\n" -" lax-ioctls fuse-compatible enable-outer\n" +" lax-ioctls lax-doors fuse-compatible enable-outer\n" " no-inner-prefix no-nptl-pthread-stackcache none\n" " --fair-sched=no|yes|try schedule threads fairly on multicore systems [no]\n" " --kernel-variant=variant1,variant2,...\n" @@ -295,13 +292,12 @@ static void usage_NORETURN ( Bool debug_help ) " Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n" "\n" " %s is %s\n" -" Valgrind is Copyright (C) 2000-2013, and GNU GPL'd, by Julian Seward et al.\n" -" LibVEX is Copyright (C) 2004-2013, and GNU GPL'd, by OpenWorks LLP et al.\n" +" Valgrind is Copyright (C) 2000-2015, and GNU GPL'd, by Julian Seward et al.\n" +" LibVEX is Copyright (C) 2004-2015, and GNU GPL'd, by OpenWorks LLP et al.\n" "\n" " Bug reports, feedback, admiration, abuse, etc, to: %s.\n" "\n"; - const HChar* gdb_path = GDB_PATH; HChar default_alignment[30]; // large enough HChar default_redzone_size[30]; // large enough @@ -319,7 +315,6 @@ static void usage_NORETURN ( Bool debug_help ) /* 'usage1' a type as described after each arg. */ VG_(printf)(usage1, VG_(clo_vgdb_error) /* int */, - gdb_path /* char* */, default_alignment /* char* */, default_redzone_size /* char* */, VG_(clo_vgdb_poll) /* int */, @@ -410,7 +405,7 @@ static void early_process_cmd_line_options ( /*OUT*/Int* need_help, // running in an outer, to have "no-inner-prefix" enabled // as early as possible. else if VG_USETX_CLO (str, "--sim-hints", - "lax-ioctls,fuse-compatible," + "lax-ioctls,lax-doors,fuse-compatible," "enable-outer,no-inner-prefix," "no-nptl-pthread-stackcache", VG_(clo_sim_hints)) {} @@ -617,7 +612,6 @@ void main_process_cmd_line_options ( /*OUT*/Bool* logging_to_fd, } else if VG_BOOL_CLO(arg, "--vgdb-shadow-registers", VG_(clo_vgdb_shadow_registers)) {} - else if VG_BOOL_CLO(arg, "--db-attach", VG_(clo_db_attach)) {} else if VG_BOOL_CLO(arg, "--demangle", VG_(clo_demangle)) {} else if VG_STR_CLO (arg, "--soname-synonyms",VG_(clo_soname_synonyms)) {} else if VG_BOOL_CLO(arg, "--error-limit", VG_(clo_error_limit)) {} @@ -682,7 +676,6 @@ void main_process_cmd_line_options ( /*OUT*/Bool* logging_to_fd, else if VG_BOOL_CLO(arg, "--trace-syscalls", VG_(clo_trace_syscalls)) {} else if VG_BOOL_CLO(arg, "--wait-for-gdb", VG_(clo_wait_for_gdb)) {} - else if VG_STR_CLO (arg, "--db-command", VG_(clo_db_command)) {} else if VG_BOOL_CLO(arg, "--sym-offsets", VG_(clo_sym_offsets)) {} else if VG_BOOL_CLO(arg, "--read-inline-info", VG_(clo_read_inline_info)) {} else if VG_BOOL_CLO(arg, "--read-var-info", VG_(clo_read_var_info)) {} @@ -902,11 +895,7 @@ void main_process_cmd_line_options ( /*OUT*/Bool* logging_to_fd, /* END command-line processing loop */ - /* Notify about deprecated features */ - if (VG_(clo_db_attach)) - VG_(umsg) - ("\nWarning: --db-attach is a deprecated feature which will be\n" - " removed in the next release. Use --vgdb-error=1 instead\n\n"); + /* Notify about deprecated features here. */ /* Determine the path prefix for vgdb */ if (VG_(clo_vgdb_prefix) == NULL) @@ -998,16 +987,6 @@ void main_process_cmd_line_options ( /*OUT*/Bool* logging_to_fd, "--gen-suppressions=yes.\n"); } - /* We can't allow DB attaching (or we maybe could, but results - could be chaotic ..) since it requires user input. Hence - disallow. */ - if (VG_(clo_db_attach)) { - VG_(fmsg_bad_option)( - "--xml=yes together with --db-attach=yes", - "--db-attach=yes is not allowed with --xml=yes\n" - "because it would require user input.\n"); - } - /* Disallow dump_error in XML mode; sounds like a recipe for chaos. No big deal; dump_error is a flag for debugging V itself. */ @@ -1443,7 +1422,7 @@ static void print_preamble ( Bool logging_to_fd, VG_(umsg)("\n"); if (VG_(clo_verbosity) > 1) { -# if !defined(VGO_darwin) +# if defined(VGO_linux) SysRes fd; # endif VexArch vex_arch; @@ -1457,7 +1436,7 @@ static void print_preamble ( Bool logging_to_fd, * (HChar**) VG_(indexXA)( VG_(args_for_valgrind), i )); } -# if !defined(VGO_darwin) +# if defined(VGO_linux) VG_(message)(Vg_DebugMsg, "Contents of /proc/version:\n"); fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 ); if (sr_isError(fd)) { @@ -1479,7 +1458,7 @@ static void print_preamble ( Bool logging_to_fd, VG_(message)(Vg_DebugMsg, "\n"); VG_(close)(fdno); } -# else +# elif defined(VGO_darwin) VG_(message)(Vg_DebugMsg, "Output from sysctl({CTL_KERN,KERN_VERSION}):\n"); /* Note: preferable to use sysctlbyname("kern.version", kernelVersion, &len, NULL, 0) however that syscall is OS X 10.10+ only. */ @@ -1490,6 +1469,20 @@ static void print_preamble ( Bool logging_to_fd, VG_(sysctl)(mib, sizeof(mib)/sizeof(Int), kernelVersion, &len, NULL, 0); VG_(message)(Vg_DebugMsg, " %s\n", kernelVersion); VG_(free)( kernelVersion ); +# elif defined(VGO_solaris) + /* There is no /proc/version file on Solaris so we try to get some + system information using the uname(2) syscall. */ + { + struct vki_utsname uts; + + VG_(message)(Vg_DebugMsg, "System information:\n"); + SysRes res = VG_(do_syscall1)(__NR_uname, (UWord)&uts); + if (sr_isError(res)) + VG_(message)(Vg_DebugMsg, " uname() failed\n"); + else + VG_(message)(Vg_DebugMsg, " %s %s %s %s\n", + uts.sysname, uts.release, uts.version, uts.machine); + } # endif VG_(machine_get_VexArchInfo)( &vex_arch, &vex_archinfo ); @@ -1539,8 +1532,8 @@ static void setup_file_descriptors(void) # endif if (show) - VG_(printf)("fd limits: host, before: cur %lu max %lu\n", - (UWord)rl.rlim_cur, (UWord)rl.rlim_max); + VG_(printf)("fd limits: host, before: cur %llu max %llu\n", + (ULong)rl.rlim_cur, (ULong)rl.rlim_max); /* Work out where to move the soft limit to. */ if (rl.rlim_cur + N_RESERVED_FDS <= rl.rlim_max) { @@ -1559,7 +1552,7 @@ static void setup_file_descriptors(void) if (show) { VG_(printf)("fd limits: host, after: cur %lu max %lu\n", (UWord)rl.rlim_cur, (UWord)rl.rlim_max); - VG_(printf)("fd limits: guest : cur %u max %u\n", + VG_(printf)("fd limits: guest : cur %d max %d\n", VG_(fd_soft_limit), VG_(fd_hard_limit)); } @@ -1945,7 +1938,7 @@ Int valgrind_main ( Int argc, HChar **argv, HChar **envp ) if (!need_help) { VG_(debugLog)(1, "main", "Create initial image\n"); -# if defined(VGO_linux) || defined(VGO_darwin) +# if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris) the_iicii.argv = argv; the_iicii.envp = envp; the_iicii.toolname = toolname; @@ -1978,16 +1971,21 @@ Int valgrind_main ( Int argc, HChar **argv, HChar **envp ) // p: setup file descriptors // p: ii_create_image for VG_(client_auxv) setup. //-------------------------------------------------------------- -#if !defined(VGO_linux) - // client shouldn't be using /proc! VG_(cl_cmdline_fd) = -1; VG_(cl_auxv_fd) = -1; -#else +#if defined(VGO_solaris) + VG_(cl_psinfo_fd) = -1; +#endif + +#if defined(VGO_linux) || defined(VGO_solaris) if (!need_help) { HChar buf[50]; // large enough HChar buf2[VG_(mkstemp_fullname_bufsz)(sizeof buf - 1)]; - HChar nul[1]; Int fd, r; + +#if defined(VGO_linux) || defined(SOLARIS_PROC_CMDLINE) + /* Fake /proc/<pid>/cmdline only on Linux and Solaris if supported. */ + HChar nul[1]; const HChar* exename; VG_(debugLog)(1, "main", "Create fake /proc/<pid>/cmdline\n"); @@ -2009,8 +2007,8 @@ Int valgrind_main ( Int argc, HChar **argv, HChar **envp ) } /* Don't bother to seek the file back to the start; instead do - it every time a copy of it is given out (by PRE(sys_open)). - That is probably more robust across fork() etc. */ + it every time a copy of it is given out (by PRE(sys_open) or + PRE(sys_openat)). That is probably more robust across fork() etc. */ /* Now delete it, but hang on to the fd. */ r = VG_(unlink)( buf2 ); @@ -2018,7 +2016,9 @@ Int valgrind_main ( Int argc, HChar **argv, HChar **envp ) VG_(err_config_error)("Can't delete client cmdline file in %s\n", buf2); VG_(cl_cmdline_fd) = fd; +#endif // defined(VGO_linux) || defined(SOLARIS_PROC_CMDLINE) + /* Fake /proc/<pid>/auxv on both Linux and Solaris. */ VG_(debugLog)(1, "main", "Create fake /proc/<pid>/auxv\n"); VG_(sprintf)(buf, "proc_%d_auxv", VG_(getpid)()); @@ -2047,6 +2047,24 @@ Int valgrind_main ( Int argc, HChar **argv, HChar **envp ) VG_(err_config_error)("Can't delete client auxv file in %s\n", buf2); VG_(cl_auxv_fd) = fd; + +#if defined(VGO_solaris) + /* Fake /proc/<pid>/psinfo on Solaris. + * Contents will be fetched and partially faked later on the fly. */ + VG_(debugLog)(1, "main", "Create fake /proc/<pid>/psinfo\n"); + + VG_(sprintf)(buf, "proc_%d_psinfo", VG_(getpid)()); + fd = VG_(mkstemp)( buf, buf2 ); + if (fd == -1) + VG_(err_config_error)("Can't create client psinfo file in %s\n", buf2); + + /* Now delete it, but hang on to the fd. */ + r = VG_(unlink)( buf2 ); + if (r) + VG_(err_config_error)("Can't delete client psinfo file in %s\n", buf2); + + VG_(cl_psinfo_fd) = fd; +#endif /* VGO_solaris */ } #endif @@ -2165,6 +2183,8 @@ Int valgrind_main ( Int argc, HChar **argv, HChar **envp ) iters = 10; # elif defined(VGO_darwin) iters = 3; +# elif defined(VGO_solaris) + iters = 10; # else # error "Unknown plat" # endif @@ -2183,6 +2203,10 @@ Int valgrind_main ( Int argc, HChar **argv, HChar **envp ) VG_(init_preopened_fds)(); } +#if defined(VGO_solaris) + VG_(syswrap_init)(); +#endif + //-------------------------------------------------------------- // Load debug info for the existing segments. // p: setup_code_redirect_table [so that redirs can be recorded] @@ -2207,7 +2231,7 @@ Int valgrind_main ( Int argc, HChar **argv, HChar **envp ) addr2dihandle = VG_(newXA)( VG_(malloc), "main.vm.2", VG_(free), sizeof(Addr_n_ULong) ); -# if defined(VGO_linux) +# if defined(VGO_linux) || defined(VGO_solaris) { Addr* seg_starts; Int n_seg_starts; Addr_n_ULong anu; @@ -2445,7 +2469,19 @@ Int valgrind_main ( Int argc, HChar **argv, HChar **envp ) // VG_(ii_create_image) [for 'the_iicii' initial info] //-------------------------------------------------------------- VG_(debugLog)(1, "main", "Finalise initial image\n"); - VG_(ii_finalise_image)( the_iifii ); + { /* Mark the main thread as running while we tell the tool about + the client memory which could be tracked during initial image + finalisation. So the tool can associate that memory with the + main thread. */ + vg_assert(VG_(running_tid) == VG_INVALID_THREADID); + VG_(running_tid) = tid_main; + + VG_(ii_finalise_image)( the_iifii ); + + /* Clear the running thread indicator */ + VG_(running_tid) = VG_INVALID_THREADID; + vg_assert(VG_(running_tid) == VG_INVALID_THREADID); + } //-------------------------------------------------------------- // Initialise the signal handling subsystem @@ -2662,10 +2698,10 @@ void shutdown_actions_NORETURN( ThreadId tid, sys_exit, do likewise; if the (last) thread stopped due to a fatal signal, terminate the entire system with that same fatal signal. */ VG_(debugLog)(1, "core_os", - "VG_(terminate_NORETURN)(tid=%lld)\n", (ULong)tid); + "VG_(terminate_NORETURN)(tid=%u)\n", tid); switch (tids_schedretcode) { - case VgSrc_ExitThread: /* the normal way out (Linux) */ + case VgSrc_ExitThread: /* the normal way out (Linux, Solaris) */ case VgSrc_ExitProcess: /* the normal way out (Darwin) */ /* Change the application return code to user's return code, if an error was found */ @@ -3431,13 +3467,92 @@ void _start_in_C_darwin ( UWord* pArgc ) VG_(exit)(r); } - +/*====================================================================*/ +/*=== Getting to main() alive: Solaris ===*/ +/*====================================================================*/ +#elif defined(VGO_solaris) +#if defined(VGP_x86_solaris) +/* The kernel hands control to _start, which extracts the initial stack + pointer and calls onwards to _start_in_C_solaris. This also switches to + the new stack. */ +asm("\n" + "\t.text\n" + "\t.globl _start\n" + "\t.type _start, @function\n" + "_start:\n" + /* Set up the new stack in %eax. */ + "\tmovl $vgPlain_interim_stack, %eax\n" + "\taddl $"VG_STRINGIFY(VG_STACK_GUARD_SZB)", %eax\n" + "\taddl $"VG_STRINGIFY(VG_DEFAULT_STACK_ACTIVE_SZB)", %eax\n" + "\tandl $~15, %eax\n" + /* Install it, and collect the original one. */ + "\txchgl %eax, %esp\n" + "\tsubl $12, %esp\n" /* Keep stack 16-byte aligned. */ + /* Call _start_in_C_solaris, passing it the startup %esp. */ + "\tpushl %eax\n" + "\tcall _start_in_C_solaris\n" + /* NOTREACHED */ + "\thlt\n" + "\t.previous\n" +); +#elif defined(VGP_amd64_solaris) +asm("\n" + ".text\n" + "\t.globl _start\n" + "\t.type _start, @function\n" + "_start:\n" + /* Set up the new stack in %rdi. */ + "\tmovq $vgPlain_interim_stack, %rdi\n" + "\taddq $"VG_STRINGIFY(VG_STACK_GUARD_SZB)", %rdi\n" + "\taddq $"VG_STRINGIFY(VG_DEFAULT_STACK_ACTIVE_SZB)", %rdi\n" + "\tandq $~15, %rdi\n" + /* Install it, and collect the original one. */ + "\txchgq %rdi, %rsp\n" + /* Call _start_in_C_solaris, passing it the startup %rsp. */ + "\tcall _start_in_C_solaris\n" + /* NOTREACHED */ + "\thlt\n" + ".previous\n" +); #else +# error "Unknown Solaris platform" +#endif + +void *memcpy(void *dest, const void *src, size_t n); +void *memcpy(void *dest, const void *src, size_t n) { + return VG_(memcpy)(dest, src, n); +} + +__attribute__ ((used)) +void _start_in_C_solaris ( UWord* pArgc ); +__attribute__ ((used)) +void _start_in_C_solaris ( UWord* pArgc ) +{ + Int r; + Word argc = pArgc[0]; + HChar** argv = (HChar**)&pArgc[1]; + HChar** envp = (HChar**)&pArgc[1 + argc + 1]; + + VG_(memset)( &the_iicii, 0, sizeof(the_iicii) ); + VG_(memset)( &the_iifii, 0, sizeof(the_iifii) ); + the_iicii.sp_at_startup = (Addr)pArgc; + + r = valgrind_main((Int)argc, argv, envp); + /* NOTREACHED */ + VG_(exit)(r); +} + +#else # error "Unknown OS" #endif +Addr VG_(get_initial_client_SP)( void ) +{ + return the_iifii.initial_client_SP; +} + /*====================================================================*/ /*=== {u,}{div,mod}di3 replacements ===*/ /*====================================================================*/ @@ -3864,9 +3979,9 @@ __fixunsdfdi(double a) /*=== Dummy _voucher_mach_msg_set for OSX 10.10 ===*/ /*====================================================================*/ -#if defined(VGO_darwin) && DARWIN_VERS == DARWIN_10_10 +#if defined(VGO_darwin) && DARWIN_VERS >= DARWIN_10_10 -/* Builds on MacOSX 10.10 seem to need this for some reason. */ +/* Builds on MacOSX 10.10+ seem to need this for some reason. */ /* extern boolean_t voucher_mach_msg_set(mach_msg_header_t *msg) __attribute__((weak_import)); I haven't a clue what the return value means, so just return 0. |