crasher.c revision af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040
1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project//#include <cutils/misc.h>
3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <unistd.h>
5dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdio.h>
6dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdlib.h>
7dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <string.h>
8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sched.h>
9dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <errno.h>
10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
11dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <signal.h>
12dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/ptrace.h>
13dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/wait.h>
14dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/socket.h>
15dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
16dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <pthread.h>
17dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
18dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <cutils/sockets.h>
19dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
20dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid crash1(void);
21dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid crashnostack(void);
22849249064cae9c1bb23b0204b5d35b832567801eBruce Bearevoid maybeabort(void);
23aa4213057ba1723e4f164e54f80bb7621c3cb6b3Elliott Hughesint do_action(const char* arg);
24dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
25dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void debuggerd_connect()
26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char tmp[1];
28dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int s;
29dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    sprintf(tmp, "%d", gettid());
30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s = socket_local_client("android:debuggerd",
31dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
32dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(s >= 0) {
33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        read(s, tmp, 1);
34dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        close(s);
35dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
36dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
37dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
38df4200e8c255fca1d03855b971b57036b9ccaa94Elliott Hughesint smash_stack(int i) {
39df4200e8c255fca1d03855b971b57036b9ccaa94Elliott Hughes    printf("crasher: deliberately corrupting stack...\n");
40df4200e8c255fca1d03855b971b57036b9ccaa94Elliott Hughes    // Unless there's a "big enough" buffer on the stack, gcc
41df4200e8c255fca1d03855b971b57036b9ccaa94Elliott Hughes    // doesn't bother inserting checks.
42df4200e8c255fca1d03855b971b57036b9ccaa94Elliott Hughes    char buf[8];
43df4200e8c255fca1d03855b971b57036b9ccaa94Elliott Hughes    // If we don't write something relatively unpredicatable
44df4200e8c255fca1d03855b971b57036b9ccaa94Elliott Hughes    // into the buffer and then do something with it, gcc
45df4200e8c255fca1d03855b971b57036b9ccaa94Elliott Hughes    // optimizes everything away and just returns a constant.
46df4200e8c255fca1d03855b971b57036b9ccaa94Elliott Hughes    *(int*)(&buf[7]) = (uintptr_t) &buf[0];
47df4200e8c255fca1d03855b971b57036b9ccaa94Elliott Hughes    return *(int*)(&buf[0]);
48df4200e8c255fca1d03855b971b57036b9ccaa94Elliott Hughes}
49df4200e8c255fca1d03855b971b57036b9ccaa94Elliott Hughes
50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid test_call1()
51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    *((int*) 32) = 1;
53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid *test_thread(void *x)
56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    printf("crasher: thread pid=%d tid=%d\n", getpid(), gettid());
58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    sleep(1);
60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    test_call1();
61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    printf("goodbye\n");
62dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid *noisy(void *x)
67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char c = (unsigned) x;
69dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for(;;) {
70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        usleep(250*1000);
71dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        write(2, &c, 1);
72dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(c == 'C') *((unsigned*) 0) = 42;
73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint ctest()
78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
79dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    pthread_t thr;
80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    pthread_attr_t attr;
81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    pthread_attr_init(&attr);
82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    pthread_create(&thr, &attr, noisy, (void*) 'A');
84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    pthread_create(&thr, &attr, noisy, (void*) 'B');
85dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    pthread_create(&thr, &attr, noisy, (void*) 'C');
86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for(;;) ;
87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
90aa4213057ba1723e4f164e54f80bb7621c3cb6b3Elliott Hughesstatic void* thread_callback(void* raw_arg)
91aa4213057ba1723e4f164e54f80bb7621c3cb6b3Elliott Hughes{
92aa4213057ba1723e4f164e54f80bb7621c3cb6b3Elliott Hughes    return (void*) do_action((const char*) raw_arg);
93aa4213057ba1723e4f164e54f80bb7621c3cb6b3Elliott Hughes}
94aa4213057ba1723e4f164e54f80bb7621c3cb6b3Elliott Hughes
95aa4213057ba1723e4f164e54f80bb7621c3cb6b3Elliott Hughesint do_action_on_thread(const char* arg)
96dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
97aa4213057ba1723e4f164e54f80bb7621c3cb6b3Elliott Hughes    pthread_t t;
98aa4213057ba1723e4f164e54f80bb7621c3cb6b3Elliott Hughes    pthread_create(&t, NULL, thread_callback, (void*) arg);
99aa4213057ba1723e4f164e54f80bb7621c3cb6b3Elliott Hughes    void* result = NULL;
100aa4213057ba1723e4f164e54f80bb7621c3cb6b3Elliott Hughes    pthread_join(t, &result);
101aa4213057ba1723e4f164e54f80bb7621c3cb6b3Elliott Hughes    return (int) result;
102aa4213057ba1723e4f164e54f80bb7621c3cb6b3Elliott Hughes}
103aa4213057ba1723e4f164e54f80bb7621c3cb6b3Elliott Hughes
104af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin__attribute__((noinline)) int crash3(int a) {
105af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin   *((int*) 0xdead) = a;
106af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin   return a*4;
107af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin}
108af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin
109af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin__attribute__((noinline)) int crash2(int a) {
110af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin   a = crash3(a) + 2;
111af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin   return a*3;
112af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin}
113af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin
114af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin__attribute__((noinline)) int crash(int a) {
115af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin   a = crash2(a) + 1;
116af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin   return a*2;
117af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin}
118af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin
119aa4213057ba1723e4f164e54f80bb7621c3cb6b3Elliott Hughesint do_action(const char* arg)
120aa4213057ba1723e4f164e54f80bb7621c3cb6b3Elliott Hughes{
121aa4213057ba1723e4f164e54f80bb7621c3cb6b3Elliott Hughes    if(!strncmp(arg, "thread-", strlen("thread-"))) {
122aa4213057ba1723e4f164e54f80bb7621c3cb6b3Elliott Hughes        return do_action_on_thread(arg + strlen("thread-"));
123aa4213057ba1723e4f164e54f80bb7621c3cb6b3Elliott Hughes    }
124aa4213057ba1723e4f164e54f80bb7621c3cb6b3Elliott Hughes
125df4200e8c255fca1d03855b971b57036b9ccaa94Elliott Hughes    if(!strcmp(arg,"smash-stack")) return smash_stack(42);
126aa4213057ba1723e4f164e54f80bb7621c3cb6b3Elliott Hughes    if(!strcmp(arg,"nostack")) crashnostack();
127aa4213057ba1723e4f164e54f80bb7621c3cb6b3Elliott Hughes    if(!strcmp(arg,"ctest")) return ctest();
128aa4213057ba1723e4f164e54f80bb7621c3cb6b3Elliott Hughes    if(!strcmp(arg,"exit")) exit(1);
129af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin    if(!strcmp(arg,"crash")) return crash(42);
130aa4213057ba1723e4f164e54f80bb7621c3cb6b3Elliott Hughes    if(!strcmp(arg,"abort")) maybeabort();
131aa4213057ba1723e4f164e54f80bb7621c3cb6b3Elliott Hughes
132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    pthread_t thr;
133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    pthread_attr_t attr;
134aa4213057ba1723e4f164e54f80bb7621c3cb6b3Elliott Hughes    pthread_attr_init(&attr);
135aa4213057ba1723e4f164e54f80bb7621c3cb6b3Elliott Hughes    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
136aa4213057ba1723e4f164e54f80bb7621c3cb6b3Elliott Hughes    pthread_create(&thr, &attr, test_thread, 0);
137aa4213057ba1723e4f164e54f80bb7621c3cb6b3Elliott Hughes    while(1) sleep(1);
138aa4213057ba1723e4f164e54f80bb7621c3cb6b3Elliott Hughes}
139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
140aa4213057ba1723e4f164e54f80bb7621c3cb6b3Elliott Hughesint main(int argc, char **argv)
141aa4213057ba1723e4f164e54f80bb7621c3cb6b3Elliott Hughes{
142aa4213057ba1723e4f164e54f80bb7621c3cb6b3Elliott Hughes    fprintf(stderr,"crasher: built at " __TIME__ "!@\n");
143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fprintf(stderr,"crasher: init pid=%d tid=%d\n", getpid(), gettid());
144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(argc > 1) {
146aa4213057ba1723e4f164e54f80bb7621c3cb6b3Elliott Hughes        return do_action(argv[1]);
147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        crash1();
149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project//        *((int*) 0) = 42;
150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid maybeabort()
156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(time(0) != 42) abort();
158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
159