~sergiusens/libhybris/autotests

« back to all changes in this revision

Viewing changes to hybris/common/ics/debugger.c

  • Committer: Package Import Robot
  • Author(s): Ricardo Salveti de Araujo
  • Date: 2013-06-04 07:33:11 UTC
  • Revision ID: package-import@ubuntu.com-20130604073311-20ldi2hm1axkvjl1
Tags: upstream-0.1.0+git20130601+dfb2e26
ImportĀ upstreamĀ versionĀ 0.1.0+git20130601+dfb2e26

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
42
void 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
 
 
50
static 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
 
 
90
#include "linker_format.h"
 
91
#include <../libc/private/logd.h>
 
92
 
 
93
/*
 
94
 * Writes a summary of the signal to the log file.
 
95
 *
 
96
 * We could be here as a result of native heap corruption, or while a
 
97
 * mutex is being held, so we don't want to use any libc functions that
 
98
 * could allocate memory or hold a lock.
 
99
 */
 
100
static void logSignalSummary(int signum, const siginfo_t* info)
 
101
{
 
102
    char buffer[128];
 
103
 
 
104
    char* signame;
 
105
    switch (signum) {
 
106
        case SIGILL:    signame = "SIGILL";     break;
 
107
        case SIGABRT:   signame = "SIGABRT";    break;
 
108
        case SIGBUS:    signame = "SIGBUS";     break;
 
109
        case SIGFPE:    signame = "SIGFPE";     break;
 
110
        case SIGSEGV:   signame = "SIGSEGV";    break;
 
111
        case SIGSTKFLT: signame = "SIGSTKFLT";  break;
 
112
        case SIGPIPE:   signame = "SIGPIPE";    break;
 
113
        default:        signame = "???";        break;
 
114
    }
 
115
 
 
116
    format_buffer(buffer, sizeof(buffer),
 
117
        "Fatal signal %d (%s) at 0x%08x (code=%d)",
 
118
        signum, signame, info->si_addr, info->si_code);
 
119
 
 
120
    __libc_android_log_write(ANDROID_LOG_FATAL, "libc", buffer);
 
121
}
 
122
 
 
123
/*
 
124
 * Catches fatal signals so we can ask debuggerd to ptrace us before
 
125
 * we crash.
 
126
 */
 
127
void debugger_signal_handler(int n, siginfo_t* info, void* unused)
 
128
{
 
129
    unsigned tid;
 
130
    int s;
 
131
 
 
132
    logSignalSummary(n, info);
 
133
 
 
134
    tid = gettid();
 
135
    s = socket_abstract_client("android:debuggerd", SOCK_STREAM);
 
136
 
 
137
    if(s >= 0) {
 
138
        /* debugger knows our pid from the credentials on the
 
139
         * local socket but we need to tell it our tid.  It
 
140
         * is paranoid and will verify that we are giving a tid
 
141
         * that's actually in our process
 
142
         */
 
143
        int  ret;
 
144
 
 
145
        RETRY_ON_EINTR(ret, write(s, &tid, sizeof(unsigned)));
 
146
        if (ret == sizeof(unsigned)) {
 
147
            /* if the write failed, there is no point to read on
 
148
             * the file descriptor. */
 
149
            RETRY_ON_EINTR(ret, read(s, &tid, 1));
 
150
            notify_gdb_of_libraries();
 
151
        }
 
152
        close(s);
 
153
    }
 
154
 
 
155
    /* remove our net so we fault for real when we return */
 
156
    signal(n, SIG_DFL);
 
157
}
 
158
 
 
159
void debugger_init()
 
160
{
 
161
    struct sigaction act;
 
162
    memset(&act, 0, sizeof(act));
 
163
    act.sa_sigaction = debugger_signal_handler;
 
164
    act.sa_flags = SA_RESTART | SA_SIGINFO;
 
165
    sigemptyset(&act.sa_mask);
 
166
 
 
167
    sigaction(SIGILL, &act, NULL);
 
168
    sigaction(SIGABRT, &act, NULL);
 
169
    sigaction(SIGBUS, &act, NULL);
 
170
    sigaction(SIGFPE, &act, NULL);
 
171
    sigaction(SIGSEGV, &act, NULL);
 
172
    sigaction(SIGSTKFLT, &act, NULL);
 
173
    sigaction(SIGPIPE, &act, NULL);
 
174
}