Получение имени символа по адресу в исполняемом файле Linux DWARF - PullRequest
0 голосов
/ 20 января 2020

В приложении, построенном с отладочными символами, мне нужна функция, которая при наличии адреса возвращает имя символа (если существует) по этому адресу.

Мне известно о dladdr(), но оно работает только для символы в общих библиотеках, а не символы в исполняемом файле или в библиотеках stati c.

В качестве примера того, как это должно работать, в gdb я могу сделать info symbol 0x..., и это дает мне имя. Для того же адреса я должен быть в состоянии сделать symbolName(0x...) и я должен получить то же имя.

Я предполагаю, что не существует легкодоступного решения для этого, поэтому я рад реализовать это сам, но я не уверен, с чего начать. Я могу проанализировать информацию DWARF об исполняемом файле, но тогда я не уверен, где искать в DWARF.

Спасибо

Ответы [ 2 ]

0 голосов
/ 21 января 2020

Одним из решений является использование ELF для символов в текущем исполняемом файле и dladdr() для символов в динамически загружаемых библиотеках.

Вот полный код в Rust (используется гоблин ящик для чтения ELF):

use std::collections::HashMap;
use std::ffi::CString;
use goblin::elf::Elf;

/// Returns a map from addresses to symbols in the current executable.
fn addr_to_sym() -> HashMap<u64, String> {
    let exec_path = std::fs::read_link("/proc/self/exe");
    println!("exec_path: {:#?}", exec_path);

    let mut addr_to_sym: HashMap<u64, String> = HashMap::new();

    if let Ok(exec_path) = exec_path {
        if let Ok(exec_bytes) = std::fs::read(exec_path) {
            if let Ok(elf) = Elf::parse(&exec_bytes) {
                for sym in elf.syms.iter() {
                    if let Some(Ok(str)) = elf.strtab.get(sym.st_name) {
                        if sym.st_value == 0 {
                            // Can't find address of the symbol in the current binary, try dlsym
                            let dyn_addr = unsafe {
                                libc::dlsym(libc::RTLD_DEFAULT, CString::new(str).unwrap().as_ptr())
                            };
                            if !dyn_addr.is_null() {
                                addr_to_sym.insert(dyn_addr as u64, str.to_owned());
                            }
                        } else {
                            addr_to_sym.insert(sym.st_value, str.to_owned());
                        }
                    }
                }
            }
        }
    }

    addr_to_sym
}

Используя эту карту, я могу найти символы как в текущем исполняемом файле (который включает статически связанные зависимости), так и в динамических c зависимостях.

0 голосов
/ 20 января 2020

Полагаю, что для этого не существует готового решения, поэтому я рад реализовать это сам, но не знаю, с чего начать.

См. этот ответ (и ссылки на него).

Я могу анализировать DWARF-информацию об исполняемом файле

Хотя DWARF содержит Информация, которую вы ищете, так же, как и таблица символов. И последний как минимум в 100 раз легче разобрать и использовать.

...