Sì, esaminando il proprio eseguibile (/proc/self/exe
) utilizzando ad es. libbfd
o una libreria di analisi dei file ELF, per analizzare i simboli stessi. In sostanza, devi scrivere codice C che fa l'equivalente di qualcosa come
env LANG=C LC_ALL=C readelf -s executable | awk '($5 == "LOCAL" && $8 ~ /^[^_]/ && $8 !~ /\./)'
Per quanto ne so, l'interfaccia linker dinamico in Linux (<dlfcn.h>
) non restituisce gli indirizzi per la statica simboli (locali).
Un approccio semplice e piuttosto robusto è quello di eseguire readelf
o objdump
dal programma. Si noti che non è possibile assegnare il percorso dello pseudo file a /proc/self/exe
, poiché si riferisce sempre al proprio eseguibile del processo. Invece, devi usare ad es. realpath("/proc/self/exe", NULL)
per ottenere un percorso assoluto assegnato dinamicamente all'eseguibile corrente che è possibile fornire al comando. Inoltre, si desidera garantire che l'ambiente contenga LANG=C
e LC_ALL=C
, in modo che l'output del comando sia facilmente analizzabile (e non localizzato in qualsiasi lingua l'utente corrente preferisca). Questo potrebbe sembrare un po 'complicato, ma richiede solo il pacchetto binutils
da installare, e non è necessario aggiornare il programma o la libreria per stare al passo con gli ultimi sviluppi, quindi penso che sia nel complesso un buon approccio .
Vuoi un esempio?
Un modo per semplificare è generare array separati con le informazioni sui simboli in fase di compilazione. In sostanza, dopo che i file oggetto vengono generati, un file di origine separato viene generato dinamicamente eseguendo objdump
o readelf
sui file oggetto correlato, generando una serie di nomi e puntatori simili a
const struct {
const char *const name;
const void *const addr;
} local_symbol_names[] = {
/* Filled in using objdump or readelf and awk, for example */
{ NULL, NULL }
};
magari con una semplice funzione di ricerca esportata in un file di intestazione, in modo che quando l'eseguibile finale è collegato, può accedere facilmente ed efficientemente alla matrice di simboli locali.
Duplica alcuni dati, poiché le stesse informazioni sono già nel file eseguibile e, se non ricordo male, devi prima collegare l'eseguibile finale con una matrice stub per ottenere gli indirizzi effettivi per i simboli, e poi ricollegarsi con l'array di simboli, rendendolo un po 'complicato in fase di compilazione .. Ma evita di avere una dipendenza da run-time su binutils
.