@@ -20,6 +20,7 @@ use blazesym::symbolize::InlinedFn;
20
20
use blazesym:: symbolize:: Input ;
21
21
use blazesym:: symbolize:: Kernel ;
22
22
use blazesym:: symbolize:: Process ;
23
+ use blazesym:: symbolize:: Reason ;
23
24
use blazesym:: symbolize:: Source ;
24
25
use blazesym:: symbolize:: Sym ;
25
26
use blazesym:: symbolize:: Symbolized ;
@@ -315,6 +316,81 @@ impl From<blaze_symbolize_src_gsym_file> for GsymFile {
315
316
pub type blaze_symbolizer = Symbolizer ;
316
317
317
318
319
+ /// The reason why symbolization failed.
320
+ ///
321
+ /// The reason is generally only meant as a hint. Reasons reported may
322
+ /// change over time and, hence, should not be relied upon for the
323
+ /// correctness of the application.
324
+ #[ repr( u8 ) ]
325
+ #[ derive( Copy , Clone , Debug , PartialEq ) ]
326
+ pub enum blaze_symbolize_reason {
327
+ /// Symbolization was successful.
328
+ BLAZE_SYMBOLIZE_REASON_SUCCESS = 0 ,
329
+ /// The absolute address was not found in the corresponding process'
330
+ /// virtual memory map.
331
+ BLAZE_SYMBOLIZE_REASON_UNMAPPED ,
332
+ /// The file offset does not map to a valid piece of code/data.
333
+ BLAZE_SYMBOLIZE_REASON_INVALID_FILE_OFFSET ,
334
+ /// The `/proc/<pid>/maps` entry corresponding to the address does
335
+ /// not have a component (file system path, object, ...) associated
336
+ /// with it.
337
+ BLAZE_SYMBOLIZE_REASON_MISSING_COMPONENT ,
338
+ /// The symbolization source has no or no relevant symbols.
339
+ BLAZE_SYMBOLIZE_REASON_MISSING_SYMS ,
340
+ /// The address could not be found in the symbolization source.
341
+ BLAZE_SYMBOLIZE_REASON_UNKNOWN_ADDR ,
342
+ /// The address belonged to an entity that is currently unsupported.
343
+ BLAZE_SYMBOLIZE_REASON_UNSUPPORTED ,
344
+ }
345
+
346
+ impl From < Reason > for blaze_symbolize_reason {
347
+ fn from ( reason : Reason ) -> Self {
348
+ use blaze_symbolize_reason:: * ;
349
+
350
+ match reason {
351
+ Reason :: Unmapped => BLAZE_SYMBOLIZE_REASON_UNMAPPED ,
352
+ Reason :: InvalidFileOffset => BLAZE_SYMBOLIZE_REASON_INVALID_FILE_OFFSET ,
353
+ Reason :: MissingComponent => BLAZE_SYMBOLIZE_REASON_MISSING_COMPONENT ,
354
+ Reason :: MissingSyms => BLAZE_SYMBOLIZE_REASON_MISSING_SYMS ,
355
+ Reason :: Unsupported => BLAZE_SYMBOLIZE_REASON_UNSUPPORTED ,
356
+ Reason :: UnknownAddr => BLAZE_SYMBOLIZE_REASON_UNKNOWN_ADDR ,
357
+ _ => unreachable ! ( ) ,
358
+ }
359
+ }
360
+ }
361
+
362
+
363
+ /// Retrieve a textual representation of the reason of a symbolization
364
+ /// failure.
365
+ #[ no_mangle]
366
+ pub extern "C" fn blaze_symbolize_reason_str ( err : blaze_symbolize_reason ) -> * const c_char {
367
+ use blaze_symbolize_reason:: * ;
368
+
369
+ match err as i32 {
370
+ e if e == BLAZE_SYMBOLIZE_REASON_SUCCESS as i32 => b"success\0 " . as_ptr ( ) . cast ( ) ,
371
+ e if e == BLAZE_SYMBOLIZE_REASON_UNMAPPED as i32 => {
372
+ Reason :: Unmapped . as_bytes ( ) . as_ptr ( ) . cast ( )
373
+ }
374
+ e if e == BLAZE_SYMBOLIZE_REASON_INVALID_FILE_OFFSET as i32 => {
375
+ Reason :: InvalidFileOffset . as_bytes ( ) . as_ptr ( ) . cast ( )
376
+ }
377
+ e if e == BLAZE_SYMBOLIZE_REASON_MISSING_COMPONENT as i32 => {
378
+ Reason :: MissingComponent . as_bytes ( ) . as_ptr ( ) . cast ( )
379
+ }
380
+ e if e == BLAZE_SYMBOLIZE_REASON_MISSING_SYMS as i32 => {
381
+ Reason :: MissingSyms . as_bytes ( ) . as_ptr ( ) . cast ( )
382
+ }
383
+ e if e == BLAZE_SYMBOLIZE_REASON_UNKNOWN_ADDR as i32 => {
384
+ Reason :: UnknownAddr . as_bytes ( ) . as_ptr ( ) . cast ( )
385
+ }
386
+ e if e == BLAZE_SYMBOLIZE_REASON_UNSUPPORTED as i32 => {
387
+ Reason :: Unsupported . as_bytes ( ) . as_ptr ( ) . cast ( )
388
+ }
389
+ _ => b"unknown reason\0 " . as_ptr ( ) . cast ( ) ,
390
+ }
391
+ }
392
+
393
+
318
394
/// Source code location information for a symbol or inlined function.
319
395
#[ repr( C ) ]
320
396
#[ derive( Debug ) ]
@@ -384,8 +460,11 @@ pub struct blaze_sym {
384
460
pub inlined_cnt : usize ,
385
461
/// An array of `inlined_cnt` symbolized inlined function calls.
386
462
pub inlined : * const blaze_symbolize_inlined_fn ,
463
+ /// On error (i.e., if `name` is NULL), a reason trying to explain
464
+ /// why symbolization failed.
465
+ pub reason : blaze_symbolize_reason ,
387
466
/// Unused member available for future expansion.
388
- pub reserved : [ u8 ; 8 ] ,
467
+ pub reserved : [ u8 ; 7 ] ,
389
468
}
390
469
391
470
/// `blaze_result` is the result of symbolization for C API.
@@ -683,6 +762,7 @@ fn convert_symbolizedresults_to_c(results: Vec<Symbolized>) -> *const blaze_resu
683
762
convert_code_info ( & sym. code_info , & mut sym_ref. code_info , & mut make_cstr) ;
684
763
sym_ref. inlined_cnt = sym. inlined . len ( ) ;
685
764
sym_ref. inlined = inlined_last;
765
+ sym_ref. reason = blaze_symbolize_reason:: BLAZE_SYMBOLIZE_REASON_SUCCESS ;
686
766
687
767
for inlined in sym. inlined . iter ( ) {
688
768
let inlined_ref = unsafe { & mut * inlined_last } ;
@@ -698,12 +778,14 @@ fn convert_symbolizedresults_to_c(results: Vec<Symbolized>) -> *const blaze_resu
698
778
inlined_last = unsafe { inlined_last. add ( 1 ) } ;
699
779
}
700
780
}
701
- Symbolized :: Unknown ( .. ) => {
781
+ Symbolized :: Unknown ( reason ) => {
702
782
// Unknown symbols/addresses are just represented with all
703
- // fields set to zero.
783
+ // fields set to zero (except for reason) .
704
784
// SAFETY: `syms_last` is pointing to a writable and properly
705
785
// aligned `blaze_sym` object.
706
786
let ( ) = unsafe { syms_last. write_bytes ( 0 , 1 ) } ;
787
+ let sym_ref = unsafe { & mut * syms_last } ;
788
+ sym_ref. reason = reason. into ( ) ;
707
789
}
708
790
}
709
791
@@ -1099,11 +1181,12 @@ mod tests {
1099
1181
} ,
1100
1182
inlined_cnt : 0 ,
1101
1183
inlined : ptr:: null ( ) ,
1102
- reserved : [ 0u8 ; 8 ] ,
1184
+ reason : blaze_symbolize_reason:: BLAZE_SYMBOLIZE_REASON_UNSUPPORTED ,
1185
+ reserved : [ 0u8 ; 7 ] ,
1103
1186
} ;
1104
1187
assert_eq ! (
1105
1188
format!( "{sym:?}" ) ,
1106
- "blaze_sym { name: 0x0, addr: 4919, offset: 24, code_info: blaze_symbolize_code_info { dir: 0x0, file: 0x0, line: 42, column: 1, reserved: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] }, inlined_cnt: 0, inlined: 0x0, reserved: [0, 0, 0, 0, 0, 0, 0, 0] }"
1189
+ "blaze_sym { name: 0x0, addr: 4919, offset: 24, code_info: blaze_symbolize_code_info { dir: 0x0, file: 0x0, line: 42, column: 1, reserved: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] }, inlined_cnt: 0, inlined: 0x0, reason: BLAZE_SYMBOLIZE_REASON_UNSUPPORTED, reserved: [ 0, 0, 0, 0, 0, 0, 0] }"
1107
1190
) ;
1108
1191
1109
1192
let inlined = blaze_symbolize_inlined_fn {
@@ -1136,6 +1219,36 @@ mod tests {
1136
1219
) ;
1137
1220
}
1138
1221
1222
+ /// Make sure that we can stringify symbolization reasons as expected.
1223
+ #[ tag( miri) ]
1224
+ #[ test]
1225
+ fn reason_stringification ( ) {
1226
+ use blaze_symbolize_reason:: * ;
1227
+
1228
+ let data = [
1229
+ ( Reason :: Unmapped , BLAZE_SYMBOLIZE_REASON_UNMAPPED ) ,
1230
+ (
1231
+ Reason :: InvalidFileOffset ,
1232
+ BLAZE_SYMBOLIZE_REASON_INVALID_FILE_OFFSET ,
1233
+ ) ,
1234
+ (
1235
+ Reason :: MissingComponent ,
1236
+ BLAZE_SYMBOLIZE_REASON_MISSING_COMPONENT ,
1237
+ ) ,
1238
+ ( Reason :: MissingSyms , BLAZE_SYMBOLIZE_REASON_MISSING_SYMS ) ,
1239
+ ( Reason :: Unsupported , BLAZE_SYMBOLIZE_REASON_UNSUPPORTED ) ,
1240
+ ( Reason :: UnknownAddr , BLAZE_SYMBOLIZE_REASON_UNKNOWN_ADDR ) ,
1241
+ ] ;
1242
+
1243
+ for ( reason, expected) in data {
1244
+ assert_eq ! ( blaze_symbolize_reason:: from( reason) , expected) ;
1245
+ let cstr = unsafe { CStr :: from_ptr ( blaze_symbolize_reason_str ( expected) ) } ;
1246
+ let expected = CStr :: from_bytes_with_nul ( reason. as_bytes ( ) ) . unwrap ( ) ;
1247
+ assert_eq ! ( cstr, expected) ;
1248
+ }
1249
+ }
1250
+
1251
+
1139
1252
/// Check that we can convert a [`blaze_symbolize_src_kernel`]
1140
1253
/// reference into a [`Kernel`].
1141
1254
#[ tag( miri) ]
@@ -1201,6 +1314,7 @@ mod tests {
1201
1314
code_info,
1202
1315
inlined_cnt,
1203
1316
inlined,
1317
+ reason,
1204
1318
reserved : _,
1205
1319
} = sym;
1206
1320
@@ -1219,6 +1333,7 @@ mod tests {
1219
1333
let ( ) = touch_cstr ( * name) ;
1220
1334
let ( ) = touch_code_info ( code_info) ;
1221
1335
}
1336
+ let ( ) = touch ( reason) ;
1222
1337
}
1223
1338
}
1224
1339
@@ -1327,6 +1442,10 @@ mod tests {
1327
1442
unsafe { CStr :: from_ptr( sym. name) } ,
1328
1443
CStr :: from_bytes_with_nul( b"factorial\0 " ) . unwrap( )
1329
1444
) ;
1445
+ assert_eq ! (
1446
+ sym. reason,
1447
+ blaze_symbolize_reason:: BLAZE_SYMBOLIZE_REASON_SUCCESS
1448
+ ) ;
1330
1449
assert_eq ! ( sym. addr, 0x2000100 ) ;
1331
1450
assert_eq ! ( sym. offset, 0 ) ;
1332
1451
@@ -1697,6 +1816,10 @@ mod tests {
1697
1816
// Shouldn't have symbolized because the debug link target cannot be
1698
1817
// found.
1699
1818
assert_eq ! ( sym. name, ptr:: null( ) ) ;
1819
+ assert_eq ! (
1820
+ sym. reason,
1821
+ blaze_symbolize_reason:: BLAZE_SYMBOLIZE_REASON_MISSING_SYMS
1822
+ ) ;
1700
1823
1701
1824
let ( ) = unsafe { blaze_result_free ( result) } ;
1702
1825
let ( ) = unsafe { blaze_symbolizer_free ( symbolizer) } ;
0 commit comments