1/*
2 * Copyright (C) 2008 The Android Open Source Project
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *  * Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 *  * Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in
12 *    the documentation and/or other materials provided with the
13 *    distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#include <stdio.h>
30#include <stdlib.h>
31#include <unistd.h>
32#include <ctype.h>
33#include <signal.h>
34#include <sys/mman.h>
35#include <errno.h>
36
37#include "linker.h"
38
39#include <sys/socket.h>
40#include <sys/un.h>
41
42void notify_gdb_of_libraries();
43
44#define  RETRY_ON_EINTR(ret,cond) \
45    do { \
46        ret = (cond); \
47    } while (ret < 0 && errno == EINTR)
48
49
50static int socket_abstract_client(const char *name, int type)
51{
52    struct sockaddr_un addr;
53    size_t namelen;
54    socklen_t alen;
55    int s, err;
56
57    namelen  = strlen(name);
58
59    // Test with length +1 for the *initial* '\0'.
60    if ((namelen + 1) > sizeof(addr.sun_path)) {
61        errno = EINVAL;
62        return -1;
63    }
64
65    /* This is used for abstract socket namespace, we need
66     * an initial '\0' at the start of the Unix socket path.
67     *
68     * Note: The path in this case is *not* supposed to be
69     * '\0'-terminated. ("man 7 unix" for the gory details.)
70     */
71    memset (&addr, 0, sizeof addr);
72    addr.sun_family = AF_LOCAL;
73    addr.sun_path[0] = 0;
74    memcpy(addr.sun_path + 1, name, namelen);
75
76    alen = namelen + offsetof(struct sockaddr_un, sun_path) + 1;
77
78    s = socket(AF_LOCAL, type, 0);
79    if(s < 0) return -1;
80
81    RETRY_ON_EINTR(err,connect(s, (struct sockaddr *) &addr, alen));
82    if (err < 0) {
83        close(s);
84        s = -1;
85    }
86
87    return s;
88}
89
90void debugger_signal_handler(int n)
91{
92    unsigned tid;
93    int s;
94
95    /* avoid picking up GC interrupts */
96    signal(SIGUSR1, SIG_IGN);
97
98    tid = gettid();
99    s = socket_abstract_client("android:debuggerd", SOCK_STREAM);
100
101    if(s >= 0) {
102        /* debugger knows our pid from the credentials on the
103         * local socket but we need to tell it our tid.  It
104         * is paranoid and will verify that we are giving a tid
105         * that's actually in our process
106         */
107        int  ret;
108
109        RETRY_ON_EINTR(ret, write(s, &tid, sizeof(unsigned)));
110        if (ret == sizeof(unsigned)) {
111            /* if the write failed, there is no point to read on
112             * the file descriptor. */
113            RETRY_ON_EINTR(ret, read(s, &tid, 1));
114            notify_gdb_of_libraries();
115        }
116        close(s);
117    }
118
119    /* remove our net so we fault for real when we return */
120    signal(n, SIG_IGN);
121}
122
123void debugger_init()
124{
125    signal(SIGILL, debugger_signal_handler);
126    signal(SIGABRT, debugger_signal_handler);
127    signal(SIGBUS, debugger_signal_handler);
128    signal(SIGFPE, debugger_signal_handler);
129    signal(SIGSEGV, debugger_signal_handler);
130    signal(SIGSTKFLT, debugger_signal_handler);
131    signal(SIGPIPE, debugger_signal_handler);
132}
133