diff options
Diffstat (limited to 'utils/test')
-rw-r--r-- | utils/test/README-disasm | 406 | ||||
-rw-r--r-- | utils/test/README-lldb-disasm | 94 | ||||
-rw-r--r-- | utils/test/README-run-until-faulted | 18 | ||||
-rwxr-xr-x | utils/test/disasm.py | 198 | ||||
-rwxr-xr-x | utils/test/lldb-disasm.py | 243 | ||||
-rwxr-xr-x | utils/test/llvm-mc-shell.py | 100 | ||||
-rw-r--r-- | utils/test/main.c | 14 | ||||
-rwxr-xr-x | utils/test/ras.py | 176 | ||||
-rwxr-xr-x | utils/test/run-dis.py | 125 | ||||
-rwxr-xr-x | utils/test/run-until-faulted.py | 111 |
10 files changed, 1485 insertions, 0 deletions
diff --git a/utils/test/README-disasm b/utils/test/README-disasm new file mode 100644 index 000000000000..00e9ab681a24 --- /dev/null +++ b/utils/test/README-disasm @@ -0,0 +1,406 @@ +This README describes a sample invocation of disasm.py whose purpose is to test +the low level ARM/Thumb disassembly functionality from llvm using the llvm-mc +command line. We invoke gdb on an executable, try to disassemble a function, +and then read the memory contents of the disassembled function. + +The byte contents are written into a file named disasm-input.txt and then we +invoke llvm-mc -disassemble plus options (set with the -o/--options) on the +byte contents. + +See the following for a sample session using this command: + +[16:26:57] johnny:/Volumes/data/Radar/9131529 $ /Volumes/data/lldb/svn/trunk/utils/test/disasm.py -C 'set shlib-path-substitutions /usr /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.3.sdk/usr /System /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.3.sdk/System /Library /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.3.sdk/Library' -O '-arch armv7' -m /Volumes/data/lldb/llvm/Debug+Asserts/bin/llvm-mc -e /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.3.sdk/usr/lib/libSystem.B.dylib -f printf --options='-triple=thumb-apple-darwin -debug-only=arm-disassembler' +gdb commands: ['set shlib-path-substitutions /usr /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.3.sdk/usr /System /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.3.sdk/System /Library /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.3.sdk/Library'] +gdb options: -arch armv7 +executable: /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.3.sdk/usr/lib/libSystem.B.dylib +function: printf +llvm-mc: /Volumes/data/lldb/llvm/Debug+Asserts/bin/llvm-mc +llvm-mc options: -triple=thumb-apple-darwin -debug-only=arm-disassembler +GNU gdb 6.3.50-20050815 (Apple version gdb-1518) (Sat Feb 12 02:56:02 UTC 2011) +Copyright 2004 Free Software Foundation, Inc. +GDB is free software, covered by the GNU General Public License, and you are +welcome to change it and/or distribute copies of it under certain conditions. +Type "show copying" to see the conditions. +There is absolutely no warranty for GDB. Type "show warranty" for details. +This GDB was configured as "--host=x86_64-apple-darwin --target=arm-apple-darwin". +<Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.3.sdk/Library +<eloper/SDKs/iPhoneOS4.3.sdk/usr/lib/libSystem.B.dylib +Reading symbols for shared libraries ................ done +Reading symbols from /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.3.sdk/usr/lib/libSystem.B.dylib...done. +(gdb) disassemble printf +Dump of assembler code for function printf: +0x0704cdd0 <printf+0>: push {r0, r1, r2, r3} +0x0704cdd2 <printf+2>: push {r4, r5, r7, lr} +0x0704cdd4 <printf+4>: add r7, sp, #8 +0x0704cdd6 <printf+6>: sub sp, #4 +0x0704cdd8 <printf+8>: add r3, sp, #20 +0x0704cdda <printf+10>: ldr.w r5, [r3], #4 +0x0704cdde <printf+14>: str r3, [sp, #0] +0x0704cde0 <printf+16>: ldr r3, [pc, #52] (0x704ce18 <printf+72>) +0x0704cde2 <printf+18>: add r3, pc +0x0704cde4 <printf+20>: ldr r0, [r3, #0] +0x0704cde6 <printf+22>: ldr r4, [r0, #0] +0x0704cde8 <printf+24>: ldr r0, [pc, #48] (0x704ce1c <printf+76>) +0x0704cdea <printf+26>: add r0, pc +0x0704cdec <printf+28>: ldr r0, [r0, #0] +0x0704cdee <printf+30>: ldr r0, [r0, #0] +0x0704cdf0 <printf+32>: blx 0x707ba30 <pthread_getspecific> +0x0704cdf4 <printf+36>: cbnz r0, 0x704cdfe <printf+46> +0x0704cdf6 <printf+38>: ldr r1, [pc, #40] (0x704ce20 <printf+80>) +0x0704cdf8 <printf+40>: add r1, pc +0x0704cdfa <printf+42>: ldr r1, [r1, #0] +0x0704cdfc <printf+44>: b.n 0x704ce00 <printf+48> +0x0704cdfe <printf+46>: mov r1, r0 +0x0704ce00 <printf+48>: mov r0, r4 +0x0704ce02 <printf+50>: mov r2, r5 +0x0704ce04 <printf+52>: ldr r3, [sp, #0] +0x0704ce06 <printf+54>: bl 0x704ad44 <vfprintf_l> +0x0704ce0a <printf+58>: sub.w sp, r7, #8 ; 0x8 +0x0704ce0e <printf+62>: ldmia.w sp!, {r4, r5, r7, lr} +0x0704ce12 <printf+66>: add sp, #16 +0x0704ce14 <printf+68>: bx lr +0x0704ce16 <printf+70>: nop +0x0704ce18 <printf+72>: movs r3, #142 +0x0704ce1a <printf+74>: lsls r5, r0, #0 +0x0704ce1c <printf+76>: adds r1, #122 +0x0704ce1e <printf+78>: lsls r5, r0, #0 +0x0704ce20 <printf+80>: adds r1, #104 +0x0704ce22 <printf+82>: lsls r5, r0, #0 +End of assembler dump. +(gdb) x /2b 0x0704cdd0 +0x704cdd0 <printf>: 0x0f 0xb4 +(gdb) x /2b 0x0704cdd2 +0x704cdd2 <printf+2>: 0xb0 0xb5 +(gdb) x /2b 0x0704cdd4 +0x704cdd4 <printf+4>: 0x02 0xaf +(gdb) x /2b 0x0704cdd6 +0x704cdd6 <printf+6>: 0x81 0xb0 +(gdb) x /2b 0x0704cdd8 +0x704cdd8 <printf+8>: 0x05 0xab +(gdb) x /4b 0x0704cdda +0x704cdda <printf+10>: 0x53 0xf8 0x04 0x5b +(gdb) x /2b 0x0704cdde +0x704cdde <printf+14>: 0x00 0x93 +(gdb) x /2b 0x0704cde0 +0x704cde0 <printf+16>: 0x0d 0x4b +(gdb) x /2b 0x0704cde2 +0x704cde2 <printf+18>: 0x7b 0x44 +(gdb) x /2b 0x0704cde4 +0x704cde4 <printf+20>: 0x18 0x68 +(gdb) x /2b 0x0704cde6 +0x704cde6 <printf+22>: 0x04 0x68 +(gdb) x /2b 0x0704cde8 +0x704cde8 <printf+24>: 0x0c 0x48 +(gdb) x /2b 0x0704cdea +0x704cdea <printf+26>: 0x78 0x44 +(gdb) x /2b 0x0704cdec +0x704cdec <printf+28>: 0x00 0x68 +(gdb) x /2b 0x0704cdee +0x704cdee <printf+30>: 0x00 0x68 +(gdb) x /4b 0x0704cdf0 +0x704cdf0 <printf+32>: 0x2e 0xf0 0x1e 0xee +(gdb) x /2b 0x0704cdf4 +0x704cdf4 <printf+36>: 0x18 0xb9 +(gdb) x /2b 0x0704cdf6 +0x704cdf6 <printf+38>: 0x0a 0x49 +(gdb) x /2b 0x0704cdf8 +0x704cdf8 <printf+40>: 0x79 0x44 +(gdb) x /2b 0x0704cdfa +0x704cdfa <printf+42>: 0x09 0x68 +(gdb) x /2b 0x0704cdfc +0x704cdfc <printf+44>: 0x00 0xe0 +(gdb) x /2b 0x0704cdfe +0x704cdfe <printf+46>: 0x01 0x46 +(gdb) x /2b 0x0704ce00 +0x704ce00 <printf+48>: 0x20 0x46 +(gdb) x /2b 0x0704ce02 +0x704ce02 <printf+50>: 0x2a 0x46 +(gdb) x /2b 0x0704ce04 +0x704ce04 <printf+52>: 0x00 0x9b +(gdb) x /4b 0x0704ce06 +0x704ce06 <printf+54>: 0xfd 0xf7 0x9d 0xff +(gdb) x /4b 0x0704ce0a +0x704ce0a <printf+58>: 0xa7 0xf1 0x08 0x0d +(gdb) x /4b 0x0704ce0e +0x704ce0e <printf+62>: 0xbd 0xe8 0xb0 0x40 +(gdb) x /2b 0x0704ce12 +0x704ce12 <printf+66>: 0x04 0xb0 +(gdb) x /2b 0x0704ce14 +0x704ce14 <printf+68>: 0x70 0x47 +(gdb) x /2b 0x0704ce16 +0x704ce16 <printf+70>: 0x00 0xbf +(gdb) x /2b 0x0704ce18 +0x704ce18 <printf+72>: 0x8e 0x23 +(gdb) x /2b 0x0704ce1a +0x704ce1a <printf+74>: 0x05 0x00 +(gdb) x /2b 0x0704ce1c +0x704ce1c <printf+76>: 0x7a 0x31 +(gdb) x /2b 0x0704ce1e +0x704ce1e <printf+78>: 0x05 0x00 +(gdb) x /2b 0x0704ce20 +0x704ce20 <printf+80>: 0x68 0x31 +(gdb) x /2b 0x0704ce22 +0x704ce22 <printf+82>: 0x05 0x00 +(gdb) quit + +Executing command: /Volumes/data/lldb/llvm/Debug+Asserts/bin/llvm-mc -disassemble -triple=thumb-apple-darwin -debug-only=arm-disassembler disasm-input.txt +Opcode=2305 Name=tPUSH Format=ARM_FORMAT_THUMBFRM(25) + 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +------------------------------------------------------------------------------------------------- +| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 1: 0: 1: 1| 0: 1: 0: 0| 0: 0: 0: 0| 1: 1: 1: 1| +------------------------------------------------------------------------------------------------- + + push {r0, r1, r2, r3} +Opcode=2305 Name=tPUSH Format=ARM_FORMAT_THUMBFRM(25) + 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +------------------------------------------------------------------------------------------------- +| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 1: 0: 1: 1| 0: 1: 0: 1| 1: 0: 1: 1| 0: 0: 0: 0| +------------------------------------------------------------------------------------------------- + + push {r4, r5, r7, lr} +Opcode=2228 Name=tADDrSPi Format=ARM_FORMAT_THUMBFRM(25) + 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +------------------------------------------------------------------------------------------------- +| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 1: 0: 1: 0| 1: 1: 1: 1| 0: 0: 0: 0| 0: 0: 1: 0| +------------------------------------------------------------------------------------------------- + + add r7, sp, #8 +Opcode=2328 Name=tSUBspi Format=ARM_FORMAT_THUMBFRM(25) + 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +------------------------------------------------------------------------------------------------- +| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 1: 0: 1: 1| 0: 0: 0: 0| 1: 0: 0: 0| 0: 0: 0: 1| +------------------------------------------------------------------------------------------------- + + sub sp, #4 +Opcode=2228 Name=tADDrSPi Format=ARM_FORMAT_THUMBFRM(25) + 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +------------------------------------------------------------------------------------------------- +| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 1: 0: 1: 0| 1: 0: 1: 1| 0: 0: 0: 0| 0: 1: 0: 1| +------------------------------------------------------------------------------------------------- + + add r3, sp, #20 +Opcode=1963 Name=t2LDR_POST Format=ARM_FORMAT_THUMBFRM(25) + 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +------------------------------------------------------------------------------------------------- +| 1: 1: 1: 1| 1: 0: 0: 0| 0: 1: 0: 1| 0: 0: 1: 1| 0: 1: 0: 1| 1: 0: 1: 1| 0: 0: 0: 0| 0: 1: 0: 0| +------------------------------------------------------------------------------------------------- + + ldr r5, [r3], #4 +Opcode=2324 Name=tSTRspi Format=ARM_FORMAT_THUMBFRM(25) + 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +------------------------------------------------------------------------------------------------- +| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 1: 0: 0: 1| 0: 0: 1: 1| 0: 0: 0: 0| 0: 0: 0: 0| +------------------------------------------------------------------------------------------------- + + str r3, [sp] +Opcode=2275 Name=tLDRpci Format=ARM_FORMAT_THUMBFRM(25) + 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +------------------------------------------------------------------------------------------------- +| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 1: 0: 0| 1: 0: 1: 1| 0: 0: 0: 0| 1: 1: 0: 1| +------------------------------------------------------------------------------------------------- + + ldr.n r3, #52 +Opcode=2223 Name=tADDhirr Format=ARM_FORMAT_THUMBFRM(25) + 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +------------------------------------------------------------------------------------------------- +| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 1: 0: 0| 0: 1: 0: 0| 0: 1: 1: 1| 1: 0: 1: 1| +------------------------------------------------------------------------------------------------- + + add r3, pc +Opcode=2274 Name=tLDRi Format=ARM_FORMAT_THUMBFRM(25) + 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +------------------------------------------------------------------------------------------------- +| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 1: 1: 0| 1: 0: 0: 0| 0: 0: 0: 1| 1: 0: 0: 0| +------------------------------------------------------------------------------------------------- + + ldr r0, [r3] +Opcode=2274 Name=tLDRi Format=ARM_FORMAT_THUMBFRM(25) + 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +------------------------------------------------------------------------------------------------- +| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 1: 1: 0| 1: 0: 0: 0| 0: 0: 0: 0| 0: 1: 0: 0| +------------------------------------------------------------------------------------------------- + + ldr r4, [r0] +Opcode=2275 Name=tLDRpci Format=ARM_FORMAT_THUMBFRM(25) + 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +------------------------------------------------------------------------------------------------- +| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 1: 0: 0| 1: 0: 0: 0| 0: 0: 0: 0| 1: 1: 0: 0| +------------------------------------------------------------------------------------------------- + + ldr.n r0, #48 +Opcode=2223 Name=tADDhirr Format=ARM_FORMAT_THUMBFRM(25) + 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +------------------------------------------------------------------------------------------------- +| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 1: 0: 0| 0: 1: 0: 0| 0: 1: 1: 1| 1: 0: 0: 0| +------------------------------------------------------------------------------------------------- + + add r0, pc +Opcode=2274 Name=tLDRi Format=ARM_FORMAT_THUMBFRM(25) + 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +------------------------------------------------------------------------------------------------- +| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 1: 1: 0| 1: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| +------------------------------------------------------------------------------------------------- + + ldr r0, [r0] +Opcode=2274 Name=tLDRi Format=ARM_FORMAT_THUMBFRM(25) + 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +------------------------------------------------------------------------------------------------- +| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 1: 1: 0| 1: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| +------------------------------------------------------------------------------------------------- + + ldr r0, [r0] +Opcode=2243 Name=tBLXi_r9 Format=ARM_FORMAT_THUMBFRM(25) + 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +------------------------------------------------------------------------------------------------- +| 1: 1: 1: 1| 0: 0: 0: 0| 0: 0: 1: 0| 1: 1: 1: 0| 1: 1: 1: 0| 1: 1: 1: 0| 0: 0: 0: 1| 1: 1: 1: 0| +------------------------------------------------------------------------------------------------- + + blx #191548 +Opcode=2255 Name=tCBNZ Format=ARM_FORMAT_THUMBFRM(25) + 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +------------------------------------------------------------------------------------------------- +| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 1: 0: 1: 1| 1: 0: 0: 1| 0: 0: 0: 1| 1: 0: 0: 0| +------------------------------------------------------------------------------------------------- + + cbnz r0, #6 +Opcode=2275 Name=tLDRpci Format=ARM_FORMAT_THUMBFRM(25) + 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +------------------------------------------------------------------------------------------------- +| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 1: 0: 0| 1: 0: 0: 1| 0: 0: 0: 0| 1: 0: 1: 0| +------------------------------------------------------------------------------------------------- + + ldr.n r1, #40 +Opcode=2223 Name=tADDhirr Format=ARM_FORMAT_THUMBFRM(25) + 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +------------------------------------------------------------------------------------------------- +| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 1: 0: 0| 0: 1: 0: 0| 0: 1: 1: 1| 1: 0: 0: 1| +------------------------------------------------------------------------------------------------- + + add r1, pc +Opcode=2274 Name=tLDRi Format=ARM_FORMAT_THUMBFRM(25) + 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +------------------------------------------------------------------------------------------------- +| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 1: 1: 0| 1: 0: 0: 0| 0: 0: 0: 0| 1: 0: 0: 1| +------------------------------------------------------------------------------------------------- + + ldr r1, [r1] +Opcode=2238 Name=tB Format=ARM_FORMAT_THUMBFRM(25) + 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +------------------------------------------------------------------------------------------------- +| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 1: 1: 1: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| +------------------------------------------------------------------------------------------------- + + b #0 +Opcode=2294 Name=tMOVr Format=ARM_FORMAT_THUMBFRM(25) + 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +------------------------------------------------------------------------------------------------- +| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 1: 0: 0| 0: 1: 1: 0| 0: 0: 0: 0| 0: 0: 0: 1| +------------------------------------------------------------------------------------------------- + + mov r1, r0 +Opcode=2294 Name=tMOVr Format=ARM_FORMAT_THUMBFRM(25) + 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +------------------------------------------------------------------------------------------------- +| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 1: 0: 0| 0: 1: 1: 0| 0: 0: 1: 0| 0: 0: 0: 0| +------------------------------------------------------------------------------------------------- + + mov r0, r4 +Opcode=2294 Name=tMOVr Format=ARM_FORMAT_THUMBFRM(25) + 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +------------------------------------------------------------------------------------------------- +| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 1: 0: 0| 0: 1: 1: 0| 0: 0: 1: 0| 1: 0: 1: 0| +------------------------------------------------------------------------------------------------- + + mov r2, r5 +Opcode=2278 Name=tLDRspi Format=ARM_FORMAT_THUMBFRM(25) + 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +------------------------------------------------------------------------------------------------- +| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 1: 0: 0: 1| 1: 0: 1: 1| 0: 0: 0: 0| 0: 0: 0: 0| +------------------------------------------------------------------------------------------------- + + ldr r3, [sp] +Opcode=2246 Name=tBLr9 Format=ARM_FORMAT_THUMBFRM(25) + 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +------------------------------------------------------------------------------------------------- +| 1: 1: 1: 1| 0: 1: 1: 1| 1: 1: 1: 1| 1: 1: 0: 1| 1: 1: 1: 1| 1: 1: 1: 1| 1: 0: 0: 1| 1: 1: 0: 1| +------------------------------------------------------------------------------------------------- + + bl #-8390 +Opcode=2153 Name=t2SUBri Format=ARM_FORMAT_THUMBFRM(25) + 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +------------------------------------------------------------------------------------------------- +| 1: 1: 1: 1| 0: 0: 0: 1| 1: 0: 1: 0| 0: 1: 1: 1| 0: 0: 0: 0| 1: 1: 0: 1| 0: 0: 0: 0| 1: 0: 0: 0| +------------------------------------------------------------------------------------------------- + + sub.w sp, r7, #8 +Opcode=1926 Name=t2LDMIA_UPD Format=ARM_FORMAT_THUMBFRM(25) + 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +------------------------------------------------------------------------------------------------- +| 1: 1: 1: 0| 1: 0: 0: 0| 1: 0: 1: 1| 1: 1: 0: 1| 0: 1: 0: 0| 0: 0: 0: 0| 1: 0: 1: 1| 0: 0: 0: 0| +------------------------------------------------------------------------------------------------- + + pop.w {r4, r5, r7, lr} +Opcode=2230 Name=tADDspi Format=ARM_FORMAT_THUMBFRM(25) + 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +------------------------------------------------------------------------------------------------- +| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 1: 0: 1: 1| 0: 0: 0: 0| 0: 0: 0: 0| 0: 1: 0: 0| +------------------------------------------------------------------------------------------------- + + add sp, #16 +Opcode=2250 Name=tBX_RET Format=ARM_FORMAT_THUMBFRM(25) + 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +------------------------------------------------------------------------------------------------- +| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 1: 0: 0| 0: 1: 1: 1| 0: 1: 1: 1| 0: 0: 0: 0| +------------------------------------------------------------------------------------------------- + + bx lr +Opcode=2300 Name=tNOP Format=ARM_FORMAT_THUMBFRM(25) + 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +------------------------------------------------------------------------------------------------- +| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 1: 0: 1: 1| 1: 1: 1: 1| 0: 0: 0: 0| 0: 0: 0: 0| +------------------------------------------------------------------------------------------------- + + nop +Opcode=2293 Name=tMOVi8 Format=ARM_FORMAT_THUMBFRM(25) + 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +------------------------------------------------------------------------------------------------- +| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 1: 0| 0: 0: 1: 1| 1: 0: 0: 0| 1: 1: 1: 0| +------------------------------------------------------------------------------------------------- + + movs r3, #142 +Opcode=2290 Name=tMOVSr Format=ARM_FORMAT_THUMBFRM(25) + 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +------------------------------------------------------------------------------------------------- +| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 1: 0: 1| +------------------------------------------------------------------------------------------------- + + movs r5, r0 +Opcode=2225 Name=tADDi8 Format=ARM_FORMAT_THUMBFRM(25) + 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +------------------------------------------------------------------------------------------------- +| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 1: 1| 0: 0: 0: 1| 0: 1: 1: 1| 1: 0: 1: 0| +------------------------------------------------------------------------------------------------- + + adds r1, #122 +Opcode=2290 Name=tMOVSr Format=ARM_FORMAT_THUMBFRM(25) + 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +------------------------------------------------------------------------------------------------- +| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 1: 0: 1| +------------------------------------------------------------------------------------------------- + + movs r5, r0 +Opcode=2225 Name=tADDi8 Format=ARM_FORMAT_THUMBFRM(25) + 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +------------------------------------------------------------------------------------------------- +| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 1: 1| 0: 0: 0: 1| 0: 1: 1: 0| 1: 0: 0: 0| +------------------------------------------------------------------------------------------------- + + adds r1, #104 +Opcode=2290 Name=tMOVSr Format=ARM_FORMAT_THUMBFRM(25) + 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +------------------------------------------------------------------------------------------------- +| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 1: 0: 1| +------------------------------------------------------------------------------------------------- + + movs r5, r0 +[16:28:00] johnny:/Volumes/data/Radar/9131529 $ diff --git a/utils/test/README-lldb-disasm b/utils/test/README-lldb-disasm new file mode 100644 index 000000000000..328658c326b1 --- /dev/null +++ b/utils/test/README-lldb-disasm @@ -0,0 +1,94 @@ +This README describes a sample invocation of lldb-disasm.py whose purpose is to test +the lldb 'disassemble' command. + +This is for the initial checkin of lldb-disasm.py which only reads an executable image and +dumps the symbol table from the imgae and its dependent libraries. The output was cut off +since it is too large. + +da0603a-dhcp191:9131529 johnny$ /Volumes/data/lldb/svn/trunk/utils/test/lldb-disasm.py -C 'platform create remote-ios' -e /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.3.sdk/usr/lib/libSystem.B.dylib +lldb commands: ['platform create remote-ios'] +lldb options: None +executable: /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.3.sdk/usr/lib/libSystem.B.dylib +sys.path: ['/Volumes/data/lldb/svn/trunk/utils/test', '/Volumes/data/lldb/svn/trunk/build/Debug/LLDB.framework/Resources/Python', '/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python26.zip', '/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6', '/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/plat-darwin', '/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/plat-mac', '/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/plat-mac/lib-scriptpackages', '/System/Library/Frameworks/Python.framework/Versions/2.6/Extras/lib/python', '/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/lib-tk', '/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/lib-old', '/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/lib-dynload', '/Library/Python/2.6/site-packages', '/AppleInternal/Library/Python/2.6/site-packages', '/System/Library/Frameworks/Python.framework/Versions/2.6/Extras/lib/python/PyObjC', '/System/Library/Frameworks/Python.framework/Versions/2.6/Extras/lib/python/wx-2.8-mac-unicode', '/Volumes/data/lldb/svn/trunk/utils/test/../../test/pexpect-2.4', '/Volumes/data/lldb/svn/trunk/test'] +/Volumes/data/lldb/svn/trunk/test/lldbutil.py:80: SyntaxWarning: import * only allowed at module level + def int_to_bytearray(val, bytesize): +/Volumes/data/lldb/svn/trunk/test/lldbutil.py:105: SyntaxWarning: import * only allowed at module level + def bytearray_to_int(bytes, bytesize): +run command: platform create remote-ios +output: Platform: remote-ios +Not connected to a remote platform. +SDKROOT: "/Developer/Platforms/iPhoneOS.platform/DeviceSupport/4.3 (8F190)" + +run command: file /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.3.sdk/usr/lib/libSystem.B.dylib +output: Current executable set to '/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.3.sdk/usr/lib/libSystem.B.dylib' (armv7). + +run command: image dump symtab +output: Dumping symbol table for 18 modules. +Symtab, file = /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.3.sdk/usr/lib/libSystem.B.dylib, num_symbols = 851: + Debug symbol + |Synthetic symbol + ||Externally Visible + ||| +Index UserID DSX Type File Address/Value Load Address Size Flags Name +------- ------ --- ------------ ------------------ ------------------ ------------------ ---------- ---------------------------------- +[ 0] 0 Code 0x0000000000001420 0x0000000000000000 0x000e0008 libSystem_initializer +[ 1] 1 Code 0x00000000000014c4 0x0000000000000000 0x001e0008 __keymgr_initializer +[ 2] 2 Code 0x00000000000014fc 0x0000000000000000 0x000e0008 dwarf2_unwind_dyld_add_image_hook +[ 3] 3 Code 0x0000000000001564 0x0000000000000000 0x000e0008 get_or_create_key_element +[ 4] 4 Code 0x0000000000001684 0x0000000000000000 0x000e0008 unlock_node +[ 5] 5 Code 0x0000000000001930 0x0000000000000000 0x000e0000 RsqrtTable +[ 6] 6 Code 0x0000000000001c30 0x0000000000000000 0x000e0000 acosf_crossover +[ 7] 7 Code 0x0000000000001c34 0x0000000000000000 0x000e0000 acosf_mid_poly +[ 8] 8 Code 0x0000000000001c48 0x0000000000000000 0x000e0000 Pi2_Q30 +[ 9] 9 Code 0x0000000000001c4c 0x0000000000000000 0x000e0000 Pi_Q30 +[ 10] 10 Code 0x0000000000001c78 0x0000000000000000 0x000e0000 acosf_approx +[ 11] 11 Code 0x0000000000001cec 0x0000000000000000 0x000e0000 acosf_pos_tail_poly +[ 12] 12 Code 0x0000000000001d00 0x0000000000000000 0x000e0000 acosf_tail +[ 13] 13 Code 0x0000000000001dfc 0x0000000000000000 0x000e0000 acosf_normalize +[ 14] 14 Code 0x0000000000001e10 0x0000000000000000 0x000e0000 acosf_round +[ 15] 15 Code 0x0000000000001e28 0x0000000000000000 0x000e0000 acosf_encode +[ 16] 16 Code 0x0000000000001e30 0x0000000000000000 0x000e0000 acosf_done +[ 17] 17 Code 0x0000000000001e38 0x0000000000000000 0x000e0000 acosf_special +[ 18] 18 Code 0x0000000000001e68 0x0000000000000000 0x000e0000 acosf_small +[ 19] 19 Code 0x0000000000001e9c 0x0000000000000000 0x000e0000 acosf_very_small +[ 20] 20 Code 0x0000000000001eb8 0x0000000000000000 0x000e0000 Pif +[ 21] 21 Code 0x000000000000220c 0x0000000000000000 0x000e0000 RsqrtTable +[ 22] 22 Code 0x000000000000250c 0x0000000000000000 0x000e0000 asinf_crossover +[ 23] 23 Code 0x0000000000002510 0x0000000000000000 0x000e0000 asinf_mid_poly +[ 24] 24 Code 0x0000000000002524 0x0000000000000000 0x000e0000 Pi2_Q30 +[ 25] 25 Code 0x0000000000002550 0x0000000000000000 0x000e0000 asinf_approx +[ 26] 26 Code 0x00000000000025e4 0x0000000000000000 0x000e0000 asinf_tail_poly +[ 27] 27 Code 0x0000000000002600 0x0000000000000000 0x000e0000 asinf_tail +[ 28] 28 Code 0x00000000000026e0 0x0000000000000000 0x000e0000 asinf_normalize +[ 29] 29 Code 0x00000000000026f4 0x0000000000000000 0x000e0000 asinf_round +[ 30] 30 Code 0x000000000000270c 0x0000000000000000 0x000e0000 asinf_encode +[ 31] 31 Code 0x0000000000002718 0x0000000000000000 0x000e0000 asinf_done +[ 32] 32 Code 0x0000000000002720 0x0000000000000000 0x000e0000 asinf_special +[ 33] 33 Code 0x0000000000002754 0x0000000000000000 0x000e0000 asinf_small +[ 34] 34 Code 0x0000000000002784 0x0000000000000000 0x000e0000 Pi2f +[ 35] 35 Code 0x0000000000005774 0x0000000000000000 0x000e0008 rem_pio2 +[ 36] 36 Code 0x00000000000076c4 0x0000000000000000 0x000e0008 __kernel_rem_pio2 +[ 37] 37 Code 0x0000000000008c90 0x0000000000000000 0x000e0008 __kernel_tan +[ 38] 38 Code 0x0000000000008ef0 0x0000000000000000 0x000e0008 lgammaApprox +[ 39] 39 Code 0x000000000000b3d4 0x0000000000000000 0x000e0000 powf_not_special +[ 40] 40 Code 0x000000000000b3dc 0x0000000000000000 0x000e0000 powf_ylgx +[ 41] 41 Code 0x000000000000b438 0x0000000000000000 0x000e0000 powf_done +[ 42] 42 Code 0x000000000000b43c 0x0000000000000000 0x000e0000 powf_special_y +[ 43] 43 Code 0x000000000000b4a8 0x0000000000000000 0x000e0000 powf_special_x +[ 44] 44 Code 0x000000000000b4cc 0x0000000000000000 0x000e0000 powf_mzero_minf +[ 45] 45 Code 0x000000000000b54c 0x0000000000000000 0x000e0000 powf_y_odd +[ 46] 46 Code 0x000000000000b57c 0x0000000000000000 0x000e0000 powf_y_nonint +[ 47] 47 Code 0x000000000000b588 0x0000000000000000 0x000e0000 powf_y_even +[ 48] 48 Code 0x000000000000b7a8 0x0000000000000000 0x000e0000 powf_log2_reduction +[ 49] 49 Code 0x000000000000b7a8 0x0000000000000000 0x000e0000 powf_log2 +[ 50] 50 Code 0x000000000000b814 0x0000000000000000 0x000e0000 powf_log2_approx +[ 51] 51 Code 0x000000000000b88c 0x0000000000000000 0x000e0000 powf_log2_synthesis +[ 52] 52 Code 0x000000000000b960 0x0000000000000000 0x000e0000 powf_log2_exactPowerOfTwo +[ 53] 53 Code 0x000000000000b980 0x0000000000000000 0x000e0000 powf_log2_near1 +[ 54] 54 Code 0x000000000000b9ec 0x0000000000000000 0x000e0000 powf_log2_synthesis_near1 +[ 55] 55 Code 0x000000000000ba04 0x0000000000000000 0x000e0000 Q32_minimax +[ 56] 56 Code 0x000000000000ba10 0x0000000000000000 0x000e0000 iexp2_lut +[ 57] 57 Code 0x000000000000ba94 0x0000000000000000 0x000e0000 powf_exp2 +[ 58] 58 Code 0x000000000000bb18 0x0000000000000000 0x000e0000 powf_exp2_exact_int +[ 59] 59 Code 0x000000000000bb24 0x0000000000000000 0x000e0000 powf_exp2_big +[ 60] 60 Code 0x000000000000bb74 0x0000000000000000 0x000e0000 powf_exp2_overflow diff --git a/utils/test/README-run-until-faulted b/utils/test/README-run-until-faulted new file mode 100644 index 000000000000..f89f8636d627 --- /dev/null +++ b/utils/test/README-run-until-faulted @@ -0,0 +1,18 @@ +A example usage of the Python script run-until-faulted.py: + +[18:20:29] johnny:/Volumes/data/lldb/svn/trunk/utils/test $ ./run-until-faulted.py -l /Volumes/data/lldb/svn/trunk/build/Debug/lldb -e './a.out' +lldb command: /Volumes/data/lldb/svn/trunk/build/Debug/lldb +executable: ./a.out +executable options: +sending file command.... +sending process launch -- (iteration: 0) + +* thread #1: tid = 0x2d03, 0x0000000100000eef a.out`main + 39 at main.c:7, stop reason = EXC_BAD_ACCESS (code=1, address=0x0) + 4 { + 5 int *null_ptr = 0; + 6 printf("Hello, fault!\n"); +-> 7 printf("Now segfault %d\n", *null_ptr); + 8 } + +(lldb) q +[18:20:40] johnny:/Volumes/data/lldb/svn/trunk/utils/test $ diff --git a/utils/test/disasm.py b/utils/test/disasm.py new file mode 100755 index 000000000000..46660299f188 --- /dev/null +++ b/utils/test/disasm.py @@ -0,0 +1,198 @@ +#!/usr/bin/env python + +""" +Run gdb to disassemble a function, feed the bytes to 'llvm-mc -disassemble' command, +and display the disassembly result. + +""" + +import os +import sys +from optparse import OptionParser + +def is_exe(fpath): + """Check whether fpath is an executable.""" + return os.path.isfile(fpath) and os.access(fpath, os.X_OK) + +def which(program): + """Find the full path to a program, or return None.""" + fpath, fname = os.path.split(program) + if fpath: + if is_exe(program): + return program + else: + for path in os.environ["PATH"].split(os.pathsep): + exe_file = os.path.join(path, program) + if is_exe(exe_file): + return exe_file + return None + +def do_llvm_mc_disassembly(gdb_commands, gdb_options, exe, func, mc, mc_options): + from cStringIO import StringIO + import pexpect + + gdb_prompt = "\r\n\(gdb\) " + gdb = pexpect.spawn(('gdb %s' % gdb_options) if gdb_options else 'gdb') + # Turn on logging for what gdb sends back. + gdb.logfile_read = sys.stdout + gdb.expect(gdb_prompt) + + # See if there any extra command(s) to execute before we issue the file command. + for cmd in gdb_commands: + gdb.sendline(cmd) + gdb.expect(gdb_prompt) + + # Now issue the file command. + gdb.sendline('file %s' % exe) + gdb.expect(gdb_prompt) + + # Send the disassemble command. + gdb.sendline('disassemble %s' % func) + gdb.expect(gdb_prompt) + + # Get the output from gdb. + gdb_output = gdb.before + + # Use StringIO to record the memory dump as well as the gdb assembler code. + mc_input = StringIO() + + # These keep track of the states of our simple gdb_output parser. + prev_line = None + prev_addr = None + curr_addr = None + addr_diff = 0 + looking = False + for line in gdb_output.split(os.linesep): + if line.startswith('Dump of assembler code'): + looking = True + continue + + if line.startswith('End of assembler dump.'): + looking = False + prev_addr = curr_addr + if mc_options and mc_options.find('arm') != -1: + addr_diff = 4 + if mc_options and mc_options.find('thumb') != -1: + # It is obviously wrong to assume the last instruction of the + # function has two bytes. + # FIXME + addr_diff = 2 + + if looking and line.startswith('0x'): + # It's an assembler code dump. + prev_addr = curr_addr + curr_addr = line.split(None, 1)[0] + if prev_addr and curr_addr: + addr_diff = int(curr_addr, 16) - int(prev_addr, 16) + + if prev_addr and addr_diff > 0: + # Feed the examining memory command to gdb. + gdb.sendline('x /%db %s' % (addr_diff, prev_addr)) + gdb.expect(gdb_prompt) + x_output = gdb.before + # Get the last output line from the gdb examine memory command, + # split the string into a 3-tuple with separator '>:' to handle + # objc method names. + memory_dump = x_output.split(os.linesep)[-1].partition('>:')[2].strip() + #print "\nbytes:", memory_dump + disasm_str = prev_line.partition('>:')[2] + print >> mc_input, '%s # %s' % (memory_dump, disasm_str) + + # We're done with the processing. Assign the current line to be prev_line. + prev_line = line + + # Close the gdb session now that we are done with it. + gdb.sendline('quit') + gdb.expect(pexpect.EOF) + gdb.close() + + # Write the memory dump into a file. + with open('disasm-input.txt', 'w') as f: + f.write(mc_input.getvalue()) + + mc_cmd = '%s -disassemble %s disasm-input.txt' % (mc, mc_options) + print "\nExecuting command:", mc_cmd + os.system(mc_cmd) + + # And invoke llvm-mc with the just recorded file. + #mc = pexpect.spawn('%s -disassemble %s disasm-input.txt' % (mc, mc_options)) + #mc.logfile_read = sys.stdout + #print "mc:", mc + #mc.close() + + +def main(): + # This is to set up the Python path to include the pexpect-2.4 dir. + # Remember to update this when/if things change. + scriptPath = sys.path[0] + sys.path.append(os.path.join(scriptPath, os.pardir, os.pardir, 'test', 'pexpect-2.4')) + + parser = OptionParser(usage="""\ +Run gdb to disassemble a function, feed the bytes to 'llvm-mc -disassemble' command, +and display the disassembly result. + +Usage: %prog [options] +""") + parser.add_option('-C', '--gdb-command', + type='string', action='append', metavar='COMMAND', + default=[], dest='gdb_commands', + help='Command(s) gdb executes after starting up (can be empty)') + parser.add_option('-O', '--gdb-options', + type='string', action='store', + dest='gdb_options', + help="""The options passed to 'gdb' command if specified.""") + parser.add_option('-e', '--executable', + type='string', action='store', + dest='executable', + help="""The executable to do disassembly on.""") + parser.add_option('-f', '--function', + type='string', action='store', + dest='function', + help="""The function name (could be an address to gdb) for disassembly.""") + parser.add_option('-m', '--llvm-mc', + type='string', action='store', + dest='llvm_mc', + help="""The llvm-mc executable full path, if specified. + Otherwise, it must be present in your PATH environment.""") + + parser.add_option('-o', '--options', + type='string', action='store', + dest='llvm_mc_options', + help="""The options passed to 'llvm-mc -disassemble' command if specified.""") + + opts, args = parser.parse_args() + + gdb_commands = opts.gdb_commands + gdb_options = opts.gdb_options + + if not opts.executable: + parser.print_help() + sys.exit(1) + executable = opts.executable + + if not opts.function: + parser.print_help() + sys.exit(1) + function = opts.function + + llvm_mc = opts.llvm_mc if opts.llvm_mc else which('llvm-mc') + if not llvm_mc: + parser.print_help() + sys.exit(1) + + # This is optional. For example: + # --options='-triple=arm-apple-darwin -debug-only=arm-disassembler' + llvm_mc_options = opts.llvm_mc_options + + # We have parsed the options. + print "gdb commands:", gdb_commands + print "gdb options:", gdb_options + print "executable:", executable + print "function:", function + print "llvm-mc:", llvm_mc + print "llvm-mc options:", llvm_mc_options + + do_llvm_mc_disassembly(gdb_commands, gdb_options, executable, function, llvm_mc, llvm_mc_options) + +if __name__ == '__main__': + main() diff --git a/utils/test/lldb-disasm.py b/utils/test/lldb-disasm.py new file mode 100755 index 000000000000..7987c6b01c37 --- /dev/null +++ b/utils/test/lldb-disasm.py @@ -0,0 +1,243 @@ +#!/usr/bin/env python + +""" +Run lldb to disassemble all the available functions for an executable image. + +""" + +import os +import re +import sys +from optparse import OptionParser + +def setupSysPath(): + """ + Add LLDB.framework/Resources/Python and the test dir to the sys.path. + """ + # Get the directory containing the current script. + scriptPath = sys.path[0] + if not scriptPath.endswith(os.path.join('utils', 'test')): + print "This script expects to reside in lldb's utils/test directory." + sys.exit(-1) + + # This is our base name component. + base = os.path.abspath(os.path.join(scriptPath, os.pardir, os.pardir)) + + # This is for the goodies in the test directory under base. + sys.path.append(os.path.join(base,'test')) + + # These are for xcode build directories. + xcode3_build_dir = ['build'] + xcode4_build_dir = ['build', 'lldb', 'Build', 'Products'] + dbg = ['Debug'] + rel = ['Release'] + bai = ['BuildAndIntegration'] + python_resource_dir = ['LLDB.framework', 'Resources', 'Python'] + + dbgPath = os.path.join(base, *(xcode3_build_dir + dbg + python_resource_dir)) + dbgPath2 = os.path.join(base, *(xcode4_build_dir + dbg + python_resource_dir)) + relPath = os.path.join(base, *(xcode3_build_dir + rel + python_resource_dir)) + relPath2 = os.path.join(base, *(xcode4_build_dir + rel + python_resource_dir)) + baiPath = os.path.join(base, *(xcode3_build_dir + bai + python_resource_dir)) + baiPath2 = os.path.join(base, *(xcode4_build_dir + bai + python_resource_dir)) + + lldbPath = None + if os.path.isfile(os.path.join(dbgPath, 'lldb.py')): + lldbPath = dbgPath + elif os.path.isfile(os.path.join(dbgPath2, 'lldb.py')): + lldbPath = dbgPath2 + elif os.path.isfile(os.path.join(relPath, 'lldb.py')): + lldbPath = relPath + elif os.path.isfile(os.path.join(relPath2, 'lldb.py')): + lldbPath = relPath2 + elif os.path.isfile(os.path.join(baiPath, 'lldb.py')): + lldbPath = baiPath + elif os.path.isfile(os.path.join(baiPath2, 'lldb.py')): + lldbPath = baiPath2 + + if not lldbPath: + print 'This script requires lldb.py to be in either ' + dbgPath + ',', + print relPath + ', or ' + baiPath + sys.exit(-1) + + # This is to locate the lldb.py module. Insert it right after sys.path[0]. + sys.path[1:1] = [lldbPath] + #print "sys.path:", sys.path + + +def run_command(ci, cmd, res, echo=True): + if echo: + print "run command:", cmd + ci.HandleCommand(cmd, res) + if res.Succeeded(): + if echo: + print "run_command output:", res.GetOutput() + else: + if echo: + print "run command failed!" + print "run_command error:", res.GetError() + +def do_lldb_disassembly(lldb_commands, exe, disassemble_options, num_symbols, + symbols_to_disassemble, + re_symbol_pattern, + quiet_disassembly): + import lldb, atexit, re + + # Create the debugger instance now. + dbg = lldb.SBDebugger.Create() + if not dbg: + raise Exception('Invalid debugger instance') + + # Register an exit callback. + atexit.register(lambda: lldb.SBDebugger.Terminate()) + + # We want our debugger to be synchronous. + dbg.SetAsync(False) + + # Get the command interpreter from the debugger. + ci = dbg.GetCommandInterpreter() + if not ci: + raise Exception('Could not get the command interpreter') + + # And the associated result object. + res = lldb.SBCommandReturnObject() + + # See if there any extra command(s) to execute before we issue the file command. + for cmd in lldb_commands: + run_command(ci, cmd, res, not quiet_disassembly) + + # Now issue the file command. + run_command(ci, 'file %s' % exe, res, not quiet_disassembly) + + # Create a target. + #target = dbg.CreateTarget(exe) + target = dbg.GetSelectedTarget() + stream = lldb.SBStream() + + def IsCodeType(symbol): + """Check whether an SBSymbol represents code.""" + return symbol.GetType() == lldb.eSymbolTypeCode + + # Define a generator for the symbols to disassemble. + def symbol_iter(num, symbols, re_symbol_pattern, target, verbose): + # If we specify the symbols to disassemble, ignore symbol table dump. + if symbols: + for i in range(len(symbols)): + if verbose: + print "symbol:", symbols[i] + yield symbols[i] + else: + limited = True if num != -1 else False + if limited: + count = 0 + if re_symbol_pattern: + pattern = re.compile(re_symbol_pattern) + stream = lldb.SBStream() + for m in target.module_iter(): + if verbose: + print "module:", m + for s in m: + if limited and count >= num: + return + # If a regexp symbol pattern is supplied, consult it. + if re_symbol_pattern: + # If the pattern does not match, look for the next symbol. + if not pattern.match(s.GetName()): + continue + + # If we come here, we're ready to disassemble the symbol. + if verbose: + print "symbol:", s.GetName() + if IsCodeType(s): + if limited: + count = count + 1 + if verbose: + print "returning symbol:", s.GetName() + yield s.GetName() + if verbose: + print "start address:", s.GetStartAddress() + print "end address:", s.GetEndAddress() + s.GetDescription(stream) + print "symbol description:", stream.GetData() + stream.Clear() + + # Disassembly time. + for symbol in symbol_iter(num_symbols, symbols_to_disassemble, re_symbol_pattern, target, not quiet_disassembly): + cmd = "disassemble %s '%s'" % (disassemble_options, symbol) + run_command(ci, cmd, res, not quiet_disassembly) + + +def main(): + # This is to set up the Python path to include the pexpect-2.4 dir. + # Remember to update this when/if things change. + scriptPath = sys.path[0] + sys.path.append(os.path.join(scriptPath, os.pardir, os.pardir, 'test', 'pexpect-2.4')) + + parser = OptionParser(usage="""\ +Run lldb to disassemble all the available functions for an executable image. + +Usage: %prog [options] +""") + parser.add_option('-C', '--lldb-command', + type='string', action='append', metavar='COMMAND', + default=[], dest='lldb_commands', + help='Command(s) lldb executes after starting up (can be empty)') + parser.add_option('-e', '--executable', + type='string', action='store', + dest='executable', + help="""Mandatory: the executable to do disassembly on.""") + parser.add_option('-o', '--options', + type='string', action='store', + dest='disassemble_options', + help="""Mandatory: the options passed to lldb's 'disassemble' command.""") + parser.add_option('-q', '--quiet-disassembly', + action='store_true', default=False, + dest='quiet_disassembly', + help="""The symbol(s) to invoke lldb's 'disassemble' command on, if specified.""") + parser.add_option('-n', '--num-symbols', + type='int', action='store', default=-1, + dest='num_symbols', + help="""The number of symbols to disassemble, if specified.""") + parser.add_option('-p', '--symbol_pattern', + type='string', action='store', + dest='re_symbol_pattern', + help="""The regular expression of symbols to invoke lldb's 'disassemble' command.""") + parser.add_option('-s', '--symbol', + type='string', action='append', metavar='SYMBOL', default=[], + dest='symbols_to_disassemble', + help="""The symbol(s) to invoke lldb's 'disassemble' command on, if specified.""") + + opts, args = parser.parse_args() + + lldb_commands = opts.lldb_commands + + if not opts.executable or not opts.disassemble_options: + parser.print_help() + sys.exit(1) + + executable = opts.executable + disassemble_options = opts.disassemble_options + quiet_disassembly = opts.quiet_disassembly + num_symbols = opts.num_symbols + symbols_to_disassemble = opts.symbols_to_disassemble + re_symbol_pattern = opts.re_symbol_pattern + + # We have parsed the options. + if not quiet_disassembly: + print "lldb commands:", lldb_commands + print "executable:", executable + print "disassemble options:", disassemble_options + print "quiet disassembly output:", quiet_disassembly + print "num of symbols to disassemble:", num_symbols + print "symbols to disassemble:", symbols_to_disassemble + print "regular expression of symbols to disassemble:", re_symbol_pattern + + setupSysPath() + do_lldb_disassembly(lldb_commands, executable, disassemble_options, + num_symbols, + symbols_to_disassemble, + re_symbol_pattern, + quiet_disassembly) + +if __name__ == '__main__': + main() diff --git a/utils/test/llvm-mc-shell.py b/utils/test/llvm-mc-shell.py new file mode 100755 index 000000000000..38c12992b914 --- /dev/null +++ b/utils/test/llvm-mc-shell.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python + +""" +Run llvm-mc interactively. + +""" + +import os +import sys +from optparse import OptionParser + +def is_exe(fpath): + """Check whether fpath is an executable.""" + return os.path.isfile(fpath) and os.access(fpath, os.X_OK) + +def which(program): + """Find the full path to a program, or return None.""" + fpath, fname = os.path.split(program) + if fpath: + if is_exe(program): + return program + else: + for path in os.environ["PATH"].split(os.pathsep): + exe_file = os.path.join(path, program) + if is_exe(exe_file): + return exe_file + return None + +def llvm_mc_loop(mc, mc_options): + contents = [] + fname = 'mc-input.txt' + sys.stdout.write("Enter your input to llvm-mc. A line starting with 'END' terminates the current batch of input.\n") + sys.stdout.write("Enter 'quit' or Ctrl-D to quit the program.\n") + while True: + sys.stdout.write("> ") + next = sys.stdin.readline() + # EOF => terminate this llvm-mc shell + if not next or next.startswith('quit'): + sys.stdout.write('\n') + sys.exit(0) + # 'END' => send the current batch of input to llvm-mc + if next.startswith('END'): + # Write contents to our file and clear the contents. + with open(fname, 'w') as f: + f.writelines(contents) + # Clear the list: replace all items with an empty list. + contents[:] = [] + + # Invoke llvm-mc with our newly created file. + mc_cmd = '%s %s %s' % (mc, mc_options, fname) + sys.stdout.write("Executing command: %s\n" % mc_cmd) + os.system(mc_cmd) + else: + # Keep accumulating our input. + contents.append(next) + +def main(): + # This is to set up the Python path to include the pexpect-2.4 dir. + # Remember to update this when/if things change. + scriptPath = sys.path[0] + sys.path.append(os.path.join(scriptPath, os.pardir, os.pardir, 'test', 'pexpect-2.4')) + + parser = OptionParser(usage="""\ +Do llvm-mc interactively within a shell-like environment. A batch of input is +submitted to llvm-mc to execute whenever you terminate the current batch by +inputing a line which starts with 'END'. Quit the program by either 'quit' or +Ctrl-D. + +Usage: %prog [options] +""") + parser.add_option('-m', '--llvm-mc', + type='string', action='store', + dest='llvm_mc', + help="""The llvm-mc executable full path, if specified. + Otherwise, it must be present in your PATH environment.""") + + parser.add_option('-o', '--options', + type='string', action='store', + dest='llvm_mc_options', + help="""The options passed to 'llvm-mc' command if specified.""") + + opts, args = parser.parse_args() + + llvm_mc = opts.llvm_mc if opts.llvm_mc else which('llvm-mc') + if not llvm_mc: + parser.print_help() + sys.exit(1) + + # This is optional. For example: + # --options='-disassemble -triple=arm-apple-darwin -debug-only=arm-disassembler' + llvm_mc_options = opts.llvm_mc_options + + # We have parsed the options. + print "llvm-mc:", llvm_mc + print "llvm-mc options:", llvm_mc_options + + llvm_mc_loop(llvm_mc, llvm_mc_options) + +if __name__ == '__main__': + main() diff --git a/utils/test/main.c b/utils/test/main.c new file mode 100644 index 000000000000..c0fe2f25a488 --- /dev/null +++ b/utils/test/main.c @@ -0,0 +1,14 @@ +#include <stdio.h> +#include <stdlib.h> + +int main(int argc, const char* argv[]) +{ + int *null_ptr = 0; + printf("Hello, fault!\n"); + u_int32_t val = (arc4random() & 0x0f); + printf("val=%u\n", val); + if (val == 0x07) // Lucky 7 :-) + printf("Now segfault %d\n", *null_ptr); + else + printf("Better luck next time!\n"); +} diff --git a/utils/test/ras.py b/utils/test/ras.py new file mode 100755 index 000000000000..a89cbae8c88d --- /dev/null +++ b/utils/test/ras.py @@ -0,0 +1,176 @@ +#!/usr/bin/env python + +""" +Run the test suite and send the result as an email message. + +The code for sending of the directory is copied from +http://docs.python.org/library/email-examples.html. +""" + +import os +import sys +import shutil +import smtplib +# For guessing MIME type based on file name extension +import mimetypes + +from optparse import OptionParser + +from email import encoders +from email.message import Message +from email.mime.audio import MIMEAudio +from email.mime.base import MIMEBase +from email.mime.image import MIMEImage +from email.mime.multipart import MIMEMultipart +from email.mime.text import MIMEText + +def runTestsuite(testDir, sessDir, envs = None): + """Run the testsuite and return a (summary, output) tuple.""" + os.chdir(testDir) + + for env in envs: + list = env.split('=') + var = list[0].strip() + val = list[1].strip() + print var + "=" + val + os.environ[var] = val + + import shlex, subprocess + + command_line = "./dotest.py -w -s %s" % sessDir + # Apply correct tokenization for subprocess.Popen(). + args = shlex.split(command_line) + + # Use subprocess module to spawn a new process. + process = subprocess.Popen(args, + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + # Wait for subprocess to terminate. + stdout, stderr = process.communicate() + + # This will be used as the subject line of our email about this test. + cmd = "%s %s" % (' '.join(envs) if envs else "", command_line) + + return (cmd, stderr) + + +COMMASPACE = ', ' + +def main(): + parser = OptionParser(usage="""\ +Run lldb test suite and send the results as a MIME message. + +Usage: %prog [options] + +Unless the -o option is given, the email is sent by forwarding to the specified +SMTP server, which then does the normal delivery process. +""") + parser.add_option('-d', '--directory', + type='string', action='store', + dest='testDir', + help="""The LLDB test directory directly under the top dir. + Otherwise use the current directory.""") + # + # This is similar to TestBase.getRunSpec(self) from lldbtest.py. + # + parser.add_option('-e', '--environment', + type='string', action='append', metavar='ENVIRONMENT', + default=[], dest='environments', + help="""The environment setting as prefix to the test driver. + Example: -e 'CC=clang' -e 'ARCH=x86_64'""") + parser.add_option('-m', '--mailserver', + type='string', action='store', metavar='MAILSERVER', + dest='mailserver', + help="""The outgoing SMTP server.""") + parser.add_option('-o', '--output', + type='string', action='store', metavar='FILE', + help="""Print the composed message to FILE instead of + sending the message to the SMTP server.""") + parser.add_option('-s', '--sender', + type='string', action='store', metavar='SENDER', + help='The value of the From: header (required)') + parser.add_option('-r', '--recipient', + type='string', action='append', metavar='RECIPIENT', + default=[], dest='recipients', + help='A To: header value (at least one required)') + opts, args = parser.parse_args() + if not opts.sender or not opts.recipients: + parser.print_help() + sys.exit(1) + testDir = opts.testDir + if not testDir: + testDir = '.' + + sessDir = 'tmp-lldb-session' + if os.path.exists(sessDir): + shutil.rmtree(sessDir) + #print "environments:", opts.environments + summary, output = runTestsuite(testDir, sessDir, opts.environments) + + # Create the enclosing (outer) message + outer = MIMEMultipart() + outer['Subject'] = summary + outer['To'] = COMMASPACE.join(opts.recipients) + outer['From'] = opts.sender + outer.preamble = 'You will not see this in a MIME-aware mail reader.\n' + + # The sessDir contains all the session logs for failed/errored tests. + # Attach them all if it exists! + + if not os.path.exists(sessDir): + outer.attach(MIMEText(output, 'plain')) + else: + outer.attach(MIMEText("%s\n%s\n\n" % (output, + "Session logs of test failures/errors:"), + 'plain')) + + for filename in (os.listdir(sessDir) if os.path.exists(sessDir) else []): + path = os.path.join(sessDir, filename) + if not os.path.isfile(path): + continue + # Guess the content type based on the file's extension. Encoding + # will be ignored, although we should check for simple things like + # gzip'd or compressed files. + ctype, encoding = mimetypes.guess_type(path) + if ctype is None or encoding is not None: + # No guess could be made, or the file is encoded (compressed), so + # use a generic bag-of-bits type. + ctype = 'application/octet-stream' + maintype, subtype = ctype.split('/', 1) + if maintype == 'text': + fp = open(path) + # Note: we should handle calculating the charset + msg = MIMEText(fp.read(), _subtype=subtype) + fp.close() + elif maintype == 'image': + fp = open(path, 'rb') + msg = MIMEImage(fp.read(), _subtype=subtype) + fp.close() + elif maintype == 'audio': + fp = open(path, 'rb') + msg = MIMEAudio(fp.read(), _subtype=subtype) + fp.close() + else: + fp = open(path, 'rb') + msg = MIMEBase(maintype, subtype) + msg.set_payload(fp.read()) + fp.close() + # Encode the payload using Base64 + encoders.encode_base64(msg) + # Set the filename parameter + msg.add_header('Content-Disposition', 'attachment', filename=filename) + outer.attach(msg) + + # Now send or store the message + composed = outer.as_string() + if opts.output: + fp = open(opts.output, 'w') + fp.write(composed) + fp.close() + else: + s = smtplib.SMTP(opts.mailserver) + s.sendmail(opts.sender, opts.recipients, composed) + s.quit() + + +if __name__ == '__main__': + main() diff --git a/utils/test/run-dis.py b/utils/test/run-dis.py new file mode 100755 index 000000000000..a2437948e47d --- /dev/null +++ b/utils/test/run-dis.py @@ -0,0 +1,125 @@ +#!/usr/bin/env python + +""" +Run lldb disassembler on all the binaries specified by a combination of root dir +and path pattern. +""" + +import os, sys, subprocess +import re +from optparse import OptionParser + +# The directory of this Python script as well as the lldb-disasm.py workhorse. +scriptPath = None + +# The root directory for the SDK symbols. +root_dir = None + +# The regular expression pattern to match the desired pathname to the binaries. +path_pattern = None + +# And the re-compiled regular expression object. +path_regexp = None + +# If specified, number of symbols to disassemble for each qualified binary. +num_symbols = -1 + +# Command template of the invocation of lldb disassembler. +template = '%s/lldb-disasm.py -C "platform select remote-ios" -o "-n" -q -e %s -n %s' + +# Regular expression for detecting file output for Mach-o binary. +mach_o = re.compile('\sMach-O.+binary') +def isbinary(path): + file_output = subprocess.Popen(["file", path], + stdout=subprocess.PIPE).stdout.read() + return (mach_o.search(file_output) is not None) + +def walk_and_invoke(sdk_root, path_regexp, suffix, num_symbols): + """Look for matched file and invoke lldb disassembly on it.""" + global scriptPath + + for root, dirs, files in os.walk(sdk_root, topdown=False): + for name in files: + path = os.path.join(root, name) + + # We're not interested in .h file. + if name.endswith(".h"): + continue + # Neither a symbolically linked file. + if os.path.islink(path): + continue + + # We'll be pattern matching based on the path relative to the SDK root. + replaced_path = path.replace(root_dir, "", 1) + # Check regular expression match for the replaced path. + if not path_regexp.search(replaced_path): + continue + # If a suffix is specified, check it, too. + if suffix and not name.endswith(suffix): + continue + if not isbinary(path): + continue + + command = template % (scriptPath, path, num_symbols if num_symbols > 0 else 1000) + print "Running %s" % (command) + os.system(command) + +def main(): + """Read the root dir and the path spec, invoke lldb-disasm.py on the file.""" + global scriptPath + global root_dir + global path_pattern + global path_regexp + global num_symbols + + scriptPath = sys.path[0] + + parser = OptionParser(usage="""\ +Run lldb disassembler on all the binaries specified by a combination of root dir +and path pattern. +""") + parser.add_option('-r', '--root-dir', + type='string', action='store', + dest='root_dir', + help='Mandatory: the root directory for the SDK symbols.') + parser.add_option('-p', '--path-pattern', + type='string', action='store', + dest='path_pattern', + help='Mandatory: regular expression pattern for the desired binaries.') + parser.add_option('-s', '--suffix', + type='string', action='store', default=None, + dest='suffix', + help='Specify the suffix of the binaries to look for.') + parser.add_option('-n', '--num-symbols', + type='int', action='store', default=-1, + dest='num_symbols', + help="""The number of symbols to disassemble, if specified.""") + + + opts, args = parser.parse_args() + if not opts.root_dir or not opts.path_pattern: + parser.print_help() + sys.exit(1) + + # Sanity check the root directory. + root_dir = opts.root_dir + root_dir = os.path.abspath(root_dir) + if not os.path.isdir(root_dir): + parser.print_help() + sys.exit(1) + + path_pattern = opts.path_pattern + path_regexp = re.compile(path_pattern) + suffix = opts.suffix + num_symbols = opts.num_symbols + + print "Root directory for SDK symbols:", root_dir + print "Regular expression for the binaries:", path_pattern + print "Suffix of the binaries to look for:", suffix + print "num of symbols to disassemble:", num_symbols + + walk_and_invoke(root_dir, path_regexp, suffix, num_symbols) + + +if __name__ == '__main__': + main() diff --git a/utils/test/run-until-faulted.py b/utils/test/run-until-faulted.py new file mode 100755 index 000000000000..d895f565a79e --- /dev/null +++ b/utils/test/run-until-faulted.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python + +""" +Run a program via lldb until it fails. +The lldb executable is located via your PATH env variable, if not specified. +""" + +import os +import sys +from optparse import OptionParser + +def is_exe(fpath): + """Check whether fpath is an executable.""" + return os.path.isfile(fpath) and os.access(fpath, os.X_OK) + +def which(program): + """Find the full path to a program, or return None.""" + fpath, fname = os.path.split(program) + if fpath: + if is_exe(program): + return program + else: + for path in os.environ["PATH"].split(os.pathsep): + exe_file = os.path.join(path, program) + if is_exe(exe_file): + return exe_file + return None + +def do_lldb_launch_loop(lldb_command, exe, exe_options): + from cStringIO import StringIO + import pexpect, time + + prompt = "\(lldb\) " + lldb = pexpect.spawn(lldb_command) + # Turn on logging for what lldb sends back. + lldb.logfile_read = sys.stdout + lldb.expect(prompt) + + # Now issue the file command. + #print "sending 'file %s' command..." % exe + lldb.sendline('file %s' % exe) + lldb.expect(prompt) + + # Loop until it faults.... + count = 0 + #while True: + # count = count + 1 + for i in range(100): + count = i + #print "sending 'process launch -- %s' command... (iteration: %d)" % (exe_options, count) + lldb.sendline('process launch -- %s' % exe_options) + index = lldb.expect(['Process .* exited with status', + 'Process .* stopped', + pexpect.TIMEOUT]) + if index == 0: + # We'll try again later. + time.sleep(3) + elif index == 1: + # Perfect, our process had stopped; break out of the loop. + break; + elif index == 2: + # Something went wrong. + print "TIMEOUT occurred:", str(lldb) + + # Give control of lldb shell to the user. + lldb.interact() + +def main(): + # This is to set up the Python path to include the pexpect-2.4 dir. + # Remember to update this when/if things change. + scriptPath = sys.path[0] + sys.path.append(os.path.join(scriptPath, os.pardir, os.pardir, 'test', 'pexpect-2.4')) + + parser = OptionParser(usage="""\ +%prog [options] +Run a program via lldb until it fails. +The lldb executable is located via your PATH env variable, if not specified.\ +""") + parser.add_option('-l', '--lldb-command', + type='string', action='store', metavar='LLDB_COMMAND', + default='lldb', dest='lldb_command', + help='Full path to your lldb command') + parser.add_option('-e', '--executable', + type='string', action='store', + dest='exe', + help="""(Mandatory) The executable to launch via lldb.""") + parser.add_option('-o', '--options', + type='string', action='store', + default = '', dest='exe_options', + help="""The args/options passed to the launched program, if specified.""") + + opts, args = parser.parse_args() + + lldb_command = which(opts.lldb_command) + + if not opts.exe: + parser.print_help() + sys.exit(1) + exe = opts.exe + + exe_options = opts.exe_options + + # We have parsed the options. + print "lldb command:", lldb_command + print "executable:", exe + print "executable options:", exe_options + + do_lldb_launch_loop(lldb_command, exe, exe_options) + +if __name__ == '__main__': + main() |