1use crate::{register::MANAGER, Dylib, ElfLibrary};
2use core::{ffi::CStr, fmt::Debug};
3
4pub struct DlInfo {
5 dylib: Dylib,
7 sname: Option<&'static CStr>,
9 saddr: usize,
11}
12
13impl DlInfo {
14 #[inline]
15 pub fn dylib(&self) -> &Dylib {
16 &self.dylib
17 }
18
19 #[inline]
21 pub fn symbol_name(&self) -> Option<&CStr> {
22 self.sname
23 }
24
25 #[inline]
27 pub fn symbol_addr(&self) -> Option<usize> {
28 if self.saddr == 0 {
29 None
30 } else {
31 Some(self.saddr)
32 }
33 }
34}
35
36impl Debug for DlInfo {
37 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
38 f.debug_struct("DlInfo")
39 .field("dylib", &self.dylib)
40 .field("sname", &self.sname)
41 .field("saddr", &format_args!("{:#x}", self.saddr))
42 .finish()
43 }
44}
45
46impl ElfLibrary {
47 fn addr2dso(addr: usize) -> Option<Dylib> {
48 MANAGER.read().all.values().find_map(|v| {
49 let start = v.relocated_dylib_ref().base();
50 let end = start + v.relocated_dylib_ref().map_len();
51 if (start..end).contains(&addr) {
52 Some(v.get_dylib())
53 } else {
54 None
55 }
56 })
57 }
58
59 pub fn dladdr(addr: usize) -> Option<DlInfo> {
63 log::info!(
64 "dladdr: Try to find the symbol information corresponding to [{:#x}]",
65 addr
66 );
67 Self::addr2dso(addr).map(|dylib| {
68 let mut dl_info = DlInfo {
69 dylib,
70 sname: None,
71 saddr: 0,
72 };
73 let symtab = dl_info.dylib.inner.symtab();
74 for i in 0..symtab.count_syms() {
75 let (sym, syminfo) = symtab.symbol_idx(i);
76 let start = dl_info.dylib.base() + sym.st_value();
77 let end = start + sym.st_size();
78 if sym.st_value() != 0
79 && sym.is_ok_bind()
80 && sym.is_ok_type()
81 && (start..end).contains(&addr)
82 {
83 dl_info.sname = Some(unsafe { core::mem::transmute(syminfo.cname().unwrap()) });
84 dl_info.saddr = start;
85 }
86 }
87 dl_info
88 })
89 }
90}