comparison src/debug.c @ 202:2f38c4ce606f

remove readpstlog, switch to plain ascii debug log files
author Carl Byington <carl@five-ten-sg.com>
date Mon, 18 May 2009 15:55:05 -0700
parents ac6e22c8a9cf
children 156cf548c764
comparison
equal deleted inserted replaced
201:3850a3b11745 202:2f38c4ce606f
1 #include "define.h" 1 #include "define.h"
2
3 struct pst_debug_item {
4 int type;
5 char * function;
6 unsigned int line;
7 char * file;
8 char * text;
9 struct pst_debug_item *next;
10 };
11
12 static struct pst_debug_item *item_head=NULL, *item_tail=NULL, *item_ptr=NULL, *info_ptr=NULL, *temp_list=NULL;
13 2
14 3
15 struct pst_debug_func { 4 struct pst_debug_func {
16 char * name; 5 char * name;
17 struct pst_debug_func *next; 6 struct pst_debug_func *next;
18 }; 7 };
19 8
20 static struct pst_debug_func *func_head=NULL, *func_ptr=NULL; 9
10 #define NUM_COL 32
11 #define MAX_DEPTH 32
12
13 static struct pst_debug_func *func_head = NULL;
14 static int func_depth = 0;
15 static char indent[MAX_DEPTH*4+1];
16 static FILE *debug_fp = NULL;
17 #ifdef HAVE_SEMAPHORE_H
18 static sem_t* debug_mutex = NULL;
19 #endif
21 20
22 21
23 static void pst_debug_write_msg(struct pst_debug_item *item, const char *fmt, va_list *ap, int size); 22 void pst_debug_lock()
24 static void pst_debug_write_hex(struct pst_debug_item *item, char *buf, size_t size, int col); 23 {
25 static void pst_debug_write(); 24 #ifdef HAVE_SEMAPHORE_H
26 25 if (debug_mutex) sem_wait(debug_mutex);
27 26 #endif
28 static size_t pst_debug_fwrite(const void *ptr, size_t size, size_t nitems, FILE *stream);
29 static size_t pst_debug_fwrite(const void *ptr, size_t size, size_t nitems, FILE *stream) {
30 return fwrite(ptr, size, nitems, stream);
31 } 27 }
32 28
33 29
34 // the largest text size we will store in memory. Otherwise we 30 void pst_debug_unlock()
35 // will do a debug_write, then create a new record, and write the 31 {
36 // text body directly to the file 32 #ifdef HAVE_SEMAPHORE_H
37 #define MAX_MESSAGE_SIZE 4096 33 if (debug_mutex) sem_post(debug_mutex);
38 34 #endif
39 void pst_debug(const char *fmt, ...) {
40 va_list ap;
41 va_start(ap,fmt);
42 vfprintf(stderr, fmt, ap);
43 va_end(ap);
44 } 35 }
45 36
46 37
47 #define NUM_COL 30 38 void pst_debug_init(const char* fname, void* output_mutex) {
48 void pst_debug_hexdumper(FILE *out, char *buf, size_t size, int col, int delta) { 39 #ifdef HAVE_SEMAPHORE_H
40 debug_mutex = (sem_t*)output_mutex;
41 #endif
42 memset(indent, ' ', MAX_DEPTH);
43 indent[MAX_DEPTH] = '\0';
44 if (debug_fp) pst_debug_close();
45 if (!fname) return;
46 if ((debug_fp = fopen(fname, "wb")) == NULL) {
47 fprintf(stderr, "Opening of file %s failed\n", fname);
48 exit(1);
49 }
50 }
51
52
53 void pst_debug_func(const char* function) {
54 struct pst_debug_func *func_ptr = pst_malloc (sizeof(struct pst_debug_func));
55 func_ptr->name = strdup(function);
56 func_ptr->next = func_head;
57 func_head = func_ptr;
58 func_depth++;
59 }
60
61
62 void pst_debug_func_ret() {
63 //remove the head item
64 struct pst_debug_func *func_ptr = func_head;
65 if (func_head) {
66 func_head = func_head->next;
67 free(func_ptr->name);
68 free(func_ptr);
69 func_depth--;
70 } else {
71 DIE(("function list is empty!\n"));
72 }
73 }
74
75
76 static void pst_debug_info(int line, const char* file);
77 static void pst_debug_info(int line, const char* file) {
78 int le = (func_depth > MAX_DEPTH) ? MAX_DEPTH : func_depth;
79 if (le > 0) le--;
80 char *func = (func_head ? func_head->name : "No Function");
81 pst_debug_lock();
82 fprintf(debug_fp, "%06d %.*s%s %s(%d) ", getpid(), le*4, indent, func, file, line);
83 }
84
85
86 void pst_debug(int line, const char* file, const char *fmt, ...) {
87 if (debug_fp) {
88 pst_debug_info(line, file);
89 va_list ap;
90 va_start(ap,fmt);
91 vfprintf(debug_fp, fmt, ap);
92 va_end(ap);
93 fflush(debug_fp);
94 pst_debug_unlock();
95 }
96 }
97
98
99 void pst_debug_hexdump(int line, const char *file, const char *buf, size_t size, int cols, int delta) {
100 if (debug_fp) {
101 pst_debug_info(line, file);
102 pst_debug_hexdumper(debug_fp, buf, size, cols, delta);
103 pst_debug_unlock();
104 }
105 }
106
107
108 void pst_debug_hexdumper(FILE *out, const char *buf, size_t size, int cols, int delta) {
109 int le = (func_depth > MAX_DEPTH) ? MAX_DEPTH : func_depth;
49 size_t off = 0, toff; 110 size_t off = 0, toff;
50 int count = 0; 111 int count = 0;
51 112
52 if (!out) return; // no file 113 if (!out) return; // no file
53 if (col == -1) col = NUM_COL; 114
115 if (cols == -1) cols = NUM_COL;
54 fprintf(out, "\n"); 116 fprintf(out, "\n");
55 while (off < size) { 117 while (off < size) {
56 fprintf(out, "%06"PRIx64"\t:", (int64_t)(off+delta)); 118 fprintf(out, "%06d %.*s%06"PRIx64"\t:", getpid(), le*4, indent, (int64_t)(off+delta));
57 toff = off; 119 toff = off;
58 while (count < col && off < size) { 120 while (count < cols && off < size) {
59 fprintf(out, "%02hhx ", (unsigned char)buf[off]); 121 fprintf(out, "%02hhx ", (unsigned char)buf[off]);
60 off++; count++; 122 off++; count++;
61 } 123 }
62 off = toff; 124 off = toff;
63 while (count < col) { 125 while (count < cols) {
64 // only happens at end of block to pad the text over to the text column 126 // only happens at end of block to pad the text over to the text column
65 fprintf(out, " "); 127 fprintf(out, " ");
66 count++; 128 count++;
67 } 129 }
68 count = 0; 130 count = 0;
69 fprintf(out, ":"); 131 fprintf(out, ":");
70 while (count < col && off < size) { 132 while (count < cols && off < size) {
71 fprintf(out, "%c", isgraph(buf[off])?buf[off]:'.'); 133 fprintf(out, "%c", isgraph(buf[off])?buf[off]:'.');
72 off++; count ++; 134 off++; count ++;
73 } 135 }
74 136
75 fprintf(out, "\n"); 137 fprintf(out, "\n");
76 count=0; 138 count=0;
77 } 139 }
78 140
79 fprintf(out, "\n"); 141 fprintf(out, "\n");
80 } 142 fflush(out);
81
82
83 static FILE *debug_fp = NULL;
84 static unsigned int max_items=DEBUG_MAX_ITEMS, curr_items=0;
85
86
87 void pst_debug_init(const char* fname) {
88 unsigned char version = DEBUG_VERSION;
89 item_head = item_tail = NULL;
90 curr_items = 0;
91 if (debug_fp) pst_debug_close();
92 if (!fname) return;
93 if ((debug_fp = fopen(fname, "wb")) == NULL) {
94 fprintf(stderr, "Opening of file %s failed\n", fname);
95 exit(1);
96 }
97 pst_debug_fwrite(&version, sizeof(char), 1, debug_fp);
98 }
99
100
101 // function must be called before pst_debug_msg. It sets up the
102 // structure for the function that follows
103 void pst_debug_msg_info(int line, const char* file, int type) {
104 char *x;
105 if (!debug_fp) return; // no file
106 info_ptr = (struct pst_debug_item*) pst_malloc(sizeof(struct pst_debug_item));
107 info_ptr->type = type;
108 info_ptr->line = line;
109 x = (func_head==NULL?"No Function":func_head->name);
110 info_ptr->function = (char*) pst_malloc(strlen(x)+1);
111 strcpy(info_ptr->function, x);
112
113 info_ptr->file = (char*) pst_malloc(strlen(file)+1);
114 strcpy(info_ptr->file, file);
115
116 //put the current record on a temp linked list
117 info_ptr->next = temp_list;
118 temp_list = info_ptr;
119 }
120
121
122 void pst_debug_msg_text(const char* fmt, ...) {
123 va_list ap;
124 int f, g;
125 char x[2];
126 #ifdef _WIN32
127 char *buf = NULL;
128 #endif
129 struct pst_debug_item *temp;
130 if (!debug_fp) return; // no file
131 // get the record off of the temp_list
132 info_ptr = temp_list;
133 if (info_ptr)
134 temp_list = info_ptr->next;
135 else {
136 fprintf(stderr, "NULL info_ptr. ERROR!!\n");
137 exit(-2);
138 }
139
140 #ifdef _WIN32
141 // vsnprintf trick doesn't work on msvc.
142 g = 2000;
143 f = -1;
144 while (f < 0) {
145 buf = realloc(buf, g+1);
146 va_start(ap, fmt);
147 f = vsnprintf(buf, g, fmt, ap);
148 va_end(ap);
149 g += g/2;
150 }
151 free(buf);
152 #else
153 // according to glibc 2.1, this should return the req. number of bytes for
154 // the string
155 va_start(ap, fmt);
156 f = vsnprintf(x, 1, fmt, ap);
157 va_end(ap);
158 #endif
159
160 if (f > 0 && f < MAX_MESSAGE_SIZE) {
161 info_ptr->text = (char*) pst_malloc(f+1);
162 va_start(ap, fmt);
163 if ((g = vsnprintf(info_ptr->text, f, fmt, ap)) == -1) {
164 fprintf(stderr, "_debug_msg: Dying! vsnprintf returned -1 for format \"%s\"\n", fmt);
165 exit(-2);
166 }
167 va_end(ap);
168 info_ptr->text[g] = '\0';
169 if (f != g) {
170 fprintf(stderr, "_debug_msg: f != g\n");
171 }
172 } else if (f > 0) { // it is over the max_message_size then
173 f += strlen(info_ptr->file)+strlen(info_ptr->function);
174 temp = info_ptr;
175 pst_debug_write(); // dump the current messages
176 info_ptr = temp;
177 va_start(ap, fmt);
178 pst_debug_write_msg(info_ptr, fmt, &ap, f);
179 va_end(ap);
180 free(info_ptr->function);
181 free(info_ptr->file);
182 free(info_ptr);
183 info_ptr = NULL;
184 return;
185 } else {
186 fprintf(stderr, "_debug_msg: error getting requested size of debug message\n");
187 info_ptr->text = "ERROR Saving\n";
188 }
189
190 // add to the linked list of pending items
191 if (!item_head) item_head = info_ptr;
192 info_ptr->next = NULL;
193 if (item_tail) item_tail->next = info_ptr;
194 item_tail = info_ptr;
195
196 if (++curr_items == max_items) {
197 // here we will jump off and save the contents
198 pst_debug_write();
199 info_ptr = NULL;
200 }
201 }
202
203
204 void pst_debug_hexdump(char *x, size_t y, int cols, int delta) {
205 struct pst_debug_item *temp;
206 if (!debug_fp) return; // no file
207 info_ptr = temp_list;
208 if (info_ptr) temp_list = info_ptr->next;
209 temp = info_ptr;
210 pst_debug_write();
211 info_ptr = temp;
212 pst_debug_write_hex(info_ptr, x, y, cols);
213 free(info_ptr->function);
214 free(info_ptr->file);
215 free(info_ptr);
216 info_ptr = NULL;
217 }
218
219
220 void pst_debug_func(const char *function) {
221 func_ptr = pst_malloc (sizeof(struct pst_debug_func));
222 func_ptr->name = pst_malloc(strlen(function)+1);
223 strcpy(func_ptr->name, function);
224 func_ptr->next = func_head;
225 func_head = func_ptr;
226 }
227
228
229 void pst_debug_func_ret() {
230 //remove the head item
231 func_ptr = func_head;
232 if (func_head) {
233 func_head = func_head->next;
234 free(func_ptr->name);
235 free(func_ptr);
236 } else {
237 DIE(("function list is empty!\n"));
238 }
239 } 143 }
240 144
241 145
242 void pst_debug_close(void) { 146 void pst_debug_close(void) {
243 pst_debug_write();
244 while (func_head) { 147 while (func_head) {
245 func_ptr = func_head; 148 struct pst_debug_func *func_ptr = func_head;
246 func_head = func_head->next; 149 func_head = func_head->next;
247 free(func_ptr->name); 150 free(func_ptr->name);
248 free(func_ptr); 151 free(func_ptr);
249 } 152 }
250 if (debug_fp) fclose(debug_fp); 153 if (debug_fp) fclose(debug_fp);
251 debug_fp = NULL; 154 debug_fp = NULL;
252 }
253
254
255 static void pst_debug_write() {
256 size_t size, ptr, funcname, filename, text, end;
257 char *buf = NULL, rec_type;
258 if (!debug_fp) return; // no file
259 int64_t index_pos = ftello(debug_fp);
260 int64_t file_pos = index_pos;
261 // add 2. One for the pointer to the next index,
262 // one for the count of this index
263 int index_size = ((curr_items+2) * sizeof(int64_t));
264 int64_t *index;
265 int index_ptr = 0;
266 struct pst_debug_file_rec_m mfile_rec;
267 struct pst_debug_file_rec_l lfile_rec;
268
269 if (curr_items == 0) return; // no items to write.
270
271 index = (int64_t*)pst_malloc(index_size);
272 memset(index, 0, index_size); // valgrind, avoid writing uninitialized data
273 file_pos += index_size;
274 // write the index first, we will re-write it later, but
275 // we want to allocate the space
276 pst_debug_fwrite(index, index_size, 1, debug_fp);
277 index[index_ptr++] = curr_items;
278
279 item_ptr = item_head;
280 while (item_ptr) {
281 file_pos = ftello(debug_fp);
282 index[index_ptr++] = file_pos;
283 size = strlen(item_ptr->function) +
284 strlen(item_ptr->file) +
285 strlen(item_ptr->text) + 3; //for the three \0s
286 if (buf) free(buf);
287 buf = pst_malloc(size+1);
288 ptr = 0;
289 funcname=ptr;
290 ptr += sprintf(&(buf[ptr]), "%s", item_ptr->function)+1;
291 filename=ptr;
292 ptr += sprintf(&(buf[ptr]), "%s", item_ptr->file)+1;
293 text=ptr;
294 ptr += sprintf(&(buf[ptr]), "%s", item_ptr->text)+1;
295 end=ptr;
296 if (end > USHRT_MAX) { // bigger than can be stored in a short
297 rec_type = 'L';
298 pst_debug_fwrite(&rec_type, sizeof(char), 1, debug_fp);
299 lfile_rec.type = item_ptr->type;
300 lfile_rec.line = item_ptr->line;
301 lfile_rec.funcname = funcname;
302 lfile_rec.filename = filename;
303 lfile_rec.text = text;
304 lfile_rec.end = end;
305 pst_debug_fwrite(&lfile_rec, sizeof(lfile_rec), 1, debug_fp);
306 } else {
307 rec_type = 'M';
308 pst_debug_fwrite(&rec_type, sizeof(char), 1, debug_fp);
309 mfile_rec.type = item_ptr->type;
310 mfile_rec.line = item_ptr->line;
311 mfile_rec.funcname = funcname;
312 mfile_rec.filename = filename;
313 mfile_rec.text = text;
314 mfile_rec.end = end;
315 pst_debug_fwrite(&mfile_rec, sizeof(mfile_rec), 1, debug_fp);
316 }
317 pst_debug_fwrite(buf, ptr, 1, debug_fp);
318 if (buf) free(buf); buf = NULL;
319 item_head = item_ptr->next;
320 free(item_ptr->function);
321 free(item_ptr->file);
322 free(item_ptr->text);
323 free(item_ptr);
324 item_ptr = item_head;
325 }
326 curr_items = 0;
327 index[index_ptr] = ftello(debug_fp);
328
329 // we should now have a complete index
330 fseeko(debug_fp, index_pos, SEEK_SET);
331 pst_debug_fwrite(index, index_size, 1, debug_fp);
332 fseeko(debug_fp, 0, SEEK_END);
333 item_ptr = item_head = item_tail = NULL;
334 free(index);
335 if (buf) free(buf);
336 }
337
338
339 static void pst_debug_write_msg(struct pst_debug_item *item, const char *fmt, va_list *ap, int size) {
340 struct pst_debug_file_rec_l lfile_rec;
341 struct pst_debug_file_rec_m mfile_rec;
342 unsigned char rec_type;
343 int index_size = 3 * sizeof(int64_t);
344 int64_t index[3];
345 int64_t index_pos, file_pos;
346 char zero = '\0';
347 unsigned int end;
348 if (!debug_fp) return; // no file
349 index[0] = 1; // only one item in this index
350 index[1] = 0; // valgrind, avoid writing uninitialized data
351 index[2] = 0; // ""
352 index_pos = ftello(debug_fp);
353 pst_debug_fwrite(index, index_size, 1, debug_fp);
354
355 index[1] = ftello(debug_fp);
356
357 if (size > USHRT_MAX) { // bigger than can be stored in a short
358 rec_type = 'L';
359 pst_debug_fwrite(&rec_type, sizeof(char), 1, debug_fp);
360 lfile_rec.type = item->type;
361 lfile_rec.line = item->line;
362 lfile_rec.funcname = 0;
363 lfile_rec.filename = strlen(item->function)+1;
364 lfile_rec.text = lfile_rec.filename+strlen(item->file)+1;
365 lfile_rec.end = 0; // valgrind, avoid writing uninitialized data
366 pst_debug_fwrite(&lfile_rec, sizeof(lfile_rec), 1, debug_fp);
367 } else {
368 rec_type = 'M';
369 pst_debug_fwrite(&rec_type, sizeof(char), 1, debug_fp);
370 mfile_rec.type = item->type;
371 mfile_rec.line = item->line;
372 mfile_rec.funcname = 0;
373 mfile_rec.filename = strlen(item->function)+1;
374 mfile_rec.text = mfile_rec.filename+strlen(item->file)+1;
375 mfile_rec.end = 0; // valgrind, avoid writing uninitialized data
376 pst_debug_fwrite(&mfile_rec, sizeof(mfile_rec), 1, debug_fp);
377 }
378 file_pos = ftello(debug_fp);
379 pst_debug_fwrite(item->function, strlen(item->function)+1, 1, debug_fp);
380 pst_debug_fwrite(item->file, strlen(item->file)+1, 1, debug_fp);
381 vfprintf(debug_fp, fmt, *ap);
382 pst_debug_fwrite(&zero, 1, 1, debug_fp);
383
384 end = (unsigned int) (ftello(debug_fp) - file_pos);
385
386 index[2] = ftello(debug_fp);
387 fseeko(debug_fp, index_pos, SEEK_SET);
388 pst_debug_fwrite(index, index_size, 1, debug_fp);
389 if (size > USHRT_MAX) {
390 pst_debug_fwrite(&rec_type, sizeof(char), 1, debug_fp);
391 lfile_rec.end = end;
392 pst_debug_fwrite(&lfile_rec, sizeof(lfile_rec), 1, debug_fp);
393 } else {
394 pst_debug_fwrite(&rec_type, sizeof(char), 1, debug_fp);
395 mfile_rec.end = end;
396 pst_debug_fwrite(&mfile_rec, sizeof(mfile_rec), 1, debug_fp);
397 }
398 fseeko(debug_fp, 0, SEEK_END);
399 }
400
401
402 void pst_debug_write_hex(struct pst_debug_item *item, char *buf, size_t size, int col) {
403 struct pst_debug_file_rec_l lfile_rec;
404 unsigned char rec_type;
405 int index_size = 3 * sizeof(int64_t);
406 int64_t index_pos, file_pos, index[3];
407 char zero='\0';
408 if (!debug_fp) return; // no file
409 index[0] = 1; // only one item in this index run
410 index[1] = 0; // valgrind, avoid writing uninitialized data
411 index[2] = 0; // ""
412 index_pos = ftello(debug_fp);
413 pst_debug_fwrite(index, index_size, 1, debug_fp);
414 index[1] = ftello(debug_fp);
415
416 // always use the long
417 rec_type = 'L';
418 pst_debug_fwrite(&rec_type, sizeof(char), 1, debug_fp);
419 lfile_rec.funcname = 0;
420 lfile_rec.filename = strlen(item->function)+1;
421 lfile_rec.text = lfile_rec.filename+strlen(item->file)+1;
422 lfile_rec.end = 0; // valgrind, avoid writing uninitialized data
423 lfile_rec.line = item->line;
424 lfile_rec.type = item->type;
425 pst_debug_fwrite(&lfile_rec, sizeof(lfile_rec), 1, debug_fp);
426
427 file_pos = ftello(debug_fp);
428 pst_debug_fwrite(item->function, strlen(item->function)+1, 1, debug_fp);
429 pst_debug_fwrite(item->file, strlen(item->file)+1, 1, debug_fp);
430
431 pst_debug_hexdumper(debug_fp, buf, size, col, 0);
432 pst_debug_fwrite(&zero, 1, 1, debug_fp);
433 lfile_rec.end = ftello(debug_fp) - file_pos;
434
435 index[2] = ftello(debug_fp);
436 fseeko(debug_fp, index_pos, SEEK_SET);
437 pst_debug_fwrite(index, index_size, 1, debug_fp);
438 pst_debug_fwrite(&rec_type, sizeof(char), 1, debug_fp);
439 pst_debug_fwrite(&lfile_rec, sizeof(lfile_rec), 1, debug_fp);
440 fseeko(debug_fp, 0, SEEK_END);
441 } 155 }
442 156
443 157
444 void *pst_malloc(size_t size) { 158 void *pst_malloc(size_t size) {
445 void *mem = malloc(size); 159 void *mem = malloc(size);