Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(259)

Side by Side Diff: tests/untrusted_crash_dump/untrusted_crash_dump.c

Issue 9316125: Adding untrusted crash dump / stack trace tests. (Closed) Base URL: svn://svn.chromium.org/native_client/trunk/src/native_client
Patch Set: fixing 64-bit build issue Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 /*
2 * Copyright (c) 2012 The Native Client Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file.
5 */
6
7
8 #include <assert.h>
9 #include <inttypes.h>
10 #include <pthread.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <sys/nacl_syscalls.h>
15
16 #ifdef __GLIBC__
17 #include <elf.h>
18 #include <link.h>
19 #endif /* __GLIBC__ */
20
21 #include "native_client/src/untrusted/nacl/syscall_bindings_trampoline.h"
22 #include "native_client/tests/untrusted_crash_dump/untrusted_crash_dump.h"
23
24
25 #define CRASH_STACK_SIZE 4096
26
27
28 static void (*g_PrevHandler)(int prog_ctr, int stack_ptr) = 0;
29 static pthread_key_t g_CrashStackKey;
30 static char *g_ProgramName = 0;
31
32
33 #ifdef __GLIBC__
34
35 typedef struct {
36 FILE *core;
37 uint32_t addr;
Mark Seaborn 2012/02/06 19:44:06 uintptr_t
bradn 2012/02/06 22:27:48 Done.
38 int first;
39 } PROGRAM_TABLE_DATA;
Mark Seaborn 2012/02/06 19:44:06 Naming style: Just call it 'struct ProgramTableDat
bradn 2012/02/06 22:27:48 Done.
40
41
42 static int PrintSectionsOne(
43 struct dl_phdr_info *info, size_t size, void *data) {
44 int i;
45 PROGRAM_TABLE_DATA *ptd = (PROGRAM_TABLE_DATA*)data;
46
47 if (ptd->first) {
48 ptd->first = 0;
49 } else {
50 fprintf(ptd->core, ",\n");
51 }
52 fprintf(ptd->core, "{\n");
53 fprintf(ptd->core, "\"dlpi_name\": \"%s\",\n", info->dlpi_name);
54 fprintf(ptd->core, "\"dlpi_addr\": %"PRIu32",\n", info->dlpi_addr);
55 fprintf(ptd->core, "\"dlpi_phdr\": [\n");
56 for (i = 0; i < info->dlpi_phnum; i++) {
57 /* Skip non-LOAD type segments. */
58 if (info->dlpi_phdr[i].p_type != PT_LOAD) {
59 continue;
60 }
61 if (i != 0) {
62 fprintf(ptd->core, ",\n");
63 }
64 fprintf(ptd->core, "{\n");
65 fprintf(ptd->core, "\"p_vaddr\": %"PRIu32",\n", info->dlpi_phdr[i].p_vaddr);
66 fprintf(ptd->core, "\"p_memsz\": %"PRIu32"\n", info->dlpi_phdr[i].p_memsz);
67 fprintf(ptd->core, "}\n");
68 }
69 fprintf(ptd->core, "]\n");
70 fprintf(ptd->core, "}\n");
71 return 0;
72 }
73
74 static void PrintSections(FILE *core) {
75 PROGRAM_TABLE_DATA data;
76 data.core = core;
77 data.first = 1;
78 dl_iterate_phdr(PrintSectionsOne, &data);
79 }
80
81 static int PrintMappedAddressOne(
82 struct dl_phdr_info *info, size_t size, void *data) {
83 int i;
84 PROGRAM_TABLE_DATA *ptd = (PROGRAM_TABLE_DATA *) data;
85 uint32_t addr = ptd->addr;
86 uint32_t start, end;
Mark Seaborn 2012/02/06 19:44:06 One var per line is our usual style, I think.
bradn 2012/02/06 22:27:48 Done.
87
88 /* Consider relative to phdr base addr. */
89 addr -= info->dlpi_addr;
90
91 for (i = 0; i < info->dlpi_phnum; i++) {
92 /* Skip non-LOAD type segments. */
93 if (info->dlpi_phdr[i].p_type != PT_LOAD) {
94 continue;
95 }
96 /* See if it's in range for this part. */
97 start = info->dlpi_phdr[i].p_vaddr;
98 end = start + info->dlpi_phdr[i].p_memsz;
99 if (addr >= start && addr < end) {
100 if (info->dlpi_name[0] == '\0') {
101 fprintf(ptd->core, "{\"file\": \"%s\", \"addr\": %"PRIu32"}",
102 g_ProgramName, addr);
103 } else {
104 fprintf(ptd->core, "{\"file\": \"%s\", \"addr\": %"PRIu32"}",
105 info->dlpi_name, addr);
106 }
107 return 1;
108 }
109 }
110 return 0;
111 }
112
113 static void PrintMappedAddress(FILE *core, uint32_t addr) {
114 PROGRAM_TABLE_DATA ptd;
115 int result;
116
117 ptd.core = core;
118 ptd.addr = addr;
119 result = dl_iterate_phdr(PrintMappedAddressOne, &ptd);
120 if (!result) {
121 fprintf(core, "{\"file\": \"%s\", \"addr\": %"PRIu32"}",
122 g_ProgramName, addr);
123 }
124 }
125
126 #else /* __GLIBC__ */
127
128 static void PrintSections(FILE *core) {
129 (void)core;
Mark Seaborn 2012/02/06 19:44:06 Use UNREFERENCED_PARAMETER(), or nothing if the wa
bradn 2012/02/06 22:27:48 Done.
130 }
131
132 static void PrintMappedAddress(FILE *core, uint32_t addr) {
133 fprintf(core, "{\"file\": \"%s\", \"addr\": %"PRIu32"}",
134 g_ProgramName, addr);
135 }
136
137 #endif /* __GLIBC__ */
138
139 uint32_t SafeRead(uint32_t a) {
Mark Seaborn 2012/02/06 19:44:06 SafeRead() is not safe. Does it need a TODO? Typ
bradn 2012/02/06 22:27:48 Done.
140 return *(uint32_t*)a;
141 }
142
143 static void StackWalk(FILE *core, uint32_t ip, uint32_t sp) {
144 uint32_t next;
145 uint32_t i;
146 int first = 1;
147
148 fprintf(core, "\"frames\": [\n");
149 for (;;) {
150 next = SafeRead(sp);
151 if (next <= sp || next == 0) {
152 break;
153 }
154 if (first) {
155 first = 0;
156 } else {
157 fprintf(core, ",");
158 }
159 fprintf(core, "{\n");
160 fprintf(core, "\"sp\": %"PRIu32",\n", sp);
161 fprintf(core, "\"ip\": %"PRIu32",\n", ip);
162 fprintf(core, "\"ip_mapped\": ");
163 PrintMappedAddress(core, ip);
164 fprintf(core, ",\n");
165 fprintf(core, "\"data\": [\n");
166 for (i = sp + 8; i < next; i += 4) {
167 if (i != sp + 8) {
168 fprintf(core, ",");
169 }
170 fprintf(core, "%"PRIu32"\n", SafeRead(i));
171 }
172 fprintf(core, "]\n");
173 fprintf(core, "}\n");
174
175 ip = SafeRead(sp + 4);
176 sp = next;
177 }
178
179 fprintf(core, "]\n");
180 }
181
182 static void CrashHandler(int prog_ctr, int stack_ptr) {
183 FILE *core;
184 const char *core_filename;
185
186 /* Pick core file name. */
187 core_filename=getenv("NACLCOREFILE");
Mark Seaborn 2012/02/06 19:44:06 spaces around '='
bradn 2012/02/06 22:27:48 Done.
188 if (!core_filename) {
189 core_filename = "naclcore.json";
190 }
191
192 /* Attempt to open core file, otherwise use stdout. */
193 core = fopen(core_filename, "w");
194 if (!core) {
195 core = stdout;
196 }
197
198 fprintf(core, "{\n");
199
200 fprintf(core, "\"sections\": [");
201 PrintSections(core);
202 fprintf(core, "],\n");
203
204 fprintf(core, "\"handler\": {\n");
205 fprintf(core, "\"prog_ctr\": %"PRIu32",\n", prog_ctr);
206 fprintf(core, "\"stack_ptr\": %"PRIu32"\n", stack_ptr);
207 fprintf(core, "},\n");
208 StackWalk(core, (uint32_t) prog_ctr, (uint32_t) stack_ptr);
209
210 fprintf(core, "}\n");
211
212 if (core != stdout) {
213 fclose(core);
214 }
215
216 exit(166);
217 }
218
219 void NaClCrashDumpThreadDestructor(void *arg) {
220 free(arg);
221 }
222
223 void NaClCrashDumpInit(char *program_name) {
224 int result;
225 g_ProgramName = program_name;
226 result = pthread_key_create(&g_CrashStackKey, NaClCrashDumpThreadDestructor);
227 assert(!result);
Mark Seaborn 2012/02/06 19:44:06 assert(result == 0);
bradn 2012/02/06 22:27:48 Done.
228 result = NACL_SYSCALL(exception_handler)(CrashHandler, &g_PrevHandler);
229 assert(!result);
230 NaClCrashDumpInitThread();
231 }
232
233 void NaClCrashDumpDestroy(void) {
234 int result;
235 void (*old)(int, int);
236 result = NACL_SYSCALL(exception_handler)(g_PrevHandler, &old);
Mark Seaborn 2012/02/06 19:44:06 'old' is unused. Use NULL.
bradn 2012/02/06 22:27:48 Done.
237 assert(!result);
238 result = pthread_key_delete(g_CrashStackKey);
239 assert(!result);
240 g_ProgramName = 0;
241 }
242
243 void NaClCrashDumpInitThread(void) {
244 void *stack;
245 int result;
246 stack = malloc(CRASH_STACK_SIZE);
Mark Seaborn 2012/02/06 19:44:06 mallocing stacks is bad because there's no guard p
bradn 2012/02/06 22:27:48 Switched to mmap + guard.
247 pthread_setspecific(g_CrashStackKey, stack);
248 result = NACL_SYSCALL(exception_stack)(stack, CRASH_STACK_SIZE);
Mark Seaborn 2012/02/06 19:44:06 FYI, you don't really need to set an exception sta
bradn 2012/02/06 22:27:48 Done.
249 assert(!result);
250 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698