@ -82,36 +82,7 @@ impl UProbe {
target : T ,
target : T ,
pid : Option < pid_t > ,
pid : Option < pid_t > ,
) -> Result < UProbeLinkId , ProgramError > {
) -> Result < UProbeLinkId , ProgramError > {
let target = target . as_ref ( ) ;
let path = resolve_attach_path ( target , pid ) ? ;
let target_str = & * target . as_os_str ( ) . to_string_lossy ( ) ;
let mut path = if let Some ( pid ) = pid {
find_lib_in_proc_maps ( pid , target_str ) . map_err ( | io_error | UProbeError ::FileError {
filename : format ! ( "/proc/{pid}/maps" ) ,
io_error ,
} ) ?
} else {
None
} ;
if path . is_none ( ) {
path = if target . is_absolute ( ) {
Some ( target_str )
} else {
let cache =
LD_SO_CACHE
. as_ref ( )
. map_err ( | error | UProbeError ::InvalidLdSoCache {
io_error : error . clone ( ) ,
} ) ? ;
cache . resolve ( target_str )
}
. map ( String ::from )
} ;
let path = path . ok_or ( UProbeError ::InvalidTarget {
path : target . to_owned ( ) ,
} ) ? ;
let sym_offset = if let Some ( fn_name ) = fn_name {
let sym_offset = if let Some ( fn_name ) = fn_name {
resolve_symbol ( & path , fn_name ) . map_err ( | error | UProbeError ::SymbolError {
resolve_symbol ( & path , fn_name ) . map_err ( | error | UProbeError ::SymbolError {
@ -152,6 +123,64 @@ impl UProbe {
}
}
}
}
fn resolve_attach_path < T : AsRef < Path > > (
target : T ,
pid : Option < pid_t > ,
) -> Result < String , UProbeError > {
// Look up the path for the target. If it there is a pid, and the target is a library name that
// is in the process's memory map, use the path of that library. Otherwise, use the target
// as-is.
let target = target . as_ref ( ) ;
let target_str = & * target . as_os_str ( ) . to_string_lossy ( ) ;
let mut path = if let Some ( pid ) = pid {
find_lib_in_proc_maps ( pid , target_str ) . map_err ( | io_error | UProbeError ::FileError {
filename : format ! ( "/proc/{pid}/maps" ) ,
io_error ,
} ) ?
} else {
None
} ;
if path . is_none ( ) {
path = if target . is_absolute ( ) {
Some ( target_str )
} else {
let cache = LD_SO_CACHE
. as_ref ( )
. map_err ( | error | UProbeError ::InvalidLdSoCache {
io_error : error . clone ( ) ,
} ) ? ;
cache . resolve ( target_str )
}
. map ( String ::from )
} ;
path . ok_or ( UProbeError ::InvalidTarget {
path : target . to_owned ( ) ,
} )
}
// Only run this test on linux with glibc because only in that configuration do we know that we'll
// be dynamically linked to libc and can exercise resolving the path to libc via the current
// process's memory map.
#[ test ]
#[ cfg_attr(
any ( miri , not ( all ( target_os = "linux" , target_env = "gnu" ) ) ) ,
ignore = "requires glibc, doesn't work in miri"
) ]
fn test_resolve_attach_path ( ) {
// Look up the current process's pid.
let pid = std ::process ::id ( ) . try_into ( ) . unwrap ( ) ;
// Now let's resolve the path to libc. It should exist in the current process's memory map and
// then in the ld.so.cache.
let libc_path = resolve_attach_path ( "libc" , Some ( pid ) ) . unwrap ( ) ;
// Make sure we got a path that contains libc.
assert! ( libc_path . contains ( "libc" ) , "libc_path: {}" , libc_path ) ;
}
define_link_wrapper ! (
define_link_wrapper ! (
/// The link used by [UProbe] programs.
/// The link used by [UProbe] programs.
UProbeLink ,
UProbeLink ,