| sewardj | de4a1d0 | 2002-03-22 01:27:54 +0000 | [diff] [blame] | 1 |  | 
 | 2 | /*--------------------------------------------------------------------*/ | 
 | 3 | /*--- C startup stuff, reached from vg_startup.S.                  ---*/ | 
 | 4 | /*---                                                    vg_main.c ---*/ | 
 | 5 | /*--------------------------------------------------------------------*/ | 
 | 6 |  | 
 | 7 | /* | 
 | 8 |    This file is part of Valgrind, an x86 protected-mode emulator  | 
 | 9 |    designed for debugging and profiling binaries on x86-Unixes. | 
 | 10 |  | 
 | 11 |    Copyright (C) 2000-2002 Julian Seward  | 
 | 12 |       jseward@acm.org | 
 | 13 |       Julian_Seward@muraroa.demon.co.uk | 
 | 14 |  | 
 | 15 |    This program is free software; you can redistribute it and/or | 
 | 16 |    modify it under the terms of the GNU General Public License as | 
 | 17 |    published by the Free Software Foundation; either version 2 of the | 
 | 18 |    License, or (at your option) any later version. | 
 | 19 |  | 
 | 20 |    This program is distributed in the hope that it will be useful, but | 
 | 21 |    WITHOUT ANY WARRANTY; without even the implied warranty of | 
 | 22 |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
 | 23 |    General Public License for more details. | 
 | 24 |  | 
 | 25 |    You should have received a copy of the GNU General Public License | 
 | 26 |    along with this program; if not, write to the Free Software | 
 | 27 |    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | 
 | 28 |    02111-1307, USA. | 
 | 29 |  | 
 | 30 |    The GNU General Public License is contained in the file LICENSE. | 
 | 31 | */ | 
 | 32 |  | 
 | 33 | #include "vg_include.h" | 
 | 34 | #include "vg_constants.h" | 
| sewardj | de4a1d0 | 2002-03-22 01:27:54 +0000 | [diff] [blame] | 35 |  | 
 | 36 |  | 
 | 37 | /* --------------------------------------------------------------------- | 
 | 38 |    Compute offsets into baseBlock.  See comments in vg_include.h. | 
 | 39 |    ------------------------------------------------------------------ */ | 
 | 40 |  | 
 | 41 | /* The variables storing offsets. */ | 
 | 42 |  | 
 | 43 | #define INVALID_OFFSET (-1) | 
 | 44 |  | 
 | 45 | Int VGOFF_(m_eax) = INVALID_OFFSET; | 
 | 46 | Int VGOFF_(m_ecx) = INVALID_OFFSET; | 
 | 47 | Int VGOFF_(m_edx) = INVALID_OFFSET; | 
 | 48 | Int VGOFF_(m_ebx) = INVALID_OFFSET; | 
 | 49 | Int VGOFF_(m_esp) = INVALID_OFFSET; | 
 | 50 | Int VGOFF_(m_ebp) = INVALID_OFFSET; | 
 | 51 | Int VGOFF_(m_esi) = INVALID_OFFSET; | 
 | 52 | Int VGOFF_(m_edi) = INVALID_OFFSET; | 
 | 53 | Int VGOFF_(m_eflags) = INVALID_OFFSET; | 
 | 54 | Int VGOFF_(m_fpustate) = INVALID_OFFSET; | 
 | 55 | Int VGOFF_(m_eip) = INVALID_OFFSET; | 
 | 56 | Int VGOFF_(spillslots) = INVALID_OFFSET; | 
 | 57 | Int VGOFF_(sh_eax) = INVALID_OFFSET; | 
 | 58 | Int VGOFF_(sh_ecx) = INVALID_OFFSET; | 
 | 59 | Int VGOFF_(sh_edx) = INVALID_OFFSET; | 
 | 60 | Int VGOFF_(sh_ebx) = INVALID_OFFSET; | 
 | 61 | Int VGOFF_(sh_esp) = INVALID_OFFSET; | 
 | 62 | Int VGOFF_(sh_ebp) = INVALID_OFFSET; | 
 | 63 | Int VGOFF_(sh_esi) = INVALID_OFFSET; | 
 | 64 | Int VGOFF_(sh_edi) = INVALID_OFFSET; | 
 | 65 | Int VGOFF_(sh_eflags) = INVALID_OFFSET; | 
 | 66 | Int VGOFF_(helper_idiv_64_32) = INVALID_OFFSET; | 
 | 67 | Int VGOFF_(helper_div_64_32) = INVALID_OFFSET; | 
 | 68 | Int VGOFF_(helper_idiv_32_16) = INVALID_OFFSET; | 
 | 69 | Int VGOFF_(helper_div_32_16) = INVALID_OFFSET; | 
 | 70 | Int VGOFF_(helper_idiv_16_8) = INVALID_OFFSET; | 
 | 71 | Int VGOFF_(helper_div_16_8) = INVALID_OFFSET; | 
 | 72 | Int VGOFF_(helper_imul_32_64) = INVALID_OFFSET; | 
 | 73 | Int VGOFF_(helper_mul_32_64) = INVALID_OFFSET; | 
 | 74 | Int VGOFF_(helper_imul_16_32) = INVALID_OFFSET; | 
 | 75 | Int VGOFF_(helper_mul_16_32) = INVALID_OFFSET; | 
 | 76 | Int VGOFF_(helper_imul_8_16) = INVALID_OFFSET; | 
 | 77 | Int VGOFF_(helper_mul_8_16) = INVALID_OFFSET; | 
 | 78 | Int VGOFF_(helper_CLD) = INVALID_OFFSET; | 
 | 79 | Int VGOFF_(helper_STD) = INVALID_OFFSET; | 
 | 80 | Int VGOFF_(helper_get_dirflag) = INVALID_OFFSET; | 
 | 81 | Int VGOFF_(helper_shldl) = INVALID_OFFSET; | 
 | 82 | Int VGOFF_(helper_shldw) = INVALID_OFFSET; | 
 | 83 | Int VGOFF_(helper_shrdl) = INVALID_OFFSET; | 
 | 84 | Int VGOFF_(helper_shrdw) = INVALID_OFFSET; | 
 | 85 | Int VGOFF_(helper_RDTSC) = INVALID_OFFSET; | 
 | 86 | Int VGOFF_(helper_CPUID) = INVALID_OFFSET; | 
 | 87 | Int VGOFF_(helper_BSWAP) = INVALID_OFFSET; | 
 | 88 | Int VGOFF_(helper_bt) = INVALID_OFFSET; | 
 | 89 | Int VGOFF_(helper_bts) = INVALID_OFFSET; | 
 | 90 | Int VGOFF_(helper_btr) = INVALID_OFFSET; | 
 | 91 | Int VGOFF_(helper_btc) = INVALID_OFFSET; | 
 | 92 | Int VGOFF_(helper_bsf) = INVALID_OFFSET; | 
 | 93 | Int VGOFF_(helper_bsr) = INVALID_OFFSET; | 
 | 94 | Int VGOFF_(helper_fstsw_AX) = INVALID_OFFSET; | 
 | 95 | Int VGOFF_(helper_SAHF) = INVALID_OFFSET; | 
| sewardj | 4d0ab1f | 2002-03-24 10:00:09 +0000 | [diff] [blame] | 96 | Int VGOFF_(helper_DAS) = INVALID_OFFSET; | 
| sewardj | fe8a166 | 2002-03-24 11:54:07 +0000 | [diff] [blame] | 97 | Int VGOFF_(helper_DAA) = INVALID_OFFSET; | 
| sewardj | de4a1d0 | 2002-03-22 01:27:54 +0000 | [diff] [blame] | 98 | Int VGOFF_(helper_value_check4_fail) = INVALID_OFFSET; | 
 | 99 | Int VGOFF_(helper_value_check2_fail) = INVALID_OFFSET; | 
 | 100 | Int VGOFF_(helper_value_check1_fail) = INVALID_OFFSET; | 
 | 101 | Int VGOFF_(helper_value_check0_fail) = INVALID_OFFSET; | 
| sewardj | de4a1d0 | 2002-03-22 01:27:54 +0000 | [diff] [blame] | 102 | Int VGOFF_(helperc_LOADV4) = INVALID_OFFSET; | 
 | 103 | Int VGOFF_(helperc_LOADV2) = INVALID_OFFSET; | 
 | 104 | Int VGOFF_(helperc_LOADV1) = INVALID_OFFSET; | 
 | 105 | Int VGOFF_(helperc_STOREV4) = INVALID_OFFSET; | 
 | 106 | Int VGOFF_(helperc_STOREV2) = INVALID_OFFSET; | 
 | 107 | Int VGOFF_(helperc_STOREV1) = INVALID_OFFSET; | 
 | 108 | Int VGOFF_(handle_esp_assignment) = INVALID_OFFSET; | 
 | 109 | Int VGOFF_(fpu_write_check) = INVALID_OFFSET; | 
 | 110 | Int VGOFF_(fpu_read_check) = INVALID_OFFSET; | 
| sewardj | de4a1d0 | 2002-03-22 01:27:54 +0000 | [diff] [blame] | 111 |  | 
 | 112 |  | 
 | 113 | /* This is the actual defn of baseblock. */ | 
 | 114 | UInt VG_(baseBlock)[VG_BASEBLOCK_WORDS]; | 
 | 115 |  | 
 | 116 | /* Words. */ | 
 | 117 | static Int baB_off = 0; | 
 | 118 |  | 
 | 119 | /* Returns the offset, in words. */ | 
 | 120 | static Int alloc_BaB ( Int words ) | 
 | 121 | { | 
 | 122 |    Int off = baB_off; | 
 | 123 |    baB_off += words; | 
 | 124 |    if (baB_off >= VG_BASEBLOCK_WORDS) | 
 | 125 |       VG_(panic)( "alloc_BaB: baseBlock is too small"); | 
 | 126 |  | 
 | 127 |    return off;    | 
 | 128 | } | 
 | 129 |  | 
 | 130 | /* Allocate 1 word in baseBlock and set it to the given value. */ | 
 | 131 | static Int alloc_BaB_1_set ( Addr a ) | 
 | 132 | { | 
 | 133 |    Int off = alloc_BaB(1); | 
 | 134 |    VG_(baseBlock)[off] = (UInt)a; | 
 | 135 |    return off; | 
 | 136 | } | 
 | 137 |  | 
 | 138 |  | 
 | 139 | /* Here we assign actual offsets.  It's important to get the most | 
 | 140 |    popular referents within 128 bytes of the start, so we can take | 
 | 141 |    advantage of short addressing modes relative to %ebp.  Popularity | 
 | 142 |    of offsets was measured on 22 Feb 02 running a KDE application, and | 
 | 143 |    the slots rearranged accordingly, with a 1.5% reduction in total | 
 | 144 |    size of translations. */ | 
 | 145 |  | 
 | 146 | static void vg_init_baseBlock ( void ) | 
 | 147 | { | 
 | 148 |    baB_off = 0; | 
 | 149 |  | 
 | 150 |    /* Those with offsets under 128 are carefully chosen. */ | 
 | 151 |  | 
 | 152 |    /* WORD offsets in this column */ | 
 | 153 |    /* 0   */ VGOFF_(m_eax)     = alloc_BaB(1); | 
 | 154 |    /* 1   */ VGOFF_(m_ecx)     = alloc_BaB(1); | 
 | 155 |    /* 2   */ VGOFF_(m_edx)     = alloc_BaB(1); | 
 | 156 |    /* 3   */ VGOFF_(m_ebx)     = alloc_BaB(1); | 
 | 157 |    /* 4   */ VGOFF_(m_esp)     = alloc_BaB(1); | 
 | 158 |    /* 5   */ VGOFF_(m_ebp)     = alloc_BaB(1); | 
 | 159 |    /* 6   */ VGOFF_(m_esi)     = alloc_BaB(1); | 
 | 160 |    /* 7   */ VGOFF_(m_edi)     = alloc_BaB(1); | 
 | 161 |    /* 8   */ VGOFF_(m_eflags)  = alloc_BaB(1); | 
 | 162 |  | 
 | 163 |    /* 9   */ VGOFF_(sh_eax)    = alloc_BaB(1); | 
 | 164 |    /* 10  */ VGOFF_(sh_ecx)    = alloc_BaB(1); | 
 | 165 |    /* 11  */ VGOFF_(sh_edx)    = alloc_BaB(1); | 
 | 166 |    /* 12  */ VGOFF_(sh_ebx)    = alloc_BaB(1); | 
 | 167 |    /* 13  */ VGOFF_(sh_esp)    = alloc_BaB(1); | 
 | 168 |    /* 14  */ VGOFF_(sh_ebp)    = alloc_BaB(1); | 
 | 169 |    /* 15  */ VGOFF_(sh_esi)    = alloc_BaB(1); | 
 | 170 |    /* 16  */ VGOFF_(sh_edi)    = alloc_BaB(1); | 
 | 171 |    /* 17  */ VGOFF_(sh_eflags) = alloc_BaB(1); | 
 | 172 |  | 
 | 173 |    /* 18  */  | 
 | 174 |    VGOFF_(helper_value_check4_fail)  | 
 | 175 |       = alloc_BaB_1_set( (Addr) & VG_(helper_value_check4_fail) ); | 
 | 176 |    /* 19 */ | 
 | 177 |    VGOFF_(helper_value_check0_fail) | 
 | 178 |       = alloc_BaB_1_set( (Addr) & VG_(helper_value_check0_fail) ); | 
 | 179 |  | 
 | 180 |    /* 20  */ | 
 | 181 |    VGOFF_(helperc_STOREV4) | 
 | 182 |       = alloc_BaB_1_set( (Addr) & VG_(helperc_STOREV4) ); | 
 | 183 |    /* 21  */ | 
 | 184 |    VGOFF_(helperc_STOREV1) | 
 | 185 |       = alloc_BaB_1_set( (Addr) & VG_(helperc_STOREV1) ); | 
 | 186 |  | 
 | 187 |    /* 22  */ | 
 | 188 |    VGOFF_(helperc_LOADV4) | 
 | 189 |       = alloc_BaB_1_set( (Addr) & VG_(helperc_LOADV4) ); | 
 | 190 |    /* 23  */ | 
 | 191 |    VGOFF_(helperc_LOADV1) | 
 | 192 |       = alloc_BaB_1_set( (Addr) & VG_(helperc_LOADV1) ); | 
 | 193 |  | 
 | 194 |    /* 24  */ | 
 | 195 |    VGOFF_(handle_esp_assignment) | 
 | 196 |       = alloc_BaB_1_set( (Addr) & VGM_(handle_esp_assignment) ); | 
 | 197 |  | 
 | 198 |    /* 25 */ | 
 | 199 |    VGOFF_(m_eip) = alloc_BaB(1); | 
 | 200 |  | 
 | 201 |    /* There are currently 24 spill slots */ | 
 | 202 |    /* 26 .. 49  This overlaps the magic boundary at >= 32 words, but | 
 | 203 |       most spills are to low numbered spill slots, so the ones above | 
 | 204 |       the boundary don't see much action. */ | 
 | 205 |    VGOFF_(spillslots) = alloc_BaB(VG_MAX_SPILLSLOTS); | 
 | 206 |  | 
 | 207 |    /* These two pushed beyond the boundary because 2-byte transactions | 
 | 208 |       are rare. */ | 
 | 209 |    /* 50  */ | 
 | 210 |    VGOFF_(helperc_STOREV2) | 
 | 211 |       = alloc_BaB_1_set( (Addr) & VG_(helperc_STOREV2) ); | 
 | 212 |    /* 51  */ | 
 | 213 |    VGOFF_(helperc_LOADV2) | 
 | 214 |       = alloc_BaB_1_set( (Addr) & VG_(helperc_LOADV2) ); | 
 | 215 |  | 
 | 216 |    /* 52  */ | 
 | 217 |    VGOFF_(fpu_write_check) | 
 | 218 |       = alloc_BaB_1_set( (Addr) & VGM_(fpu_write_check) ); | 
 | 219 |    /* 53  */ | 
 | 220 |    VGOFF_(fpu_read_check) | 
 | 221 |       = alloc_BaB_1_set( (Addr) & VGM_(fpu_read_check) ); | 
 | 222 |  | 
 | 223 |    /* Actually I don't think these two are ever used. */ | 
 | 224 |    /* 54  */  | 
 | 225 |    VGOFF_(helper_value_check2_fail) | 
 | 226 |       = alloc_BaB_1_set( (Addr) & VG_(helper_value_check2_fail) ); | 
 | 227 |    /* 55  */  | 
 | 228 |    VGOFF_(helper_value_check1_fail) | 
 | 229 |       = alloc_BaB_1_set( (Addr) & VG_(helper_value_check1_fail) ); | 
 | 230 |  | 
 | 231 |    /* I gave up counting at this point.  Since they're way above the | 
 | 232 |       short-amode-boundary, there's no point. */ | 
 | 233 |  | 
 | 234 |    VGOFF_(m_fpustate) = alloc_BaB(VG_SIZE_OF_FPUSTATE_W); | 
 | 235 |  | 
 | 236 |    VGOFF_(helper_idiv_64_32) | 
 | 237 |       = alloc_BaB_1_set( (Addr) & VG_(helper_idiv_64_32) ); | 
 | 238 |    VGOFF_(helper_div_64_32) | 
 | 239 |       = alloc_BaB_1_set( (Addr) & VG_(helper_div_64_32) ); | 
 | 240 |    VGOFF_(helper_idiv_32_16) | 
 | 241 |       = alloc_BaB_1_set( (Addr) & VG_(helper_idiv_32_16) ); | 
 | 242 |    VGOFF_(helper_div_32_16) | 
 | 243 |       = alloc_BaB_1_set( (Addr) & VG_(helper_div_32_16) ); | 
 | 244 |    VGOFF_(helper_idiv_16_8) | 
 | 245 |       = alloc_BaB_1_set( (Addr) & VG_(helper_idiv_16_8) ); | 
 | 246 |    VGOFF_(helper_div_16_8) | 
 | 247 |       = alloc_BaB_1_set( (Addr) & VG_(helper_div_16_8) ); | 
 | 248 |  | 
 | 249 |    VGOFF_(helper_imul_32_64) | 
 | 250 |       = alloc_BaB_1_set( (Addr) & VG_(helper_imul_32_64) ); | 
 | 251 |    VGOFF_(helper_mul_32_64) | 
 | 252 |       = alloc_BaB_1_set( (Addr) & VG_(helper_mul_32_64) ); | 
 | 253 |    VGOFF_(helper_imul_16_32) | 
 | 254 |       = alloc_BaB_1_set( (Addr) & VG_(helper_imul_16_32) ); | 
 | 255 |    VGOFF_(helper_mul_16_32) | 
 | 256 |       = alloc_BaB_1_set( (Addr) & VG_(helper_mul_16_32) ); | 
 | 257 |    VGOFF_(helper_imul_8_16) | 
 | 258 |       = alloc_BaB_1_set( (Addr) & VG_(helper_imul_8_16) ); | 
 | 259 |    VGOFF_(helper_mul_8_16) | 
 | 260 |       = alloc_BaB_1_set( (Addr) & VG_(helper_mul_8_16) ); | 
 | 261 |  | 
 | 262 |    VGOFF_(helper_CLD) | 
 | 263 |       = alloc_BaB_1_set( (Addr) & VG_(helper_CLD) ); | 
 | 264 |    VGOFF_(helper_STD) | 
 | 265 |       = alloc_BaB_1_set( (Addr) & VG_(helper_STD) ); | 
 | 266 |    VGOFF_(helper_get_dirflag) | 
 | 267 |       = alloc_BaB_1_set( (Addr) & VG_(helper_get_dirflag) ); | 
 | 268 |  | 
 | 269 |    VGOFF_(helper_shldl) | 
 | 270 |       = alloc_BaB_1_set( (Addr) & VG_(helper_shldl) ); | 
 | 271 |    VGOFF_(helper_shldw) | 
 | 272 |       = alloc_BaB_1_set( (Addr) & VG_(helper_shldw) ); | 
 | 273 |    VGOFF_(helper_shrdl) | 
 | 274 |       = alloc_BaB_1_set( (Addr) & VG_(helper_shrdl) ); | 
 | 275 |    VGOFF_(helper_shrdw) | 
 | 276 |       = alloc_BaB_1_set( (Addr) & VG_(helper_shrdw) ); | 
 | 277 |  | 
 | 278 |    VGOFF_(helper_RDTSC) | 
 | 279 |       = alloc_BaB_1_set( (Addr) & VG_(helper_RDTSC) ); | 
 | 280 |    VGOFF_(helper_CPUID) | 
 | 281 |       = alloc_BaB_1_set( (Addr) & VG_(helper_CPUID) ); | 
 | 282 |  | 
 | 283 |    VGOFF_(helper_bt) | 
 | 284 |       = alloc_BaB_1_set( (Addr) & VG_(helper_bt) ); | 
 | 285 |    VGOFF_(helper_bts) | 
 | 286 |       = alloc_BaB_1_set( (Addr) & VG_(helper_bts) ); | 
 | 287 |    VGOFF_(helper_btr) | 
 | 288 |       = alloc_BaB_1_set( (Addr) & VG_(helper_btr) ); | 
 | 289 |    VGOFF_(helper_btc) | 
 | 290 |       = alloc_BaB_1_set( (Addr) & VG_(helper_btc) ); | 
 | 291 |  | 
 | 292 |    VGOFF_(helper_bsf) | 
 | 293 |       = alloc_BaB_1_set( (Addr) & VG_(helper_bsf) ); | 
 | 294 |    VGOFF_(helper_bsr) | 
 | 295 |       = alloc_BaB_1_set( (Addr) & VG_(helper_bsr) ); | 
 | 296 |  | 
 | 297 |    VGOFF_(helper_fstsw_AX) | 
 | 298 |       = alloc_BaB_1_set( (Addr) & VG_(helper_fstsw_AX) ); | 
 | 299 |    VGOFF_(helper_SAHF) | 
 | 300 |       = alloc_BaB_1_set( (Addr) & VG_(helper_SAHF) ); | 
| sewardj | 4d0ab1f | 2002-03-24 10:00:09 +0000 | [diff] [blame] | 301 |    VGOFF_(helper_DAS) | 
 | 302 |       = alloc_BaB_1_set( (Addr) & VG_(helper_DAS) ); | 
| sewardj | fe8a166 | 2002-03-24 11:54:07 +0000 | [diff] [blame] | 303 |    VGOFF_(helper_DAA) | 
 | 304 |       = alloc_BaB_1_set( (Addr) & VG_(helper_DAA) ); | 
| sewardj | de4a1d0 | 2002-03-22 01:27:54 +0000 | [diff] [blame] | 305 | } | 
 | 306 |  | 
 | 307 |  | 
 | 308 | /* --------------------------------------------------------------------- | 
 | 309 |    Global entities which are not referenced from generated code. | 
 | 310 |    ------------------------------------------------------------------ */ | 
 | 311 |  | 
 | 312 | /* The stack on which Valgrind runs.  We can't use the same stack as | 
 | 313 |    the simulatee -- that's an important design decision.  */ | 
 | 314 | UInt VG_(stack)[10000]; | 
 | 315 |  | 
 | 316 | /* Ditto our signal delivery stack. */ | 
 | 317 | UInt VG_(sigstack)[10000]; | 
 | 318 |  | 
 | 319 | /* Saving stuff across system calls. */ | 
 | 320 | UInt VG_(real_fpu_state_saved_over_syscall_d1)[VG_SIZE_OF_FPUSTATE_W]; | 
 | 321 | UInt VG_(real_fpu_state_saved_over_syscall_d2)[VG_SIZE_OF_FPUSTATE_W]; | 
 | 322 | Addr VG_(esp_saved_over_syscall_d1); | 
 | 323 | Addr VG_(esp_saved_over_syscall_d2); | 
 | 324 |  | 
 | 325 | /* Counts downwards in vg_run_innerloop. */ | 
 | 326 | UInt VG_(dispatch_ctr); | 
 | 327 |  | 
| sewardj | de4a1d0 | 2002-03-22 01:27:54 +0000 | [diff] [blame] | 328 |  | 
 | 329 | /* 64-bit counter for the number of basic blocks done. */ | 
 | 330 | ULong VG_(bbs_done); | 
 | 331 | /* 64-bit counter for the number of bbs to go before a debug exit. */ | 
 | 332 | ULong VG_(bbs_to_go); | 
 | 333 |  | 
 | 334 | /* Produce debugging output? */ | 
 | 335 | Bool VG_(disassemble) = False; | 
 | 336 |  | 
 | 337 | /* The current LRU epoch. */ | 
 | 338 | UInt VG_(current_epoch) = 0; | 
 | 339 |  | 
 | 340 |  | 
 | 341 | /* --------------------------------------------------------------------- | 
 | 342 |    Counters, for informational purposes only. | 
 | 343 |    ------------------------------------------------------------------ */ | 
 | 344 |  | 
 | 345 | /* Number of lookups which miss the fast tt helper. */ | 
 | 346 | UInt VG_(tt_fast_misses) = 0; | 
 | 347 |  | 
 | 348 |  | 
 | 349 | /* Counts for LRU informational messages. */ | 
 | 350 |  | 
 | 351 | /* Number and total o/t size of new translations this epoch. */ | 
 | 352 | UInt VG_(this_epoch_in_count) = 0; | 
 | 353 | UInt VG_(this_epoch_in_osize) = 0; | 
 | 354 | UInt VG_(this_epoch_in_tsize) = 0; | 
 | 355 | /* Number and total o/t size of discarded translations this epoch. */ | 
 | 356 | UInt VG_(this_epoch_out_count) = 0; | 
 | 357 | UInt VG_(this_epoch_out_osize) = 0; | 
 | 358 | UInt VG_(this_epoch_out_tsize) = 0; | 
 | 359 | /* Number and total o/t size of translations overall. */ | 
 | 360 | UInt VG_(overall_in_count) = 0; | 
 | 361 | UInt VG_(overall_in_osize) = 0; | 
 | 362 | UInt VG_(overall_in_tsize) = 0; | 
 | 363 | /* Number and total o/t size of discards overall. */ | 
 | 364 | UInt VG_(overall_out_count) = 0; | 
 | 365 | UInt VG_(overall_out_osize) = 0; | 
 | 366 | UInt VG_(overall_out_tsize) = 0; | 
 | 367 |  | 
 | 368 | /* The number of LRU-clearings of TT/TC. */ | 
 | 369 | UInt VG_(number_of_lrus) = 0; | 
 | 370 |  | 
 | 371 |  | 
 | 372 | /* Counts pertaining to the register allocator. */ | 
 | 373 |  | 
 | 374 | /* total number of uinstrs input to reg-alloc */ | 
 | 375 | UInt VG_(uinstrs_prealloc) = 0; | 
 | 376 |  | 
 | 377 | /* total number of uinstrs added due to spill code */ | 
 | 378 | UInt VG_(uinstrs_spill) = 0; | 
 | 379 |  | 
 | 380 | /* number of bbs requiring spill code */ | 
 | 381 | UInt VG_(translations_needing_spill) = 0; | 
 | 382 |  | 
 | 383 | /* total of register ranks over all translations */ | 
 | 384 | UInt VG_(total_reg_rank) = 0; | 
 | 385 |  | 
 | 386 |  | 
 | 387 | /* Counts pertaining to the self-modifying-code detection machinery. */ | 
 | 388 |  | 
 | 389 | /* Total number of writes checked. */ | 
 | 390 | UInt VG_(smc_total_check4s) = 0; | 
 | 391 |  | 
 | 392 | /* Number of writes which the fast smc check couldn't show were | 
 | 393 |    harmless. */ | 
 | 394 | UInt VG_(smc_cache_passed) = 0; | 
 | 395 |  | 
 | 396 | /* Numnber of writes which really did write on original code. */ | 
 | 397 | UInt VG_(smc_fancy_passed) = 0; | 
 | 398 |  | 
 | 399 | /* Number of translations discarded as a result. */ | 
 | 400 | UInt VG_(smc_discard_count) = 0; | 
 | 401 |  | 
 | 402 |  | 
 | 403 | /* Counts pertaining to internal sanity checking. */ | 
| sewardj | de4a1d0 | 2002-03-22 01:27:54 +0000 | [diff] [blame] | 404 | UInt VG_(sanity_fast_count) = 0; | 
 | 405 | UInt VG_(sanity_slow_count) = 0; | 
 | 406 |  | 
| sewardj | 2e93c50 | 2002-04-12 11:12:52 +0000 | [diff] [blame^] | 407 | /* Counts pertaining to the scheduler. */ | 
 | 408 | UInt VG_(num_scheduling_events_MINOR) = 0; | 
 | 409 | UInt VG_(num_scheduling_events_MAJOR) = 0; | 
| sewardj | de4a1d0 | 2002-03-22 01:27:54 +0000 | [diff] [blame] | 410 |  | 
 | 411 |  | 
 | 412 | /* --------------------------------------------------------------------- | 
 | 413 |    Values derived from command-line options. | 
 | 414 |    ------------------------------------------------------------------ */ | 
 | 415 |  | 
| sewardj | 97ced73 | 2002-03-25 00:07:36 +0000 | [diff] [blame] | 416 | Bool   VG_(clo_check_addrVs); | 
| sewardj | de4a1d0 | 2002-03-22 01:27:54 +0000 | [diff] [blame] | 417 | Bool   VG_(clo_GDB_attach); | 
 | 418 | Int    VG_(sanity_level); | 
 | 419 | Int    VG_(clo_verbosity); | 
 | 420 | Bool   VG_(clo_demangle); | 
 | 421 | Bool   VG_(clo_leak_check); | 
 | 422 | Bool   VG_(clo_show_reachable); | 
 | 423 | Int    VG_(clo_leak_resolution); | 
 | 424 | Bool   VG_(clo_sloppy_malloc); | 
 | 425 | Bool   VG_(clo_partial_loads_ok); | 
 | 426 | Bool   VG_(clo_trace_children); | 
 | 427 | Int    VG_(clo_logfile_fd); | 
 | 428 | Int    VG_(clo_freelist_vol); | 
 | 429 | Bool   VG_(clo_workaround_gcc296_bugs); | 
 | 430 | Int    VG_(clo_n_suppressions); | 
 | 431 | Char*  VG_(clo_suppressions)[VG_CLO_MAX_SFILES]; | 
 | 432 | Bool   VG_(clo_single_step); | 
 | 433 | Bool   VG_(clo_optimise); | 
 | 434 | Bool   VG_(clo_instrument); | 
 | 435 | Bool   VG_(clo_cleanup); | 
 | 436 | Bool   VG_(clo_client_perms); | 
 | 437 | Int    VG_(clo_smc_check); | 
 | 438 | Bool   VG_(clo_trace_syscalls); | 
 | 439 | Bool   VG_(clo_trace_signals); | 
 | 440 | Bool   VG_(clo_trace_symtab); | 
 | 441 | Bool   VG_(clo_trace_malloc); | 
 | 442 | ULong  VG_(clo_stop_after); | 
 | 443 | Int    VG_(clo_dump_error); | 
 | 444 | Int    VG_(clo_backtrace_size); | 
 | 445 |  | 
 | 446 | /* This Bool is needed by wrappers in vg_clientmalloc.c to decide how | 
 | 447 |    to behave.  Initially we say False. */ | 
 | 448 | Bool VG_(running_on_simd_CPU) = False; | 
 | 449 |  | 
 | 450 | /* Holds client's %esp at the point we gained control. */ | 
 | 451 | Addr VG_(esp_at_startup); | 
 | 452 |  | 
 | 453 | /* As deduced from VG_(esp_at_startup), the client's argc, argv[] and | 
 | 454 |    envp[] as extracted from the client's stack at startup-time. */ | 
 | 455 | Int    VG_(client_argc); | 
 | 456 | Char** VG_(client_argv); | 
 | 457 | Char** VG_(client_envp); | 
 | 458 |  | 
 | 459 | /* A place into which to copy the value of env var VG_ARGS, so we | 
 | 460 |    don't have to modify the original. */ | 
 | 461 | static Char vg_cmdline_copy[M_VG_CMDLINE_STRLEN]; | 
 | 462 |  | 
 | 463 |  | 
 | 464 | /* --------------------------------------------------------------------- | 
| sewardj | de4a1d0 | 2002-03-22 01:27:54 +0000 | [diff] [blame] | 465 |    Processing of command-line options. | 
 | 466 |    ------------------------------------------------------------------ */ | 
 | 467 |  | 
 | 468 | static void bad_option ( Char* opt ) | 
 | 469 | { | 
 | 470 |    VG_(shutdown_logging)(); | 
 | 471 |    VG_(clo_logfile_fd) = 2; /* stderr */ | 
 | 472 |    VG_(printf)("valgrind.so: Bad option `%s'; aborting.\n", opt); | 
 | 473 |    VG_(exit)(1); | 
 | 474 | } | 
 | 475 |  | 
 | 476 | static void config_error ( Char* msg ) | 
 | 477 | { | 
 | 478 |    VG_(shutdown_logging)(); | 
 | 479 |    VG_(clo_logfile_fd) = 2; /* stderr */ | 
 | 480 |    VG_(printf)("valgrind.so: Startup or configuration error:\n\t%s\n", msg); | 
 | 481 |    VG_(printf)("valgrind.so: Unable to start up properly.  Giving up.\n"); | 
 | 482 |    VG_(exit)(1); | 
 | 483 | } | 
 | 484 |  | 
 | 485 |  | 
 | 486 | static void process_cmd_line_options ( void ) | 
 | 487 | { | 
 | 488 |    UChar* argv[M_VG_CMDLINE_OPTS]; | 
 | 489 |    UInt   argc; | 
 | 490 |    UChar* p; | 
 | 491 |    UChar* str; | 
 | 492 |    Int    i, eventually_logfile_fd; | 
 | 493 |  | 
 | 494 | #  define ISSPACE(cc)      ((cc) == ' ' || (cc) == '\t' || (cc) == '\n') | 
 | 495 | #  define STREQ(s1,s2)     (0==VG_(strcmp_ws)((s1),(s2))) | 
 | 496 | #  define STREQN(nn,s1,s2) (0==VG_(strncmp_ws)((s1),(s2),(nn))) | 
 | 497 |  | 
 | 498 |    /* Set defaults. */ | 
| sewardj | 97ced73 | 2002-03-25 00:07:36 +0000 | [diff] [blame] | 499 |    VG_(clo_check_addrVs)     = True; | 
| sewardj | de4a1d0 | 2002-03-22 01:27:54 +0000 | [diff] [blame] | 500 |    VG_(clo_GDB_attach)       = False; | 
 | 501 |    VG_(sanity_level)         = 1; | 
 | 502 |    VG_(clo_verbosity)        = 1; | 
 | 503 |    VG_(clo_demangle)         = True; | 
 | 504 |    VG_(clo_leak_check)       = False; | 
 | 505 |    VG_(clo_show_reachable)   = False; | 
 | 506 |    VG_(clo_leak_resolution)  = 2; | 
 | 507 |    VG_(clo_sloppy_malloc)    = False; | 
 | 508 |    VG_(clo_partial_loads_ok) = True; | 
 | 509 |    VG_(clo_trace_children)   = False; | 
 | 510 |    VG_(clo_logfile_fd)       = 2; /* stderr */ | 
 | 511 |    VG_(clo_freelist_vol)     = 1000000; | 
 | 512 |    VG_(clo_workaround_gcc296_bugs) = False; | 
 | 513 |    VG_(clo_n_suppressions)   = 0; | 
 | 514 |    VG_(clo_single_step)      = False; | 
 | 515 |    VG_(clo_optimise)         = True; | 
 | 516 |    VG_(clo_instrument)       = True; | 
 | 517 |    VG_(clo_cleanup)          = True; | 
| sewardj | 2e93c50 | 2002-04-12 11:12:52 +0000 | [diff] [blame^] | 518 |    VG_(clo_client_perms)     = True; | 
| sewardj | de4a1d0 | 2002-03-22 01:27:54 +0000 | [diff] [blame] | 519 |    VG_(clo_smc_check)        = /* VG_CLO_SMC_SOME */ VG_CLO_SMC_NONE; | 
 | 520 |    VG_(clo_trace_syscalls)   = False; | 
 | 521 |    VG_(clo_trace_signals)    = False; | 
 | 522 |    VG_(clo_trace_symtab)     = False; | 
 | 523 |    VG_(clo_trace_malloc)     = False; | 
 | 524 |    VG_(clo_stop_after)       = 1000000000000LL; | 
 | 525 |    VG_(clo_dump_error)       = 0; | 
 | 526 |    VG_(clo_backtrace_size)   = 4; | 
 | 527 |  | 
 | 528 |    eventually_logfile_fd = VG_(clo_logfile_fd); | 
 | 529 |  | 
 | 530 |    /* Once logging is started, we can safely send messages pertaining | 
 | 531 |       to failures in initialisation. */ | 
 | 532 |    VG_(startup_logging)(); | 
 | 533 |  | 
 | 534 |    /* Magically find the client's argc/argv/envp.  This kludge is | 
 | 535 |       entirely dependent on the stack layout imposed by libc at | 
 | 536 |       startup.  Hence the magic offsets.  Then check (heuristically) | 
 | 537 |       that the results are plausible.  There must be a better way to | 
 | 538 |       do this ... */ | 
 | 539 |  | 
 | 540 | #  if 0 | 
 | 541 |    /* Use this to search for the correct offsets if the tests below | 
 | 542 |       barf. */ | 
 | 543 |    { Int i; | 
 | 544 |      VG_(printf)("startup %%esp is %p\n", VG_(esp_at_startup) ); | 
 | 545 |      for (i = 0; i < 10; i++) { | 
 | 546 |         Char* p = ((Char**)VG_(esp_at_startup))[i]; | 
 | 547 |         VG_(printf)("%d:  %p\n", i, p); | 
 | 548 |      } | 
 | 549 |    } | 
 | 550 | #  endif | 
 | 551 |  | 
| sewardj | a88ebf6 | 2002-03-24 12:22:39 +0000 | [diff] [blame] | 552 | #  if defined(GLIBC_2_2) | 
| sewardj | de4a1d0 | 2002-03-22 01:27:54 +0000 | [diff] [blame] | 553 |    /* These offsets (5,6,7) are right for my RedHat 7.2 (glibc-2.2.4) | 
 | 554 |       box. */ | 
 | 555 |  | 
 | 556 |    VG_(client_argc) = (Int)   ( ((void**)VG_(esp_at_startup)) [5] ); | 
 | 557 |    VG_(client_argv) = (Char**)( ((void**)VG_(esp_at_startup)) [6] ); | 
 | 558 |    VG_(client_envp) = (Char**)( ((void**)VG_(esp_at_startup)) [7] ); | 
 | 559 |  | 
 | 560 |    if ( ((UInt)VG_(client_argc)) > 0 && | 
 | 561 |         ((UInt)VG_(client_argc)) < 10000 && | 
 | 562 |         (Addr)VG_(client_argv) >= 0x8000000 && | 
 | 563 |         (Addr)VG_(client_envp) >= 0x8000000) | 
 | 564 |       goto argc_argv_envp_OK; | 
 | 565 |  | 
 | 566 |    /* If that's no good, try some other offsets discovered by KDE | 
 | 567 |       folks on 8 Feb 02: | 
 | 568 |       For glibc > 2.2.4 the offset 9/10/11 did the trick. Coolo found | 
 | 569 |       out those, on I think a Caldera 3.1 with glibc 2.2.4 -- the same | 
 | 570 |       offsets worked for on a debian sid with glibc 2.2.5.  */ | 
 | 571 |  | 
 | 572 |    VG_(client_argc) = (Int)   ( ((void**)VG_(esp_at_startup)) [9] ); | 
 | 573 |    VG_(client_argv) = (Char**)( ((void**)VG_(esp_at_startup)) [10] ); | 
 | 574 |    VG_(client_envp) = (Char**)( ((void**)VG_(esp_at_startup)) [11] ); | 
 | 575 |  | 
 | 576 |    if ( ((UInt)VG_(client_argc)) > 0 && | 
 | 577 |         ((UInt)VG_(client_argc)) < 10000 && | 
 | 578 |         (Addr)VG_(client_argv) >= 0x8000000 && | 
 | 579 |         (Addr)VG_(client_envp) >= 0x8000000) | 
 | 580 |       goto argc_argv_envp_OK; | 
 | 581 |  | 
| sewardj | a88ebf6 | 2002-03-24 12:22:39 +0000 | [diff] [blame] | 582 | #  endif /* defined(GLIBC_2_2) */ | 
 | 583 |  | 
 | 584 | #  if defined(GLIBC_2_1) | 
| sewardj | de4a1d0 | 2002-03-22 01:27:54 +0000 | [diff] [blame] | 585 |    /* Doesn't look promising.  Try offsets for RedHat 6.2 | 
 | 586 |       (glibc-2.1.3) instead.  In this case, the argv and envp vectors | 
 | 587 |       are actually on the stack (bizarrely). */ | 
 | 588 |  | 
 | 589 |    VG_(client_argc) = (Int)      ( ((void**)VG_(esp_at_startup)) [4] ); | 
 | 590 |    VG_(client_argv) = (Char**) & ( ((void**)VG_(esp_at_startup)) [5] ); | 
 | 591 |    VG_(client_envp)  | 
 | 592 |       = (Char**) & ( ((void**)VG_(esp_at_startup)) [6 + VG_(client_argc)] ); | 
 | 593 |  | 
 | 594 |    if ( ((UInt)VG_(client_argc)) > 0 && | 
 | 595 |         ((UInt)VG_(client_argc)) < 10000 && | 
 | 596 |         (Addr)VG_(client_argv) >= 0x8000000 && | 
 | 597 |         (Addr)VG_(client_envp) >= 0x8000000) | 
 | 598 |       goto argc_argv_envp_OK; | 
 | 599 |  | 
 | 600 |    /* Here's yet another variant, from <hansen> (irc.kde.org). */ | 
 | 601 |  | 
 | 602 |    VG_(client_argc) = (Int)      ( ((void**)VG_(esp_at_startup)) [9] ); | 
 | 603 |    VG_(client_argv) = (Char**) & ( ((void**)VG_(esp_at_startup)) [10] ); | 
 | 604 |    VG_(client_envp)  | 
 | 605 |       = (Char**) & ( ((void**)VG_(esp_at_startup)) [11 + VG_(client_argc)] ); | 
 | 606 |  | 
 | 607 |    if ( ((UInt)VG_(client_argc)) > 0 && | 
 | 608 |         ((UInt)VG_(client_argc)) < 10000 && | 
 | 609 |         (Addr)VG_(client_argv) >= 0x8000000 && | 
 | 610 |         (Addr)VG_(client_envp) >= 0x8000000) | 
 | 611 |       goto argc_argv_envp_OK; | 
| sewardj | a88ebf6 | 2002-03-24 12:22:39 +0000 | [diff] [blame] | 612 | #  endif /* defined(GLIBC_2_1) */ | 
 | 613 |  | 
 | 614 | #  if !defined(GLIBC_2_2) && !defined(GLIBC_2_1) | 
 | 615 |    config_error("autoconf/configure detected neither glibc 2.1.X nor 2.2.X"); | 
 | 616 | #  endif | 
| sewardj | de4a1d0 | 2002-03-22 01:27:54 +0000 | [diff] [blame] | 617 |  | 
 | 618 |    /* VG_(printf)("%d %p %p\n", VG_(client_argc), VG_(client_argv),  | 
 | 619 |                                                   VG_(client_envp)); | 
 | 620 |    */ | 
 | 621 |    /* We're hosed.  Give up :-( */ | 
 | 622 |    config_error( | 
 | 623 |       "Can't get plausible values for client's argc/argv/envp.\n\t" | 
 | 624 |       "You may be able to fix this; see process_cmd_line_options()\n\t" | 
 | 625 |       "in vg_main.c" | 
 | 626 |    ); | 
 | 627 |    /* NOTREACHED */ | 
 | 628 |  | 
 | 629 |   argc_argv_envp_OK: | 
 | 630 |  | 
 | 631 |    /* Now that VG_(client_envp) has been set, we can extract the args | 
 | 632 |       for Valgrind itself.  Copy into global var so that we don't have to | 
 | 633 |       write zeroes to the getenv'd value itself. */ | 
 | 634 |    str = VG_(getenv)("VG_ARGS"); | 
 | 635 |    argc = 0; | 
 | 636 |  | 
 | 637 |    if (!str) { | 
 | 638 |       config_error("Can't read options from env var VG_ARGS."); | 
 | 639 |    } | 
 | 640 |  | 
 | 641 |    if (VG_(strlen)(str) >= M_VG_CMDLINE_STRLEN-1) { | 
 | 642 |       config_error("Command line length exceeds M_CMDLINE_STRLEN."); | 
 | 643 |    } | 
 | 644 |    VG_(strcpy)(vg_cmdline_copy, str); | 
 | 645 |    str = NULL; | 
 | 646 |  | 
 | 647 |    p = &vg_cmdline_copy[0]; | 
 | 648 |    while (True) { | 
 | 649 |       while (ISSPACE(*p)) { *p = 0; p++; } | 
 | 650 |       if (*p == 0) break; | 
 | 651 |       if (argc < M_VG_CMDLINE_OPTS-1) {  | 
 | 652 |          argv[argc] = p; argc++;  | 
 | 653 |       } else { | 
 | 654 |          config_error( | 
 | 655 |             "Found more than M_CMDLINE_OPTS command-line opts."); | 
 | 656 |       } | 
 | 657 |       while (*p != 0 && !ISSPACE(*p)) p++; | 
 | 658 |    } | 
 | 659 |  | 
 | 660 |    for (i = 0; i < argc; i++) { | 
 | 661 |  | 
 | 662 |       if (STREQ(argv[i], "-v") || STREQ(argv[i], "--verbose")) | 
 | 663 |          VG_(clo_verbosity)++; | 
 | 664 |       else if (STREQ(argv[i], "-q") || STREQ(argv[i], "--quiet")) | 
 | 665 |          VG_(clo_verbosity)--; | 
 | 666 |  | 
| sewardj | 97ced73 | 2002-03-25 00:07:36 +0000 | [diff] [blame] | 667 |       else if (STREQ(argv[i], "--check-addrVs=yes")) | 
 | 668 |          VG_(clo_check_addrVs) = True; | 
 | 669 |       else if (STREQ(argv[i], "--check-addrVs=no")) | 
 | 670 |          VG_(clo_check_addrVs) = False; | 
 | 671 |  | 
| sewardj | de4a1d0 | 2002-03-22 01:27:54 +0000 | [diff] [blame] | 672 |       else if (STREQ(argv[i], "--gdb-attach=yes")) | 
 | 673 |          VG_(clo_GDB_attach) = True; | 
 | 674 |       else if (STREQ(argv[i], "--gdb-attach=no")) | 
 | 675 |          VG_(clo_GDB_attach) = False; | 
 | 676 |  | 
 | 677 |       else if (STREQ(argv[i], "--demangle=yes")) | 
 | 678 |          VG_(clo_demangle) = True; | 
 | 679 |       else if (STREQ(argv[i], "--demangle=no")) | 
 | 680 |          VG_(clo_demangle) = False; | 
 | 681 |  | 
 | 682 |       else if (STREQ(argv[i], "--partial-loads-ok=yes")) | 
 | 683 |          VG_(clo_partial_loads_ok) = True; | 
 | 684 |       else if (STREQ(argv[i], "--partial-loads-ok=no")) | 
 | 685 |          VG_(clo_partial_loads_ok) = False; | 
 | 686 |  | 
 | 687 |       else if (STREQ(argv[i], "--leak-check=yes")) | 
 | 688 |          VG_(clo_leak_check) = True; | 
 | 689 |       else if (STREQ(argv[i], "--leak-check=no")) | 
 | 690 |          VG_(clo_leak_check) = False; | 
 | 691 |  | 
 | 692 |       else if (STREQ(argv[i], "--show-reachable=yes")) | 
 | 693 |          VG_(clo_show_reachable) = True; | 
 | 694 |       else if (STREQ(argv[i], "--show-reachable=no")) | 
 | 695 |          VG_(clo_show_reachable) = False; | 
 | 696 |  | 
 | 697 |       else if (STREQ(argv[i], "--leak-resolution=low")) | 
 | 698 |          VG_(clo_leak_resolution) = 2; | 
 | 699 |       else if (STREQ(argv[i], "--leak-resolution=med")) | 
 | 700 |          VG_(clo_leak_resolution) = 4; | 
 | 701 |       else if (STREQ(argv[i], "--leak-resolution=high")) | 
 | 702 |          VG_(clo_leak_resolution) = VG_DEEPEST_BACKTRACE; | 
 | 703 |  | 
 | 704 |       else if (STREQ(argv[i], "--sloppy-malloc=yes")) | 
 | 705 |          VG_(clo_sloppy_malloc) = True; | 
 | 706 |       else if (STREQ(argv[i], "--sloppy-malloc=no")) | 
 | 707 |          VG_(clo_sloppy_malloc) = False; | 
 | 708 |  | 
 | 709 |       else if (STREQ(argv[i], "--trace-children=yes")) | 
 | 710 |          VG_(clo_trace_children) = True; | 
 | 711 |       else if (STREQ(argv[i], "--trace-children=no")) | 
 | 712 |          VG_(clo_trace_children) = False; | 
 | 713 |  | 
 | 714 |       else if (STREQ(argv[i], "--workaround-gcc296-bugs=yes")) | 
 | 715 |          VG_(clo_workaround_gcc296_bugs) = True; | 
 | 716 |       else if (STREQ(argv[i], "--workaround-gcc296-bugs=no")) | 
 | 717 |          VG_(clo_workaround_gcc296_bugs) = False; | 
 | 718 |  | 
 | 719 |       else if (STREQN(15, argv[i], "--sanity-level=")) | 
 | 720 |          VG_(sanity_level) = (Int)VG_(atoll)(&argv[i][15]); | 
 | 721 |  | 
 | 722 |       else if (STREQN(13, argv[i], "--logfile-fd=")) | 
 | 723 |          eventually_logfile_fd = (Int)VG_(atoll)(&argv[i][13]); | 
 | 724 |  | 
 | 725 |       else if (STREQN(15, argv[i], "--freelist-vol=")) { | 
 | 726 |          VG_(clo_freelist_vol) = (Int)VG_(atoll)(&argv[i][15]); | 
 | 727 |          if (VG_(clo_freelist_vol) < 0) VG_(clo_freelist_vol) = 2; | 
 | 728 |       } | 
 | 729 |  | 
 | 730 |       else if (STREQN(15, argv[i], "--suppressions=")) { | 
 | 731 |          if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) { | 
 | 732 |             VG_(message)(Vg_UserMsg, "Too many logfiles specified."); | 
 | 733 |             VG_(message)(Vg_UserMsg,  | 
 | 734 |                          "Increase VG_CLO_MAX_SFILES and recompile."); | 
 | 735 |             bad_option(argv[i]); | 
 | 736 |          } | 
 | 737 |          VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &argv[i][15]; | 
 | 738 |          VG_(clo_n_suppressions)++; | 
 | 739 |       } | 
 | 740 |       else if (STREQ(argv[i], "--single-step=yes")) | 
 | 741 |          VG_(clo_single_step) = True; | 
 | 742 |       else if (STREQ(argv[i], "--single-step=no")) | 
 | 743 |          VG_(clo_single_step) = False; | 
 | 744 |  | 
 | 745 |       else if (STREQ(argv[i], "--optimise=yes")) | 
 | 746 |          VG_(clo_optimise) = True; | 
 | 747 |       else if (STREQ(argv[i], "--optimise=no")) | 
 | 748 |          VG_(clo_optimise) = False; | 
 | 749 |  | 
 | 750 |       else if (STREQ(argv[i], "--instrument=yes")) | 
 | 751 |          VG_(clo_instrument) = True; | 
 | 752 |       else if (STREQ(argv[i], "--instrument=no")) | 
 | 753 |          VG_(clo_instrument) = False; | 
 | 754 |  | 
 | 755 |       else if (STREQ(argv[i], "--cleanup=yes")) | 
 | 756 |          VG_(clo_cleanup) = True; | 
 | 757 |       else if (STREQ(argv[i], "--cleanup=no")) | 
 | 758 |          VG_(clo_cleanup) = False; | 
 | 759 |  | 
 | 760 |       else if (STREQ(argv[i], "--client-perms=yes")) | 
 | 761 |          VG_(clo_client_perms) = True; | 
 | 762 |       else if (STREQ(argv[i], "--client-perms=no")) | 
 | 763 |          VG_(clo_client_perms) = False; | 
 | 764 |  | 
 | 765 |       else if (STREQ(argv[i], "--smc-check=none")) | 
 | 766 |          VG_(clo_smc_check) = VG_CLO_SMC_NONE; | 
 | 767 |       else if (STREQ(argv[i], "--smc-check=some")) | 
 | 768 |          VG_(clo_smc_check) = VG_CLO_SMC_SOME; | 
 | 769 |       else if (STREQ(argv[i], "--smc-check=all")) | 
 | 770 |          VG_(clo_smc_check) = VG_CLO_SMC_ALL; | 
 | 771 |  | 
 | 772 |       else if (STREQ(argv[i], "--trace-syscalls=yes")) | 
 | 773 |          VG_(clo_trace_syscalls) = True; | 
 | 774 |       else if (STREQ(argv[i], "--trace-syscalls=no")) | 
 | 775 |          VG_(clo_trace_syscalls) = False; | 
 | 776 |  | 
 | 777 |       else if (STREQ(argv[i], "--trace-signals=yes")) | 
 | 778 |          VG_(clo_trace_signals) = True; | 
 | 779 |       else if (STREQ(argv[i], "--trace-signals=no")) | 
 | 780 |          VG_(clo_trace_signals) = False; | 
 | 781 |  | 
 | 782 |       else if (STREQ(argv[i], "--trace-symtab=yes")) | 
 | 783 |          VG_(clo_trace_symtab) = True; | 
 | 784 |       else if (STREQ(argv[i], "--trace-symtab=no")) | 
 | 785 |          VG_(clo_trace_symtab) = False; | 
 | 786 |  | 
 | 787 |       else if (STREQ(argv[i], "--trace-malloc=yes")) | 
 | 788 |          VG_(clo_trace_malloc) = True; | 
 | 789 |       else if (STREQ(argv[i], "--trace-malloc=no")) | 
 | 790 |          VG_(clo_trace_malloc) = False; | 
 | 791 |  | 
 | 792 |       else if (STREQN(13, argv[i], "--stop-after=")) | 
 | 793 |          VG_(clo_stop_after) = VG_(atoll)(&argv[i][13]); | 
 | 794 |  | 
 | 795 |       else if (STREQN(13, argv[i], "--dump-error=")) | 
 | 796 |          VG_(clo_dump_error) = (Int)VG_(atoll)(&argv[i][13]); | 
 | 797 |  | 
 | 798 |       else if (STREQN(14, argv[i], "--num-callers=")) { | 
 | 799 |          /* Make sure it's sane. */ | 
 | 800 | 	 VG_(clo_backtrace_size) = (Int)VG_(atoll)(&argv[i][14]); | 
 | 801 |          if (VG_(clo_backtrace_size) < 2) | 
 | 802 |             VG_(clo_backtrace_size) = 2; | 
 | 803 |          if (VG_(clo_backtrace_size) >= VG_DEEPEST_BACKTRACE) | 
 | 804 |             VG_(clo_backtrace_size) = VG_DEEPEST_BACKTRACE; | 
 | 805 |       } | 
 | 806 |  | 
 | 807 |       else | 
 | 808 |          bad_option(argv[i]); | 
 | 809 |    } | 
 | 810 |  | 
 | 811 | #  undef ISSPACE | 
 | 812 | #  undef STREQ | 
 | 813 | #  undef STREQN | 
 | 814 |  | 
 | 815 |    if (VG_(clo_verbosity < 0)) | 
 | 816 |       VG_(clo_verbosity) = 0; | 
 | 817 |  | 
 | 818 |    if (VG_(clo_GDB_attach) && VG_(clo_trace_children)) { | 
 | 819 |       VG_(message)(Vg_UserMsg, ""); | 
 | 820 |       VG_(message)(Vg_UserMsg,  | 
 | 821 |          "--gdb-attach=yes conflicts with --trace-children=yes"); | 
 | 822 |       VG_(message)(Vg_UserMsg,  | 
 | 823 |          "Please choose one or the other, but not both."); | 
 | 824 |       bad_option("--gdb-attach=yes and --trace-children=yes"); | 
 | 825 |    } | 
 | 826 |  | 
| sewardj | 2e93c50 | 2002-04-12 11:12:52 +0000 | [diff] [blame^] | 827 | #if 0 | 
| sewardj | de4a1d0 | 2002-03-22 01:27:54 +0000 | [diff] [blame] | 828 |    if (VG_(clo_client_perms) && !VG_(clo_instrument)) { | 
 | 829 |       VG_(message)(Vg_UserMsg, ""); | 
 | 830 |       VG_(message)(Vg_UserMsg,  | 
 | 831 |          "--client-perms=yes requires --instrument=yes"); | 
 | 832 |       bad_option("--client-perms=yes without --instrument=yes"); | 
 | 833 |    } | 
 | 834 |  | 
 | 835 |    if (VG_(clo_client_perms)) | 
 | 836 |       vg_assert(VG_(clo_instrument)); | 
| sewardj | 2e93c50 | 2002-04-12 11:12:52 +0000 | [diff] [blame^] | 837 | #endif | 
| sewardj | de4a1d0 | 2002-03-22 01:27:54 +0000 | [diff] [blame] | 838 |  | 
 | 839 |    VG_(clo_logfile_fd) = eventually_logfile_fd; | 
 | 840 |  | 
| sewardj | de4a1d0 | 2002-03-22 01:27:54 +0000 | [diff] [blame] | 841 |    if (VG_(clo_verbosity > 0)) | 
 | 842 |       VG_(message)(Vg_UserMsg,  | 
 | 843 |                    "valgrind-%s, a memory error detector for x86 GNU/Linux.", | 
| sewardj | 3b2736a | 2002-03-24 12:18:35 +0000 | [diff] [blame] | 844 |                    VERSION); | 
 | 845 |  | 
| sewardj | de4a1d0 | 2002-03-22 01:27:54 +0000 | [diff] [blame] | 846 |    if (VG_(clo_verbosity > 0)) | 
 | 847 |       VG_(message)(Vg_UserMsg,  | 
 | 848 |                    "Copyright (C) 2000-2002, and GNU GPL'd, by Julian Seward."); | 
 | 849 |    if (VG_(clo_verbosity) > 1) { | 
 | 850 |       VG_(message)(Vg_UserMsg, "Startup, with flags:"); | 
 | 851 |       for (i = 0; i < argc; i++) { | 
 | 852 |          VG_(message)(Vg_UserMsg, "   %s", argv[i]); | 
 | 853 |       } | 
 | 854 |    } | 
 | 855 |  | 
 | 856 |    if (VG_(clo_n_suppressions) == 0) { | 
 | 857 |       config_error("No error-suppression files were specified."); | 
 | 858 |    } | 
 | 859 | } | 
 | 860 |  | 
 | 861 |  | 
 | 862 | /* --------------------------------------------------------------------- | 
 | 863 |    Copying to/from m_state_static. | 
 | 864 |    ------------------------------------------------------------------ */ | 
 | 865 |  | 
 | 866 | UInt VG_(m_state_static) [8 /* int regs, in Intel order */  | 
 | 867 |                           + 1 /* %eflags */  | 
 | 868 |                           + 1 /* %eip */ | 
 | 869 |                           + VG_SIZE_OF_FPUSTATE_W /* FPU state */ | 
 | 870 |                          ]; | 
 | 871 |  | 
 | 872 | void VG_(copy_baseBlock_to_m_state_static) ( void ) | 
 | 873 | { | 
 | 874 |    Int i; | 
 | 875 |    VG_(m_state_static)[ 0/4] = VG_(baseBlock)[VGOFF_(m_eax)]; | 
 | 876 |    VG_(m_state_static)[ 4/4] = VG_(baseBlock)[VGOFF_(m_ecx)]; | 
 | 877 |    VG_(m_state_static)[ 8/4] = VG_(baseBlock)[VGOFF_(m_edx)]; | 
 | 878 |    VG_(m_state_static)[12/4] = VG_(baseBlock)[VGOFF_(m_ebx)]; | 
 | 879 |    VG_(m_state_static)[16/4] = VG_(baseBlock)[VGOFF_(m_esp)]; | 
 | 880 |    VG_(m_state_static)[20/4] = VG_(baseBlock)[VGOFF_(m_ebp)]; | 
 | 881 |    VG_(m_state_static)[24/4] = VG_(baseBlock)[VGOFF_(m_esi)]; | 
 | 882 |    VG_(m_state_static)[28/4] = VG_(baseBlock)[VGOFF_(m_edi)]; | 
 | 883 |  | 
 | 884 |    VG_(m_state_static)[32/4] = VG_(baseBlock)[VGOFF_(m_eflags)]; | 
 | 885 |    VG_(m_state_static)[36/4] = VG_(baseBlock)[VGOFF_(m_eip)]; | 
 | 886 |  | 
 | 887 |    for (i = 0; i < VG_SIZE_OF_FPUSTATE_W; i++) | 
 | 888 |       VG_(m_state_static)[40/4 + i]  | 
 | 889 |          = VG_(baseBlock)[VGOFF_(m_fpustate) + i]; | 
 | 890 | } | 
 | 891 |  | 
 | 892 |  | 
 | 893 | void VG_(copy_m_state_static_to_baseBlock) ( void ) | 
 | 894 | { | 
 | 895 |    Int i; | 
 | 896 |    VG_(baseBlock)[VGOFF_(m_eax)] = VG_(m_state_static)[ 0/4]; | 
 | 897 |    VG_(baseBlock)[VGOFF_(m_ecx)] = VG_(m_state_static)[ 4/4]; | 
 | 898 |    VG_(baseBlock)[VGOFF_(m_edx)] = VG_(m_state_static)[ 8/4]; | 
 | 899 |    VG_(baseBlock)[VGOFF_(m_ebx)] = VG_(m_state_static)[12/4]; | 
 | 900 |    VG_(baseBlock)[VGOFF_(m_esp)] = VG_(m_state_static)[16/4]; | 
 | 901 |    VG_(baseBlock)[VGOFF_(m_ebp)] = VG_(m_state_static)[20/4]; | 
 | 902 |    VG_(baseBlock)[VGOFF_(m_esi)] = VG_(m_state_static)[24/4]; | 
 | 903 |    VG_(baseBlock)[VGOFF_(m_edi)] = VG_(m_state_static)[28/4]; | 
 | 904 |  | 
 | 905 |    VG_(baseBlock)[VGOFF_(m_eflags)] = VG_(m_state_static)[32/4]; | 
 | 906 |    VG_(baseBlock)[VGOFF_(m_eip)] = VG_(m_state_static)[36/4]; | 
 | 907 |  | 
 | 908 |    for (i = 0; i < VG_SIZE_OF_FPUSTATE_W; i++) | 
 | 909 |       VG_(baseBlock)[VGOFF_(m_fpustate) + i] | 
 | 910 |          = VG_(m_state_static)[40/4 + i]; | 
 | 911 | } | 
 | 912 |  | 
 | 913 |  | 
 | 914 | /* --------------------------------------------------------------------- | 
 | 915 |    Show accumulated counts. | 
 | 916 |    ------------------------------------------------------------------ */ | 
 | 917 |  | 
 | 918 | static void vg_show_counts ( void ) | 
 | 919 | { | 
 | 920 |    VG_(message)(Vg_DebugMsg, | 
| sewardj | 2e93c50 | 2002-04-12 11:12:52 +0000 | [diff] [blame^] | 921 | 		"      lru: %d epochs, %d clearings.", | 
 | 922 | 		VG_(current_epoch), | 
 | 923 |                 VG_(number_of_lrus) ); | 
| sewardj | de4a1d0 | 2002-03-22 01:27:54 +0000 | [diff] [blame] | 924 |    VG_(message)(Vg_DebugMsg, | 
 | 925 |                 "translate: new %d (%d -> %d), discard %d (%d -> %d).", | 
 | 926 |                 VG_(overall_in_count), | 
 | 927 |                 VG_(overall_in_osize), | 
 | 928 |                 VG_(overall_in_tsize), | 
 | 929 |                 VG_(overall_out_count), | 
 | 930 |                 VG_(overall_out_osize), | 
 | 931 |                 VG_(overall_out_tsize) ); | 
 | 932 |    VG_(message)(Vg_DebugMsg, | 
| sewardj | 2e93c50 | 2002-04-12 11:12:52 +0000 | [diff] [blame^] | 933 |       " dispatch: %lu basic blocks, %d/%d sched events, %d tt_fast misses.",  | 
 | 934 |       VG_(bbs_done), VG_(num_scheduling_events_MAJOR),  | 
 | 935 |                      VG_(num_scheduling_events_MINOR),  | 
 | 936 |                      VG_(tt_fast_misses)); | 
| sewardj | de4a1d0 | 2002-03-22 01:27:54 +0000 | [diff] [blame] | 937 |    VG_(message)(Vg_DebugMsg,  | 
 | 938 |                 "reg-alloc: %d t-req-spill, " | 
 | 939 |                 "%d+%d orig+spill uis, %d total-reg-r.", | 
 | 940 |                 VG_(translations_needing_spill), | 
 | 941 |                 VG_(uinstrs_prealloc), | 
 | 942 |                 VG_(uinstrs_spill), | 
 | 943 |                 VG_(total_reg_rank) ); | 
 | 944 |    VG_(message)(Vg_DebugMsg,  | 
 | 945 |                 "smc-check: %d checks, %d fast pass, " | 
 | 946 |                 "%d slow pass, %d discards.", | 
 | 947 | 		VG_(smc_total_check4s), | 
 | 948 | 		VG_(smc_cache_passed), | 
 | 949 | 		VG_(smc_fancy_passed), | 
 | 950 | 		VG_(smc_discard_count) ); | 
 | 951 |    VG_(message)(Vg_DebugMsg,  | 
 | 952 |                 "   sanity: %d cheap, %d expensive checks.", | 
 | 953 |                 VG_(sanity_fast_count),  | 
 | 954 |                 VG_(sanity_slow_count) ); | 
 | 955 | } | 
 | 956 |  | 
 | 957 |  | 
 | 958 | /* --------------------------------------------------------------------- | 
 | 959 |    Main! | 
 | 960 |    ------------------------------------------------------------------ */ | 
 | 961 |  | 
 | 962 | /* Where we jump to once Valgrind has got control, and the real | 
 | 963 |    machine's state has been copied to the m_state_static. */ | 
 | 964 |  | 
 | 965 | void VG_(main) ( void ) | 
 | 966 | { | 
| sewardj | 2e93c50 | 2002-04-12 11:12:52 +0000 | [diff] [blame^] | 967 |    Int               i; | 
 | 968 |    VgSchedReturnCode src; | 
| sewardj | de4a1d0 | 2002-03-22 01:27:54 +0000 | [diff] [blame] | 969 |  | 
 | 970 |    /* Set up our stack sanity-check words. */ | 
 | 971 |    for (i = 0; i < 10; i++) { | 
 | 972 |       VG_(stack)[i]         = (UInt)(&VG_(stack)[i])         ^ 0xA4B3C2D1; | 
 | 973 |       VG_(stack)[10000-1-i] = (UInt)(&VG_(stack)[10000-i-1]) ^ 0xABCD4321; | 
 | 974 |    } | 
 | 975 |  | 
 | 976 |    /* Set up baseBlock offsets and copy the saved machine's state into | 
 | 977 |       it. */ | 
 | 978 |    vg_init_baseBlock(); | 
 | 979 |    VG_(copy_m_state_static_to_baseBlock)(); | 
 | 980 |  | 
 | 981 |    /* Process Valgrind's command-line opts (from env var VG_OPTS). */ | 
 | 982 |    process_cmd_line_options(); | 
 | 983 |  | 
 | 984 |    /* Initialise the signal handling subsystem. */ | 
 | 985 |    VG_(sigstartup_actions)(); | 
 | 986 |  | 
 | 987 | #  ifdef VG_PROFILE | 
 | 988 |    VGP_(init_profiling)(); | 
 | 989 | #  endif | 
 | 990 |  | 
| sewardj | b3c2687 | 2002-03-24 10:05:14 +0000 | [diff] [blame] | 991 |    /* Hook to delay things long enough so we can get the pid and | 
 | 992 |       attach GDB in another shell. */ | 
 | 993 |    /* {extern unsigned int sleep(unsigned int seconds); sleep(10);} */ | 
 | 994 |  | 
| sewardj | de4a1d0 | 2002-03-22 01:27:54 +0000 | [diff] [blame] | 995 |    if (VG_(clo_instrument)) { | 
 | 996 |       VGP_PUSHCC(VgpInitAudit); | 
 | 997 |       VGM_(init_memory_audit)(); | 
 | 998 |       VGP_POPCC; | 
 | 999 |       VGP_PUSHCC(VgpReadSyms); | 
 | 1000 |       VG_(read_symbols)(); | 
 | 1001 |       VGP_POPCC; | 
 | 1002 |    } | 
 | 1003 |  | 
 | 1004 |    /* This should come after init_memory_audit; otherwise the latter | 
 | 1005 |       carefully sets up the permissions maps to cover the anonymous | 
 | 1006 |       mmaps for the translation table and translation cache, which | 
 | 1007 |       wastes > 20M of virtual address space. */ | 
 | 1008 |    VG_(init_transtab_and_SMC)(); | 
 | 1009 |  | 
 | 1010 |    if (VG_(clo_verbosity) == 1) { | 
 | 1011 |       VG_(message)(Vg_UserMsg,  | 
 | 1012 |                    "For more details, rerun with: -v"); | 
 | 1013 |    } | 
 | 1014 |  | 
 | 1015 |    /* Now it is safe for malloc et al in vg_clientmalloc.c to act | 
 | 1016 |       instrumented-ly. */ | 
 | 1017 |    VG_(running_on_simd_CPU) = True; | 
 | 1018 |    if (VG_(clo_instrument)) { | 
 | 1019 |       VGM_(make_readable) ( (Addr)&VG_(running_on_simd_CPU), 1 ); | 
 | 1020 |       VGM_(make_readable) ( (Addr)&VG_(clo_instrument), 1 ); | 
 | 1021 |       VGM_(make_readable) ( (Addr)&VG_(clo_trace_malloc), 1 ); | 
 | 1022 |       VGM_(make_readable) ( (Addr)&VG_(clo_sloppy_malloc), 1 ); | 
 | 1023 |    } | 
 | 1024 |  | 
 | 1025 |    if (VG_(clo_verbosity) > 0) | 
 | 1026 |       VG_(message)(Vg_UserMsg, ""); | 
 | 1027 |  | 
 | 1028 |    VG_(bbs_to_go) = VG_(clo_stop_after); | 
| sewardj | 2e93c50 | 2002-04-12 11:12:52 +0000 | [diff] [blame^] | 1029 |  | 
 | 1030 |    VG_(scheduler_init)(); | 
 | 1031 |    src = VG_(scheduler)(); | 
| sewardj | de4a1d0 | 2002-03-22 01:27:54 +0000 | [diff] [blame] | 1032 |  | 
 | 1033 |    if (VG_(clo_verbosity) > 0) | 
 | 1034 |       VG_(message)(Vg_UserMsg, ""); | 
 | 1035 |  | 
| sewardj | 2e93c50 | 2002-04-12 11:12:52 +0000 | [diff] [blame^] | 1036 |    if (src == VgSrc_Deadlock) { | 
 | 1037 |      VG_(message)(Vg_UserMsg,  | 
 | 1038 |         "Warning: pthread scheduler exited due to deadlock"); | 
 | 1039 |    } | 
 | 1040 |  | 
| sewardj | de4a1d0 | 2002-03-22 01:27:54 +0000 | [diff] [blame] | 1041 |    if (VG_(clo_instrument)) { | 
 | 1042 |       VG_(show_all_errors)(); | 
 | 1043 |       VG_(clientmalloc_done)(); | 
 | 1044 |       if (VG_(clo_verbosity) == 1) { | 
 | 1045 |          VG_(message)(Vg_UserMsg,  | 
 | 1046 |                       "For counts of detected errors, rerun with: -v"); | 
 | 1047 |       } | 
 | 1048 |       if (VG_(clo_leak_check)) VG_(detect_memory_leaks)(); | 
 | 1049 |    } | 
 | 1050 |    VG_(running_on_simd_CPU) = False; | 
| sewardj | 2e93c50 | 2002-04-12 11:12:52 +0000 | [diff] [blame^] | 1051 |  | 
 | 1052 |    VG_(do_sanity_checks)( 0 /* root thread */,  | 
 | 1053 |                           True /*include expensive checks*/ ); | 
| sewardj | de4a1d0 | 2002-03-22 01:27:54 +0000 | [diff] [blame] | 1054 |  | 
 | 1055 |    if (VG_(clo_verbosity) > 1) | 
 | 1056 |       vg_show_counts(); | 
 | 1057 |  | 
 | 1058 |    if (0) { | 
 | 1059 |       VG_(message)(Vg_DebugMsg, ""); | 
 | 1060 |       VG_(message)(Vg_DebugMsg,  | 
 | 1061 |          "------ Valgrind's internal memory use stats follow ------" ); | 
 | 1062 |       VG_(mallocSanityCheckAll)(); | 
 | 1063 |       VG_(show_all_arena_stats)(); | 
 | 1064 |       VG_(message)(Vg_DebugMsg,  | 
 | 1065 |          "------ Valgrind's ExeContext management stats follow ------" ); | 
 | 1066 |       VG_(show_ExeContext_stats)(); | 
 | 1067 |       VG_(message)(Vg_DebugMsg,  | 
 | 1068 |          "------ Valgrind's client block stats follow ---------------" ); | 
 | 1069 |       VG_(show_client_block_stats)(); | 
 | 1070 |    } | 
 | 1071 |   | 
 | 1072 | #  ifdef VG_PROFILE | 
 | 1073 |    VGP_(done_profiling)(); | 
 | 1074 | #  endif | 
 | 1075 |  | 
 | 1076 |    VG_(done_prof_mem)(); | 
 | 1077 |  | 
 | 1078 |    VG_(shutdown_logging)(); | 
 | 1079 |  | 
 | 1080 |    /* In LD_PRELOAD, convert "valgrind.so" into "valgrinq.so", so that | 
 | 1081 |       child processes don't get traced into.  Also done on simulated | 
 | 1082 |       execve system call. */ | 
 | 1083 |    if (!VG_(clo_trace_children)) {  | 
 | 1084 |       VG_(mash_LD_PRELOAD_string)(VG_(getenv)("LD_PRELOAD")); | 
 | 1085 |    } | 
 | 1086 |  | 
 | 1087 |    /* Prepare to restore state to the real CPU. */ | 
| sewardj | 2e93c50 | 2002-04-12 11:12:52 +0000 | [diff] [blame^] | 1088 |    VG_(load_thread_state)(0); | 
| sewardj | de4a1d0 | 2002-03-22 01:27:54 +0000 | [diff] [blame] | 1089 |    VG_(copy_baseBlock_to_m_state_static)(); | 
 | 1090 |  | 
 | 1091 |    /* This pushes a return address on the simulator's stack, which | 
 | 1092 |       is abandoned.  We call vg_sigshutdown_actions() at the end | 
 | 1093 |       of vg_switch_to_real_CPU(), so as to ensure that the original | 
 | 1094 |       stack and machine state is restored before the real signal | 
 | 1095 |       mechanism is restored. | 
 | 1096 |    */ | 
 | 1097 |    VG_(switch_to_real_CPU)(); | 
 | 1098 | } | 
 | 1099 |  | 
 | 1100 |  | 
 | 1101 | /* Debugging thing .. can be called from assembly with OYNK macro. */ | 
 | 1102 | void VG_(oynk) ( Int n ) | 
 | 1103 | { | 
 | 1104 |    OINK(n); | 
 | 1105 | } | 
 | 1106 |  | 
 | 1107 |  | 
 | 1108 | /* Find "valgrind.so" in a LD_PRELOAD=... string, and convert it to | 
 | 1109 |    "valgrinq.so", which doesn't do anything.  This is used to avoid | 
 | 1110 |    tracing into child processes.  To make this work the build system | 
 | 1111 |    also supplies a dummy file, "valgrinq.so".  | 
 | 1112 | */ | 
 | 1113 | void VG_(mash_LD_PRELOAD_string)( Char* ld_preload_str ) | 
 | 1114 | { | 
 | 1115 |    Char* p; | 
 | 1116 |    if (ld_preload_str == NULL) | 
 | 1117 |       return; | 
 | 1118 |    p = VG_(strstr)(ld_preload_str, "valgrind.so"); | 
 | 1119 |    if (p == NULL) | 
 | 1120 |       return; | 
 | 1121 |    p[7] = 'q'; | 
 | 1122 | } | 
 | 1123 |  | 
 | 1124 | /* RUNS ON THE CLIENT'S STACK, but on the real CPU.  Start GDB and get | 
 | 1125 |    it to attach to this process.  Called if the user requests this | 
 | 1126 |    service after an error has been shown, so she can poke around and | 
 | 1127 |    look at parameters, memory, etc.  You can't meaningfully get GDB to | 
 | 1128 |    continue the program, though; to continue, quit GDB.  */ | 
 | 1129 | extern void VG_(start_GDB_whilst_on_client_stack) ( void ) | 
 | 1130 | { | 
 | 1131 |    UChar buf[100]; | 
 | 1132 |    VG_(sprintf)(buf, | 
 | 1133 |                 "/usr/bin/gdb -nw /proc/%d/exe %d",  | 
 | 1134 |                 VG_(getpid)(), VG_(getpid)()); | 
 | 1135 |    VG_(printf)("starting GDB with cmd: %s\n", buf); | 
 | 1136 |    VG_(mash_LD_PRELOAD_string)(VG_(getenv)("LD_PRELOAD")); | 
 | 1137 |    { /* HACK ALERT */ | 
 | 1138 |      extern int system ( const char * ); | 
 | 1139 |      system(buf); | 
 | 1140 |      /* end of HACK ALERT */ | 
 | 1141 |    } | 
 | 1142 |    VG_(message)(Vg_UserMsg, ""); | 
 | 1143 |    VG_(message)(Vg_UserMsg,  | 
 | 1144 |       "GDB has detached.  Valgrind regains control.  We continue."); | 
 | 1145 | } | 
 | 1146 |  | 
 | 1147 |  | 
 | 1148 | /* Print some helpful-ish text about unimplemented things, and give | 
 | 1149 |    up. */ | 
 | 1150 | extern void VG_(unimplemented) ( Char* msg ) | 
 | 1151 | { | 
 | 1152 |    VG_(message)(Vg_UserMsg, ""); | 
 | 1153 |    VG_(message)(Vg_UserMsg,  | 
 | 1154 |       "Valgrind detected that your program requires"); | 
 | 1155 |    VG_(message)(Vg_UserMsg,  | 
 | 1156 |       "the following unimplemented functionality:"); | 
 | 1157 |    VG_(message)(Vg_UserMsg, "   %s", msg); | 
 | 1158 |    VG_(message)(Vg_UserMsg, | 
 | 1159 |       "This may be because the functionality is hard to implement,"); | 
 | 1160 |    VG_(message)(Vg_UserMsg, | 
 | 1161 |       "or because no reasonable program would behave this way,"); | 
 | 1162 |    VG_(message)(Vg_UserMsg, | 
 | 1163 |       "or because nobody has yet needed it.  In any case, let me know"); | 
 | 1164 |    VG_(message)(Vg_UserMsg, | 
 | 1165 |       "(jseward@acm.org) and/or try to work around the problem, if you can."); | 
 | 1166 |    VG_(message)(Vg_UserMsg, | 
 | 1167 |       ""); | 
 | 1168 |    VG_(message)(Vg_UserMsg, | 
 | 1169 |       "Valgrind has to exit now.  Sorry.  Bye!"); | 
 | 1170 |    VG_(message)(Vg_UserMsg, | 
 | 1171 |       ""); | 
 | 1172 |    VG_(exit)(1); | 
 | 1173 | } | 
 | 1174 |  | 
 | 1175 |  | 
| sewardj | de4a1d0 | 2002-03-22 01:27:54 +0000 | [diff] [blame] | 1176 | /*--------------------------------------------------------------------*/ | 
 | 1177 | /*--- end                                                vg_main.c ---*/ | 
 | 1178 | /*--------------------------------------------------------------------*/ |