43
43
#include <errno.h>
44
44
#include <string.h>
45
45
#include <stdlib.h>
46
+ #include <ctype.h>
46
47
#include <execinfo.h>
47
48
48
49
// clang speciality
@@ -224,12 +225,12 @@ static int _dump_less_shabby( struct mulle_stacktrace *stacktrace,
224
225
225
226
226
227
static void _shabby_default_dump ( struct mulle_stacktrace * stacktrace ,
227
- void * * callstack ,
228
- int frames ,
229
- int offset ,
230
- FILE * fp ,
231
- char * delimchar ,
232
- enum mulle_stacktrace_format format )
228
+ void * * callstack ,
229
+ int frames ,
230
+ int offset ,
231
+ FILE * fp ,
232
+ char * delimchar ,
233
+ enum mulle_stacktrace_format format )
233
234
{
234
235
char * * strs ;
235
236
char * * p ;
@@ -262,6 +263,10 @@ static struct mulle_stacktrace dummy =
262
263
};
263
264
264
265
266
+ // csv output:
267
+ //
268
+ // address,symbol,symbol_offset,segment_name,segment_offset
269
+ //
265
270
static void mulle_stacktrace_dump ( struct mulle_stacktrace * stacktrace ,
266
271
void * * callstack ,
267
272
int frames ,
@@ -272,17 +277,25 @@ static void mulle_stacktrace_dump( struct mulle_stacktrace *stacktrace,
272
277
{
273
278
char * delim ;
274
279
char * s ;
280
+ char * segment_name ;
281
+ char * symbol_name ;
282
+ char buf [ 512 ];
275
283
Dl_info info ;
276
- ptrdiff_t diff ;
277
- size_t max ;
278
284
int havedl ;
285
+ int i ;
286
+ intptr_t segment_offset ;
287
+ intptr_t symbol_offset ;
288
+ size_t max ;
279
289
void * * p ;
280
290
void * * sentinel ;
281
291
void * address ;
292
+ void * segment_address ;
293
+ void * symbol_address ;
282
294
void * userinfo ;
283
- // char **strs;
284
- char buf [ 512 ];
285
- int i ;
295
+ #if 0
296
+ int symbol_name_length ;
297
+ int segment_name_length ;
298
+ #endif
286
299
287
300
// non underscore shouldn't crash for NULL params
288
301
if ( ! stacktrace || ! callstack || ! fp || ! delimchar )
@@ -300,54 +313,107 @@ static void mulle_stacktrace_dump( struct mulle_stacktrace *stacktrace,
300
313
delim = (i == 0 ) ? "" : delimchar ;
301
314
++ i ;
302
315
303
- address = * -- p ;
304
- max = 0x800 ;
316
+ address = * -- p ;
317
+ symbol_address = NULL ;
318
+ segment_address = NULL ;
319
+ symbol_offset = 0 ;
320
+ segment_offset = (intptr_t ) address ;
321
+ symbol_name = "" ;
322
+ segment_name = "" ;
323
+
305
324
//musl doesn't have it ?
325
+ max = 0x800 ;
306
326
havedl = dladdr ( address , & info );
307
- if ( havedl && info . dli_saddr )
327
+ if ( havedl )
308
328
{
309
- max = (intptr_t ) address - (intptr_t ) info .dli_saddr ;
310
- if ( max > 0x800 )
311
- max = 0x800 ;
329
+ if ( info .dli_saddr )
330
+ {
331
+ symbol_address = info .dli_saddr ;
332
+ symbol_offset = (intptr_t ) address - (intptr_t ) symbol_address ;
333
+ max = symbol_offset < max ? symbol_offset : max ;
334
+ }
335
+ segment_name = info .dli_fname ? (char * ) info .dli_fname : "" ;
336
+ segment_address = info .dli_fbase ;
337
+ segment_offset = (intptr_t ) address - (intptr_t ) segment_address ;
338
+ symbol_name = info .dli_sname ? (char * ) info .dli_sname : "" ;
312
339
}
313
340
314
- // try to improve on max with symbolizer
341
+ // try to improve on max with symbolizer, if we aren't close enough
342
+ // complete heuristic
315
343
if ( max )
316
344
{
317
345
s = stacktrace -> symbolize ( address , max - 1 , buf , sizeof ( buf ), & userinfo );
318
- if ( s )
346
+ if ( s && (! symbol_name || strcmp ( symbol_name , s )) )
319
347
{
320
- if ( ! stacktrace -> is_boring ( s , -1 ))
321
- fprintf ( fp , "%s %s" , delim , s );
322
- continue ;
348
+ symbol_name = s ;
349
+ symbol_offset = 0 ; // now unknown really
323
350
}
324
351
}
325
352
353
+ #if 0
354
+ // for some weird reason symbol_name and segment_name have linefeeds
355
+ // at the end
356
+ symbol_name_length = symbol_name ? strlen ( symbol_name ) : 0 ;
357
+ while ( symbol_name_length )
358
+ {
359
+ if ( isprint ( symbol_name [ symbol_name_length - 1 ]))
360
+ break ;
361
+ symbol_name_length -- ;
362
+ }
363
+
364
+ segment_name_length = segment_name ? strlen ( segment_name ) : 0 ;
365
+ while ( segment_name_length )
366
+ {
367
+ if ( isprint ( segment_name [ segment_name_length - 1 ]))
368
+ break ;
369
+ segment_name_length -- ;
370
+ }
371
+ #endif
372
+
373
+ // address,segment_offset,symbol_offset,symbol_address,symbol_name,segment_address,segment_name
374
+ if ( format == mulle_stacktrace_csv )
375
+ {
376
+ fprintf ( fp , "%p,0x%tx,0x%td," ,
377
+ address ,
378
+ segment_offset ,
379
+ symbol_offset );
380
+ if ( symbol_address )
381
+ fprintf ( fp , "%p,\"%s\"," ,
382
+ symbol_address ,
383
+ symbol_name );
384
+ else
385
+ fprintf ( fp , ",\"%s\"," , symbol_name );
386
+
387
+ fprintf ( fp , "0x%tx,\"%s\"\n" ,
388
+ (intptr_t ) segment_address ,
389
+ segment_name );
390
+
391
+ continue ;
392
+ }
393
+
326
394
if ( havedl )
327
395
{
328
- if ( info . dli_sname )
396
+ if ( symbol_name )
329
397
{
330
- if ( ! stacktrace -> is_boring ( (char * ) info .dli_sname , -1 ))
331
- {
332
- diff = (intptr_t ) address - (intptr_t ) info .dli_saddr ;
333
- if ( diff )
334
- fprintf ( fp , "%s %s+0x%0lx" , delim , info .dli_sname , (long ) diff );
335
- else
336
- fprintf ( fp , "%s %s" , delim , info .dli_sname );
337
- }
338
- continue ;
398
+ if ( stacktrace -> is_boring ( (char * ) symbol_name , -1 ))
399
+ continue ;
400
+
401
+ if ( symbol_offset )
402
+ fprintf ( fp , "%s %s+0x%0lx" , delim , symbol_name , (long ) symbol_offset );
403
+ else
404
+ fprintf ( fp , "%s %s" , delim , symbol_name );
339
405
}
340
406
341
- if ( info . dli_fname )
407
+ if ( segment_name )
342
408
{
343
- s = strrchr ( info . dli_fname , '/' );
409
+ s = strrchr ( segment_name , '/' );
344
410
if ( s )
345
411
s = & s [ 1 ];
346
412
else
347
- s = (char * ) info . dli_fname ;
413
+ s = (char * ) segment_name ;
348
414
349
415
// relative address of shared lib is not really useful
350
- fprintf ( fp , "%s %s:%p " , delim , s , address );
416
+ fprintf ( fp , "%s %s:0x%tx " , delim , s , segment_offset );
351
417
continue ;
352
418
}
353
419
}
@@ -377,11 +443,28 @@ void _mulle_stacktrace( struct mulle_stacktrace *stacktrace,
377
443
if ( ! fp )
378
444
fp = stderr ;
379
445
380
- delimchar = "\n" ;
381
- if ( ! (format & mulle_stacktrace_linefeed ))
446
+
447
+ // mulle_stacktrace_normal = 0,
448
+ // mulle_stacktrace_trimmed = 1,
449
+ // mulle_stacktrace_linefeed = 2,
450
+ // mulle_stacktrace_csv = 3
451
+
452
+ switch ( format )
382
453
{
454
+ case mulle_stacktrace_normal :
455
+ case mulle_stacktrace_trimmed :
383
456
fprintf ( fp , " : [" );
384
- delimchar = " |" ;
457
+ delimchar = " |" ;;
458
+ break ;
459
+
460
+ case mulle_stacktrace_linefeed :
461
+ delimchar = "\n" ;
462
+ break ;
463
+
464
+ default :
465
+ fprintf ( fp , "address,segment_offset,symbol_offset,symbol_address,symbol_name,segment_address,segment_name\n" );
466
+ delimchar = "\n" ;
467
+ break ;
385
468
}
386
469
387
470
{
@@ -396,7 +479,15 @@ void _mulle_stacktrace( struct mulle_stacktrace *stacktrace,
396
479
#endif
397
480
}
398
481
399
- fputc ( (format & mulle_stacktrace_linefeed ) ? '\n' : ']' , fp );
482
+ switch ( format )
483
+ {
484
+ case mulle_stacktrace_normal : // fall thru
485
+ case mulle_stacktrace_trimmed : fputc ( ']' , fp );
486
+ break ;
487
+
488
+ case mulle_stacktrace_linefeed : fputc ( '\n' , fp ); // fall thru
489
+ default : break ;
490
+ }
400
491
}
401
492
402
493
0 commit comments