Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1136)

Side by Side Diff: tools/command_tester.py

Issue 12278019: Mac: Enable Mach exception handler by default Base URL: svn://svn.chromium.org/native_client/trunk/src/native_client
Patch Set: Rebase Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/trusted/service_runtime/sel_main.c ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/python 1 #!/usr/bin/python
2 # Copyright (c) 2012 The Native Client Authors. All rights reserved. 2 # Copyright (c) 2012 The Native Client Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 6
7 """Simple testing harness for running commands and checking expected output. 7 """Simple testing harness for running commands and checking expected output.
8 8
9 This harness is used instead of shell scripts to ensure windows compatibility 9 This harness is used instead of shell scripts to ensure windows compatibility
10 10
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after
201 MungeWindowsErrorExit(STATUS_INTEGER_DIVIDE_BY_ZERO), 201 MungeWindowsErrorExit(STATUS_INTEGER_DIVIDE_BY_ZERO),
202 ] 202 ]
203 203
204 # We patch Windows' KiUserExceptionDispatcher on x86-64 to terminate 204 # We patch Windows' KiUserExceptionDispatcher on x86-64 to terminate
205 # the process safely when untrusted code crashes. We get the exit 205 # the process safely when untrusted code crashes. We get the exit
206 # code associated with the HLT instruction. 206 # code associated with the HLT instruction.
207 win64_exit_via_ntdll_patch = [ 207 win64_exit_via_ntdll_patch = [
208 MungeWindowsErrorExit(STATUS_PRIVILEGED_INSTRUCTION)] 208 MungeWindowsErrorExit(STATUS_PRIVILEGED_INSTRUCTION)]
209 209
210 210
211 EXC_BAD_ACCESS = 1
212 EXC_BAD_INSTRUCTION = 2
213
214
211 # 32-bit processes on Mac OS X return SIGBUS in most of the cases where Linux 215 # 32-bit processes on Mac OS X return SIGBUS in most of the cases where Linux
212 # returns SIGSEGV, except for actual x86 segmentation violations. 64-bit 216 # returns SIGSEGV, except for actual x86 segmentation violations. 64-bit
213 # processes on Mac OS X behave differently. 217 # processes on Mac OS X behave differently.
214 status_map = { 218 status_map = {
215 'sigtrap' : { 219 'sigtrap' : {
216 'linux2': [-5], # SIGTRAP 220 'linux2': [-5], # SIGTRAP
217 'darwin': [-5], # SIGTRAP 221 'darwin': [-5], # SIGTRAP
218 }, 222 },
219 'trusted_sigabrt' : { 223 'trusted_sigabrt' : {
220 'linux2': [-6], # SIGABRT 224 'linux2': [-6], # SIGABRT
(...skipping 15 matching lines...) Expand all
236 # This is not used on Windows because Windows does not have an 240 # This is not used on Windows because Windows does not have an
237 # equivalent of SIGPIPE. 241 # equivalent of SIGPIPE.
238 'linux2': [-13], # SIGPIPE 242 'linux2': [-13], # SIGPIPE
239 'mac32': [-13], # SIGPIPE 243 'mac32': [-13], # SIGPIPE
240 'mac64': [-13], # SIGPIPE 244 'mac64': [-13], # SIGPIPE
241 }, 245 },
242 'untrusted_sigsegv': { 246 'untrusted_sigsegv': {
243 'linux2': [-11], # SIGSEGV 247 'linux2': [-11], # SIGSEGV
244 'mac32': [-11], # SIGSEGV 248 'mac32': [-11], # SIGSEGV
245 'mac64': [-11], # SIGSEGV 249 'mac64': [-11], # SIGSEGV
250 'mach_exception': EXC_BAD_ACCESS,
246 'win32': win32_untrusted_crash_exit, 251 'win32': win32_untrusted_crash_exit,
247 'win64': win64_exit_via_ntdll_patch, 252 'win64': win64_exit_via_ntdll_patch,
248 }, 253 },
249 'untrusted_sigill' : { 254 'untrusted_sigill' : {
250 'linux2': [-4], # SIGILL 255 'linux2': [-4], # SIGILL
251 'mac32': [-4], # SIGILL 256 'mac32': [-4], # SIGILL
252 'mac64': [-4], # SIGILL 257 'mac64': [-4], # SIGILL
253 'win32': win32_untrusted_crash_exit, 258 'win32': win32_untrusted_crash_exit,
254 'win64': win64_exit_via_ntdll_patch, 259 'win64': win64_exit_via_ntdll_patch,
255 }, 260 },
256 'untrusted_sigfpe' : { 261 'untrusted_sigfpe' : {
257 'linux2': [-8], # SIGFPE 262 'linux2': [-8], # SIGFPE
258 'mac32': [-8], # SIGFPE 263 'mac32': [-8], # SIGFPE
259 'mac64': [-8], # SIGFPE 264 'mac64': [-8], # SIGFPE
260 'win32': win32_sigfpe, 265 'win32': win32_sigfpe,
261 'win64': win64_exit_via_ntdll_patch, 266 'win64': win64_exit_via_ntdll_patch,
262 }, 267 },
263 'untrusted_segfault': { 268 'untrusted_segfault': {
264 'linux2': [-11], # SIGSEGV 269 'linux2': [-11], # SIGSEGV
265 'mac32': [-10], # SIGBUS 270 'mac32': [-10], # SIGBUS
266 'mac64': [-10], # SIGBUS 271 'mac64': [-10], # SIGBUS
272 'mach_exception': EXC_BAD_ACCESS,
267 'win32': win32_untrusted_crash_exit, 273 'win32': win32_untrusted_crash_exit,
268 'win64': win64_exit_via_ntdll_patch, 274 'win64': win64_exit_via_ntdll_patch,
269 }, 275 },
270 'untrusted_sigsegv_or_equivalent': { 276 'untrusted_sigsegv_or_equivalent': {
271 'linux2': [-11], # SIGSEGV 277 'linux2': [-11], # SIGSEGV
272 'mac32': [-11], # SIGSEGV 278 'mac32': [-11], # SIGSEGV
273 'mac64': [-10], # SIGBUS 279 'mac64': [-10], # SIGBUS
280 'mach_exception': EXC_BAD_ACCESS,
274 'win32': win32_untrusted_crash_exit, 281 'win32': win32_untrusted_crash_exit,
275 'win64': win64_exit_via_ntdll_patch, 282 'win64': win64_exit_via_ntdll_patch,
276 }, 283 },
277 'trusted_segfault': { 284 'trusted_segfault': {
278 'linux2': [-11], # SIGSEGV 285 'linux2': [-11], # SIGSEGV
279 'mac32': [-10], # SIGBUS 286 'mac32': [-10], # SIGBUS
280 'mac64': [-11], # SIGSEGV 287 'mac64': [-11], # SIGSEGV
288 'mach_exception': EXC_BAD_ACCESS,
281 'win32': [MungeWindowsErrorExit(STATUS_ACCESS_VIOLATION)], 289 'win32': [MungeWindowsErrorExit(STATUS_ACCESS_VIOLATION)],
282 'win64': [MungeWindowsErrorExit(STATUS_ACCESS_VIOLATION)], 290 'win64': [MungeWindowsErrorExit(STATUS_ACCESS_VIOLATION)],
283 }, 291 },
284 'trusted_sigsegv_or_equivalent': { 292 'trusted_sigsegv_or_equivalent': {
285 'linux2': [-11], # SIGSEGV 293 'linux2': [-11], # SIGSEGV
286 'mac32': [-11], # SIGSEGV 294 'mac32': [-11], # SIGSEGV
287 'mac64': [-11], # SIGSEGV 295 'mac64': [-11], # SIGSEGV
296 'mach_exception': EXC_BAD_ACCESS,
288 'win32': [], 297 'win32': [],
289 'win64': [], 298 'win64': [],
290 }, 299 },
291 # This is like 'untrusted_segfault', but without the 'untrusted_' 300 # This is like 'untrusted_segfault', but without the 'untrusted_'
292 # prefix which marks the status type as expecting a 301 # prefix which marks the status type as expecting a
293 # gracefully-printed exit message from nacl_signal_common.c. This 302 # gracefully-printed exit message from nacl_signal_common.c. This
294 # is a special case because we use different methods for writing 303 # is a special case because we use different methods for writing
295 # the exception stack frame on different platforms. On Mac and 304 # the exception stack frame on different platforms. On Mac and
296 # Windows, NaCl uses a system call which will detect unwritable 305 # Windows, NaCl uses a system call which will detect unwritable
297 # pages, so the exit status appears as an unhandled fault from 306 # pages, so the exit status appears as an unhandled fault from
298 # untrusted code. On Linux, NaCl's signal handler writes the 307 # untrusted code. On Linux, NaCl's signal handler writes the
299 # frame directly, so the exit status comes from getting a SIGSEGV 308 # frame directly, so the exit status comes from getting a SIGSEGV
300 # inside the SIGSEGV handler. 309 # inside the SIGSEGV handler.
301 'unwritable_exception_stack': { 310 'unwritable_exception_stack': {
302 'linux2': [-11], # SIGSEGV 311 'linux2': [-11], # SIGSEGV
303 'mac32': [-10], # SIGBUS 312 'mac32': [-10], # SIGBUS
304 'mac64': [-10], # SIGBUS 313 'mac64': [-10], # SIGBUS
314 'mach_exception': 123,
305 'win32': win32_untrusted_crash_exit, 315 'win32': win32_untrusted_crash_exit,
306 'win64': win64_exit_via_ntdll_patch, 316 'win64': win64_exit_via_ntdll_patch,
307 }, 317 },
308 } 318 }
309 319
310 320
311 def ProcessOptions(argv): 321 def ProcessOptions(argv):
312 global GlobalPlatform 322 global GlobalPlatform
313 323
314 """Process command line options and return the unprocessed left overs.""" 324 """Process command line options and return the unprocessed left overs."""
(...skipping 28 matching lines...) Expand all
343 353
344 354
345 # Parse output for signal type and number 355 # Parse output for signal type and number
346 # 356 #
347 # The '** Signal' output is from the nacl signal handler code. 357 # The '** Signal' output is from the nacl signal handler code.
348 # 358 #
349 # Since it is possible for there to be an output race with another 359 # Since it is possible for there to be an output race with another
350 # thread, or additional output due to atexit functions, we scan the 360 # thread, or additional output due to atexit functions, we scan the
351 # output in reverse order for the signal signature. 361 # output in reverse order for the signal signature.
352 def GetNaClSignalInfoFromStderr(stderr): 362 def GetNaClSignalInfoFromStderr(stderr):
353 sigNum = None
354 sigType = 'normal'
355
356 lines = stderr.splitlines() 363 lines = stderr.splitlines()
357
358 # Scan for signal msg in reverse order 364 # Scan for signal msg in reverse order
359 for curline in reversed(lines): 365 for curline in reversed(lines):
360 words = curline.split() 366 match = re.match('\*\* (Signal|Mach exception) (\d+) from '
361 if len(words) > 4 and words[0] == '**' and words[1] == 'Signal': 367 '(trusted|untrusted) code', curline)
362 sigNum = int(words[2]) 368 if match is not None:
363 sigType = words[4] 369 return match.group(0)
364 break 370 return None
365 return sigNum, sigType 371
366 372
367 def GetQemuSignalFromStderr(stderr, default): 373 def GetQemuSignalFromStderr(stderr, default):
368 for line in reversed(stderr.splitlines()): 374 for line in reversed(stderr.splitlines()):
369 # Look for 'qemu: uncaught target signal XXX'. 375 # Look for 'qemu: uncaught target signal XXX'.
370 words = line.split() 376 words = line.split()
371 if (len(words) > 4 and 377 if (len(words) > 4 and
372 words[0] == 'qemu:' and words[1] == 'uncaught' and 378 words[0] == 'qemu:' and words[1] == 'uncaught' and
373 words[2] == 'target' and words[3] == 'signal'): 379 words[2] == 'target' and words[3] == 'signal'):
374 return -int(words[4]) 380 return -int(words[4])
375 return default 381 return default
(...skipping 29 matching lines...) Expand all
405 % FormatExitStatus(exit_status)) 411 % FormatExitStatus(exit_status))
406 return False 412 return False
407 elif len(intended_statuses) != 1: 413 elif len(intended_statuses) != 1:
408 Print('\nERROR: Command returned exit status %s but produced ' 414 Print('\nERROR: Command returned exit status %s but produced '
409 'multiple intended_exit_status lines (%s)' 415 'multiple intended_exit_status lines (%s)'
410 % (FormatExitStatus(exit_status), ', '.join(intended_statuses))) 416 % (FormatExitStatus(exit_status), ', '.join(intended_statuses)))
411 return False 417 return False
412 else: 418 else:
413 req_status = intended_statuses[0] 419 req_status = intended_statuses[0]
414 420
421 if req_status == 'unwritable_exception_stack' and sys.platform != 'linux2':
422 req_status = 'untrusted_segfault'
423
424 expected_printed_status = None
415 expected_sigtype = 'normal' 425 expected_sigtype = 'normal'
416 if req_status in status_map: 426 if req_status in status_map:
417 expected_statuses = status_map[req_status][GlobalPlatform] 427 expected_statuses = status_map[req_status][GlobalPlatform]
418 if using_nacl_signal_handler: 428 if using_nacl_signal_handler:
419 if req_status.startswith('trusted_'): 429 if req_status.startswith('trusted_'):
420 expected_sigtype = 'trusted' 430 expected_sigtype = 'trusted'
421 elif req_status.startswith('untrusted_'): 431 elif req_status.startswith('untrusted_'):
422 expected_sigtype = 'untrusted' 432 expected_sigtype = 'untrusted'
433
423 else: 434 else:
424 expected_statuses = [int(req_status)] 435 expected_statuses = [int(req_status)]
425 436
426 # On 32-bit Windows, we cannot catch a signal that occurs in x86-32 437 if expected_sigtype != 'normal':
427 # untrusted code, so it always appears as a 'normal' exit, which 438 if sys.platform == 'darwin':
428 # means that the signal handler does not print a message. 439 # Mac OS X
429 if GlobalPlatform == 'win32' and expected_sigtype == 'untrusted': 440 expected_printed_status = '** Mach exception %d from %s code' % (
430 expected_sigtype = 'normal' 441 status_map[req_status]['mach_exception'],
431 442 expected_sigtype)
432 if expected_sigtype == 'normal': 443 else:
433 expected_printed_signum = None 444 # Linux
434 else: 445 assert sys.platform != 'win32'
435 assert sys.platform != 'win32' 446 assert len(expected_statuses) == 1
436 assert len(expected_statuses) == 1 447 assert expected_statuses[0] < 0
437 assert expected_statuses[0] < 0 448 expected_printed_signum = -expected_statuses[0]
438 expected_printed_signum = -expected_statuses[0] 449 expected_printed_status = '** Signal %d from %s code' % (
439 expected_statuses = [IndirectSignal(expected_printed_signum)] 450 expected_printed_signum,
451 expected_sigtype)
452 expected_statuses = [IndirectSignal(expected_printed_signum)]
440 453
441 # If an uncaught signal occurs under QEMU (on ARM), the exit status 454 # If an uncaught signal occurs under QEMU (on ARM), the exit status
442 # contains the signal number, mangled as per IndirectSignal(). We 455 # contains the signal number, mangled as per IndirectSignal(). We
443 # extract the unadulterated signal number from QEMU's log message in 456 # extract the unadulterated signal number from QEMU's log message in
444 # stderr instead. If we are not using QEMU, or no signal is raised 457 # stderr instead. If we are not using QEMU, or no signal is raised
445 # under QEMU, this is a no-op. 458 # under QEMU, this is a no-op.
446 if stderr is not None: 459 if stderr is not None:
447 exit_status = GetQemuSignalFromStderr(stderr, exit_status) 460 exit_status = GetQemuSignalFromStderr(stderr, exit_status)
448 461
449 msg = '\nERROR: Command returned exit status %s but we expected %s' % ( 462 msg = '\nERROR: Command returned exit status %s but we expected %s' % (
450 FormatExitStatus(exit_status), 463 FormatExitStatus(exit_status),
451 ' or '.join(FormatExitStatus(value) for value in expected_statuses)) 464 ' or '.join(FormatExitStatus(value) for value in expected_statuses))
452 if exit_status not in expected_statuses: 465 if exit_status not in expected_statuses:
453 Print(msg) 466 Print(msg)
454 failed = True 467 failed = True
455 if using_nacl_signal_handler and stderr is not None: 468 if using_nacl_signal_handler and stderr is not None:
456 expected_printed = (expected_printed_signum, expected_sigtype) 469 actual_printed_status = GetNaClSignalInfoFromStderr(stderr)
457 actual_printed = GetNaClSignalInfoFromStderr(stderr) 470 msg = ('\nERROR: Command printed the signal info %r to stderr '
458 msg = ('\nERROR: Command printed the signal info %s to stderr ' 471 'but we expected %r' %
459 'but we expected %s' % 472 (actual_printed_status, expected_printed_status))
460 (actual_printed, expected_printed)) 473 if actual_printed_status != expected_printed_status:
461 if actual_printed != expected_printed:
462 Print(msg) 474 Print(msg)
463 failed = True 475 failed = True
464 476
465 return not failed 477 return not failed
466 478
467 def CheckTimeBounds(total_time): 479 def CheckTimeBounds(total_time):
468 if GlobalSettings['time_error']: 480 if GlobalSettings['time_error']:
469 if total_time > GlobalSettings['time_error']: 481 if total_time > GlobalSettings['time_error']:
470 Print('ERROR: should have taken less than %f secs' % 482 Print('ERROR: should have taken less than %f secs' %
471 (GlobalSettings['time_error'])) 483 (GlobalSettings['time_error']))
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after
678 # Bogus time, since only ProcessLogOutputCombined failed. 690 # Bogus time, since only ProcessLogOutputCombined failed.
679 Print(FailureMessage(0.0) + ' ProcessLogOutputCombined failed!') 691 Print(FailureMessage(0.0) + ' ProcessLogOutputCombined failed!')
680 return 1 692 return 1
681 return 0 693 return 0
682 694
683 if __name__ == '__main__': 695 if __name__ == '__main__':
684 retval = Main(sys.argv[1:]) 696 retval = Main(sys.argv[1:])
685 # Add some whitepsace to make the logs easier to read. 697 # Add some whitepsace to make the logs easier to read.
686 sys.stdout.write('\n\n') 698 sys.stdout.write('\n\n')
687 sys.exit(retval) 699 sys.exit(retval)
OLDNEW
« no previous file with comments | « src/trusted/service_runtime/sel_main.c ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698