21 #include <sys/types.h>
40 #include <elfutils/libebl.h>
41 #include <elfutils/libdw.h>
42 #include <elfutils/libdwfl.h>
48 static GHashTable *binfile_tab = NULL;
60 static char *LIBFORMAT1 =
"([\\w\\d_\\.\\-]+[\\w\\d]).so.([\\d\\.]+)";
61 static char *LIBFORMAT2 =
"([\\w\\d_\\.\\-]+[\\w\\d]).so";
62 static regex_t LIBREGEX1;
63 static regex_t LIBREGEX2;
65 static int init_done = 0;
70 static int _filename_info(
char *filename,
71 char **realfilename,
char **name,
char **version);
76 static void binfile_fini(
void) {
84 while (g_hash_table_size(binfile_tab)) {
85 g_hash_table_iter_init(&iter,binfile_tab);
86 while (g_hash_table_iter_next(&iter,NULL,(gpointer)&binfile)) {
91 g_hash_table_destroy(binfile_tab);
96 memset(&LIBREGEX1,0,
sizeof(LIBREGEX1));
98 memset(&LIBREGEX2,0,
sizeof(LIBREGEX2));
107 atexit(binfile_fini);
109 if (regcomp(&LIBREGEX1,LIBFORMAT1,REG_EXTENDED)) {
110 verror(
"regcomp('%s'): %s\n",LIBFORMAT1,strerror(errno));
113 if (regcomp(&LIBREGEX2,LIBFORMAT2,REG_EXTENDED)) {
114 verror(
"regcomp('%s'): %s\n",LIBFORMAT2,strerror(errno));
118 binfile_tab = g_hash_table_new_full(g_str_hash,g_str_equal,
126 struct binfile *binfile;
129 binfile = (
struct binfile *)
calloc(1,
sizeof(*binfile));
132 binfile->
ops = bfops;
141 if (_filename_info(filename,&binfile->
filename,
146 else if (binfile->
filename == filename)
147 binfile->
filename = strdup(filename);
152 sre =
calloc(1,
sizeof(*sre));
164 struct binfile *retval = NULL;
166 if (_filename_info(filename,&realname,NULL,NULL)) {
173 retval = (
struct binfile *)g_hash_table_lookup(binfile_tab,realname);
174 if (realname != filename)
181 if (g_hash_table_lookup(binfile_tab,binfile->
filename)) {
182 vwarn(
"binfile %s already cached; not caching!\n",binfile->
filename);
185 g_hash_table_insert(binfile_tab,(gpointer)binfile->
filename,(gpointer)binfile);
190 if (g_hash_table_lookup(binfile_tab,binfile->
filename) != binfile)
192 g_hash_table_remove(binfile_tab,(gpointer)binfile->
filename);
199 struct binfile *binfile;
206 while (g_hash_table_size(binfile_tab)) {
207 g_hash_table_iter_init(&iter,binfile_tab);
208 while (g_hash_table_iter_next(&iter,NULL,(gpointer)&binfile)) {
209 if (binfile->refcnt <= 0) {
230 verror(
"could not build instance from %s!\n",filename);
235 verror(
"could not build instance from binfile %s!\n",bf->
filename);
249 RHOLD(retval,retval);
256 struct binfile *retval = NULL;
261 "using %s backend (from instance) for file %s\n",
263 return bfinst->
ops->
open(filename,root_prefix,bfinst);
269 ops = &binfile_types[0];
272 (*ops)->get_backend_name(),filename);
273 retval = (*ops)->open(filename,root_prefix,bfinst);
275 if (!retval->instance) {
288 struct binfile *retval;
292 RHOLD(retval,retval);
299 const char *DFPATH[]) {
308 const char *DFPATH[]) {
309 struct binfile *retval;
313 RHOLD(retval,retval);
323 return binfile->
type;
327 int *named,
int *duplicated,
int *anon,
342 if (binfile->
fd < 0 && !binfile->
image) {
347 retval = binfile->
ops->
close(binfile);
354 RPUT(binfile,binfile,binfile,refcnt);
364 verror(
"cannot free (%d refs) binfile(%s)\n",
369 vwarn(
"forced free (%d refs) binfile(%s)\n",
383 if (g_hash_table_lookup(binfile_tab,binfile->
filename) == binfile)
384 g_hash_table_remove(binfile_tab,binfile->
filename);
386 if (binfile->
fd > -1 || binfile->
image)
415 binfile->
name = NULL;
442 verror(
"cannot free (%d refs) binfile_instance(%s)\n",
447 vwarn(
"forced free (%d refs) binfile_instance(%s)\n",
465 static int _filename_info(
char *filename,
466 char **realfilename,
char **name,
char **version) {
467 regmatch_t matches[2];
472 realname = realpath(filename,NULL);
473 if (realname && strcmp(realname,filename) == 0) {
477 else if (!realname) {
478 verror(
"realpath(%s): %s\n",filename,strerror(errno));
482 if (stat(realname,&sbuf) < 0) {
483 verror(
"stat(%s): %s\n",realname,strerror(errno));
484 if (realname != filename)
490 *realfilename = realname;
492 if (!name && !version)
495 if (regexec(&LIBREGEX1,realname,2,matches,0) == 0) {
497 match_len = matches[0].rm_eo - matches[0].rm_so;
498 *name =
malloc(match_len + 1);
499 memcpy(*name,realname + matches[0].rm_so,match_len);
500 *name[match_len] =
'\0';
504 match_len = matches[1].rm_eo - matches[1].rm_so;
505 *version =
malloc(match_len + 1);
506 memcpy(*name,realname + matches[1].rm_so,match_len);
507 *version[match_len] =
'\0';
510 else if (regexec(&LIBREGEX2,realname,1,matches,0) == 0) {
512 match_len = matches[0].rm_eo - matches[0].rm_so;
513 *name =
malloc(match_len + 1);
514 memcpy(*name,realname + matches[0].rm_so,match_len);
515 *name[match_len] =
'\0';
520 vwarn(
"cannot extract version from %s!\n",realname);
REFCNT binfile_instance_release(struct binfile_instance *bfi)
struct scope * symbol_write_owned_scope(struct symbol *symbol)
struct binfile_instance * binfile_infer_instance(char *filename, char *root_prefix, ADDR base, GHashTable *config)
REFCNT binfile_free(struct binfile *binfile, int force)
struct symbol * symbol_create(symbol_type_t symtype, symbol_source_t source, char *name, int name_copy, SMOFFSET offset, load_type_t loadtype, struct scope *scope)
struct scope * symbol_read_owned_scope(struct symbol *symbol)
struct binfile * binfile_open_debuginfo(struct binfile *binfile, struct binfile_instance *bfinst, const char *DFPATH[])
unsigned int dynstrtablen
void(* free)(struct binfile *bfile)
struct binfile_instance * binfile_infer_instance__int(char *filename, char *root_prefix, ADDR base, GHashTable *config)
#define verror(format,...)
struct binfile * binfile_lookup(char *filename)
struct binfile * binfile_open(char *filename, char *root_prefix, struct binfile_instance *bfinst)
struct binfile * binfile_open_debuginfo__int(struct binfile *binfile, struct binfile_instance *bfinst, const char *DFPATH[])
#define vwarn(format,...)
REFCNT binfile_instance_free(struct binfile_instance *bfi, int force)
void clrange_free(clrange_t clf)
int(* close)(struct binfile *bfile)
const char *(* get_backend_name)(void)
struct binfile * binfile_open__int(char *filename, char *root_prefix, struct binfile_instance *bfinst)
binfile_type_t binfile_get_binfile_type(struct binfile *binfile)
int binfile_cache(struct binfile *binfile)
int binfile_uncache(struct binfile *binfile)
struct binfile_ops elf_binfile_ops
#define vdebug(devel, areas, flags, format,...)
struct binfile *(* open)(char *filename, char *root_prefix, struct binfile_instance *bfinst)
struct binfile * binfile_create(char *filename, struct binfile_ops *bfops, void *priv)
struct binfile *(* open_debuginfo)(struct binfile *binfile, struct binfile_instance *bfinst, const char *DFPATH[])
void * calloc(size_t nmemb, size_t size)
int binfile_cache_clean(void)
REFCNT binfile_release(struct binfile *binfile)
const char * binfile_get_backend_name(struct binfile *binfile)
int scope_get_sizes(struct scope *scope, int *named, int *duplicated, int *anon, int *numscopes)
struct binfile_instance *(* infer_instance)(struct binfile *binfile, ADDR base, GHashTable *config)
int symbol_set_root_priv(struct symbol *symbol, void *priv)
struct binfile_instance * instance
void(* free_instance)(struct binfile_instance *bfi)
int binfile_get_root_scope_sizes(struct binfile *binfile, int *named, int *duplicated, int *anon, int *numscopes)
int binfile_close(struct binfile *binfile)
#define RPUT(x, objtype, hx, rc)
void * malloc(size_t size)
struct binfile_ops * binfile_types[]
struct spf_config * config
clrange_t clrange_create(void)