@@ -21,7 +21,7 @@ impl Mapping {
21
21
let object = Object :: parse ( & map) ?;
22
22
23
23
// Try to locate an external debug file using the build ID.
24
- if let Some ( path_debug) = object. build_id_debug_path ( ) {
24
+ if let Some ( path_debug) = object. build_id ( ) . and_then ( locate_build_id ) {
25
25
if let Some ( mapping) = Mapping :: new_debug ( path_debug, None ) {
26
26
return Some ( mapping) ;
27
27
}
@@ -251,44 +251,6 @@ impl<'a> Object<'a> {
251
251
None
252
252
}
253
253
254
- // The format of build id paths is documented at:
255
- // https://sourceware.org/gdb/onlinedocs/gdb/Separate-Debug-Files.html
256
- fn build_id_debug_path ( & self ) -> Option < PathBuf > {
257
- const BUILD_ID_PATH : & [ u8 ] = b"/usr/lib/debug/.build-id/" ;
258
- const BUILD_ID_SUFFIX : & [ u8 ] = b".debug" ;
259
-
260
- if !debug_path_exists ( ) {
261
- return None ;
262
- }
263
-
264
- let build_id = self . build_id ( ) ?;
265
- if build_id. len ( ) < 2 {
266
- return None ;
267
- }
268
-
269
- fn hex ( byte : u8 ) -> u8 {
270
- if byte < 10 {
271
- b'0' + byte
272
- } else {
273
- b'a' + byte - 10
274
- }
275
- }
276
-
277
- let mut path = Vec :: with_capacity (
278
- BUILD_ID_PATH . len ( ) + BUILD_ID_SUFFIX . len ( ) + build_id. len ( ) * 2 + 1 ,
279
- ) ;
280
- path. extend ( BUILD_ID_PATH ) ;
281
- path. push ( hex ( build_id[ 0 ] >> 4 ) ) ;
282
- path. push ( hex ( build_id[ 0 ] & 0xf ) ) ;
283
- path. push ( b'/' ) ;
284
- for byte in & build_id[ 1 ..] {
285
- path. push ( hex ( byte >> 4 ) ) ;
286
- path. push ( hex ( byte & 0xf ) ) ;
287
- }
288
- path. extend ( BUILD_ID_SUFFIX ) ;
289
- Some ( PathBuf :: from ( OsString :: from_vec ( path) ) )
290
- }
291
-
292
254
// The contents of the ".gnu_debuglink" section is documented at:
293
255
// https://sourceware.org/gdb/onlinedocs/gdb/Separate-Debug-Files.html
294
256
fn gnu_debuglink_path ( & self , path : & Path ) -> Option < ( PathBuf , u32 ) > {
@@ -305,14 +267,14 @@ impl<'a> Object<'a> {
305
267
Some ( ( path_debug, crc) )
306
268
}
307
269
308
- // The format if the ".gnu_debugaltlink" section is based on gdb.
270
+ // The format of the ".gnu_debugaltlink" section is based on gdb.
309
271
fn gnu_debugaltlink_path ( & self , path : & Path ) -> Option < ( PathBuf , & ' a [ u8 ] ) > {
310
272
let section = self . section_header ( ".gnu_debugaltlink" ) ?;
311
273
let data = section. data ( self . endian , self . data ) . ok ( ) ?;
312
274
let len = data. iter ( ) . position ( |x| * x == 0 ) ?;
313
275
let filename = & data[ ..len] ;
314
276
let build_id = & data[ len + 1 ..] ;
315
- let path_sup = locate_debuglink ( path, filename) ?;
277
+ let path_sup = locate_debugaltlink ( path, filename, build_id ) ?;
316
278
Some ( ( path_sup, build_id) )
317
279
}
318
280
}
@@ -362,8 +324,55 @@ fn debug_path_exists() -> bool {
362
324
}
363
325
}
364
326
365
- // Search order matches gdb, documented at:
366
- // https://sourceware.org/gdb/onlinedocs/gdb/Separate-Debug-Files.html
327
+ /// Locate a debug file based on its build ID.
328
+ ///
329
+ /// The format of build id paths is documented at:
330
+ /// https://sourceware.org/gdb/onlinedocs/gdb/Separate-Debug-Files.html
331
+ fn locate_build_id ( build_id : & [ u8 ] ) -> Option < PathBuf > {
332
+ const BUILD_ID_PATH : & [ u8 ] = b"/usr/lib/debug/.build-id/" ;
333
+ const BUILD_ID_SUFFIX : & [ u8 ] = b".debug" ;
334
+
335
+ if build_id. len ( ) < 2 {
336
+ return None ;
337
+ }
338
+
339
+ if !debug_path_exists ( ) {
340
+ return None ;
341
+ }
342
+
343
+ let mut path =
344
+ Vec :: with_capacity ( BUILD_ID_PATH . len ( ) + BUILD_ID_SUFFIX . len ( ) + build_id. len ( ) * 2 + 1 ) ;
345
+ path. extend ( BUILD_ID_PATH ) ;
346
+ path. push ( hex ( build_id[ 0 ] >> 4 ) ) ;
347
+ path. push ( hex ( build_id[ 0 ] & 0xf ) ) ;
348
+ path. push ( b'/' ) ;
349
+ for byte in & build_id[ 1 ..] {
350
+ path. push ( hex ( byte >> 4 ) ) ;
351
+ path. push ( hex ( byte & 0xf ) ) ;
352
+ }
353
+ path. extend ( BUILD_ID_SUFFIX ) ;
354
+ Some ( PathBuf :: from ( OsString :: from_vec ( path) ) )
355
+ }
356
+
357
+ fn hex ( byte : u8 ) -> u8 {
358
+ if byte < 10 {
359
+ b'0' + byte
360
+ } else {
361
+ b'a' + byte - 10
362
+ }
363
+ }
364
+
365
+ /// Locate a file specified in a `.gnu_debuglink` section.
366
+ ///
367
+ /// `path` is the file containing the section.
368
+ /// `filename` is from the contents of the section.
369
+ ///
370
+ /// Search order is based on gdb, documented at:
371
+ /// https://sourceware.org/gdb/onlinedocs/gdb/Separate-Debug-Files.html
372
+ ///
373
+ /// gdb also allows the user to customize the debug search path, but we don't.
374
+ ///
375
+ /// gdb also supports debuginfod, but we don't yet.
367
376
fn locate_debuglink ( path : & Path , filename : & [ u8 ] ) -> Option < PathBuf > {
368
377
let path = fs:: canonicalize ( path) . ok ( ) ?;
369
378
let parent = path. parent ( ) ?;
@@ -400,3 +409,32 @@ fn locate_debuglink(path: &Path, filename: &[u8]) -> Option<PathBuf> {
400
409
401
410
None
402
411
}
412
+
413
+ /// Locate a file specified in a `.gnu_debugaltlink` section.
414
+ ///
415
+ /// `path` is the file containing the section.
416
+ /// `filename` and `build_id` are the contents of the section.
417
+ ///
418
+ /// Search order is based on gdb:
419
+ /// - filename, which is either absolute or relative to `path`
420
+ /// - the build ID path under `BUILD_ID_PATH`
421
+ ///
422
+ /// gdb also allows the user to customize the debug search path, but we don't.
423
+ ///
424
+ /// gdb also supports debuginfod, but we don't yet.
425
+ fn locate_debugaltlink ( path : & Path , filename : & [ u8 ] , build_id : & [ u8 ] ) -> Option < PathBuf > {
426
+ let filename = Path :: new ( OsStr :: from_bytes ( filename) ) ;
427
+ if filename. is_absolute ( ) {
428
+ if filename. is_file ( ) {
429
+ return Some ( filename. into ( ) ) ;
430
+ }
431
+ } else {
432
+ let mut f = PathBuf :: from ( path) ;
433
+ f. push ( filename) ;
434
+ if f. is_file ( ) {
435
+ return Some ( f) ;
436
+ }
437
+ }
438
+
439
+ locate_build_id ( build_id)
440
+ }
0 commit comments