/[zanavi_public1]/navit/navit/coffeejni.c
ZANavi

Contents of /navit/navit/coffeejni.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 52 - (show annotations) (download)
Mon Nov 7 10:01:21 2016 UTC (7 years, 5 months ago) by zoff99
File MIME type: text/plain
File size: 6050 byte(s)
v2.0.53
1 /* CoffeeCatch, a tiny native signal handler/catcher for JNI code.
2 * (especially for Android/Dalvik)
3 *
4 * Copyright (c) 2013, Xavier Roche (http://www.httrack.com/)
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright notice, this
11 * list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright notice,
13 * this list of conditions and the following disclaimer in the documentation
14 * and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 #ifndef COFFEECATCH_JNI_H
29 #define COFFEECATCH_JNI_H
30
31 #include <stdio.h>
32 #include <string.h>
33 #include <stdint.h>
34 #include <sys/types.h>
35 #include <jni.h>
36 #include <assert.h>
37 #include "coffeecatch.h"
38
39 #ifdef __cplusplus
40 extern "C" {
41 #endif
42
43 typedef struct t_bt_fun {
44 JNIEnv* env;
45 jclass cls;
46 jclass cls_ste;
47 jmethodID cons_ste;
48 jobjectArray elements;
49 size_t size;
50 size_t index;
51 } t_bt_fun;
52
53 static char* bt_print(const char *function, uintptr_t offset) {
54 if (function != NULL) {
55 char buffer[256];
56 snprintf(buffer, sizeof(buffer), "%s:%p", function, (void*) offset);
57 return strdup(buffer);
58 } else {
59 return "<unknown>";
60 }
61 }
62
63 static char* bt_addr(uintptr_t addr) {
64 char buffer[32];
65 snprintf(buffer, sizeof(buffer), "%p", (void*) addr);
66 return strdup(buffer);
67 }
68
69 #define IS_VALID_CLASS_CHAR(C) ( \
70 ((C) >= 'a' && (C) <= 'z') \
71 || ((C) >= 'A' && (C) <= 'Z') \
72 || ((C) >= '0' && (C) <= '9') \
73 || (C) == '_' \
74 )
75
76 static char* bt_module(const char *module) {
77 if (module != NULL) {
78 size_t i;
79 char *copy;
80 if (*module == '/') {
81 module++;
82 }
83 copy = strdup(module);
84 /* Pseudo-java-class. */
85 for(i = 0; copy[i] != '\0'; i++) {
86 if (copy[i] == '/') {
87 copy[i] = '.';
88 } else if (!IS_VALID_CLASS_CHAR(copy[i])) {
89 copy[i] = '_';
90 }
91 }
92 return copy;
93 } else {
94 return "<unknown>";
95 }
96 }
97
98 static void bt_fun(void *arg, const char *module, uintptr_t addr,
99 const char *function, uintptr_t offset) {
100 t_bt_fun *const t = (t_bt_fun*) arg;
101 JNIEnv*const env = t->env;
102 jstring declaringClass = (*env)->NewStringUTF(env, bt_module(module));
103 jstring methodName = (*env)->NewStringUTF(env, bt_addr(addr));
104 jstring fileName = (*env)->NewStringUTF(env, bt_print(function, offset));
105 const int lineNumber = function != NULL ? 0 : -2; /* "-2" is "inside JNI code" */
106 jobject trace = (*env)->NewObject(env, t->cls_ste, t->cons_ste,
107 declaringClass, methodName, fileName,
108 lineNumber);
109 if (t->index < t->size) {
110 (*t->env)->SetObjectArrayElement(t->env, t->elements, t->index++, trace);
111 }
112 }
113
114 void coffeecatch_throw_exception(JNIEnv* env) {
115 jclass cls = (*env)->FindClass(env, "java/lang/Error");
116 jclass cls_ste = (*env)->FindClass(env, "java/lang/StackTraceElement");
117
118 jmethodID cons = (*env)->GetMethodID(env, cls, "<init>", "(Ljava/lang/String;)V");
119 jmethodID cons_cause = (*env)->GetMethodID(env, cls, "<init>", "(Ljava/lang/String;Ljava/lang/Throwable;)V");
120 jmethodID cons_ste = (*env)->GetMethodID(env, cls_ste, "<init>",
121 "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V");
122 jmethodID meth_sste = (*env)->GetMethodID(env, cls, "setStackTrace",
123 "([Ljava/lang/StackTraceElement;)V");
124
125 /* Exception message. */
126 const char*const message = coffeecatch_get_message();
127 jstring str = (*env)->NewStringUTF(env, strdup(message));
128
129 /* Final exception. */
130 jthrowable exception;
131
132 /* Add pseudo-stack trace. */
133 const ssize_t bt_size = coffeecatch_get_backtrace_size();
134
135 assert(cls != NULL);
136 assert(cls_ste != NULL);
137 assert(cons != NULL);
138 assert(cons_cause != NULL);
139 assert(cons_ste != NULL);
140 assert(meth_sste != NULL);
141
142 assert(message != NULL);
143 assert(str != NULL);
144
145 /* Can we produce a stack trace ? */
146 if (bt_size > 0) {
147 /* Create secondary exception. */
148 jthrowable cause = (jthrowable) (*env)->NewObject(env, cls, cons, str);
149
150 /* Stack trace. */
151 jobjectArray elements =
152 (*env)->NewObjectArray(env, bt_size, cls_ste, NULL);
153 if (elements != NULL) {
154 t_bt_fun t;
155 t.env = env;
156 t.cls = cls;
157 t.cls_ste = cls_ste;
158 t.cons_ste = cons_ste;
159 t.elements = elements;
160 t.index = 0;
161 t.size = bt_size;
162 coffeecatch_get_backtrace_info(bt_fun, &t);
163 (*env)->CallVoidMethod(env, cause, meth_sste, elements);
164 }
165
166 /* Primary exception */
167 exception = (jthrowable) (*env)->NewObject(env, cls, cons_cause, str, cause);
168 } else {
169 /* Simple exception */
170 exception = (jthrowable) (*env)->NewObject(env, cls, cons, str);
171 }
172
173 /* Throw exception. */
174 if (exception != NULL) {
175 (*env)->Throw(env, exception);
176 } else {
177 (*env)->ThrowNew(env, cls, strdup(message));
178 }
179 }
180
181 #ifdef __cplusplus
182 }
183 #endif
184
185 #endif

   
Visit the ZANavi Wiki