dwarf: separate dwarf_tag from tag
So that, when not needing the DWARF info, the apps can tell that at load time, and then the dwarf loader can just free all the dwarf_tags allocated, reducing memory usage. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
822f8b675e
commit
250dded466
4
codiff.c
4
codiff.c
|
@ -797,7 +797,7 @@ failure:
|
|||
/* If old_file is a character device, leave its cus empty */
|
||||
if (!S_ISCHR(st.st_mode)) {
|
||||
filenames[0] = old_filename;
|
||||
err = cus__loadfl(old_cus, filenames);
|
||||
err = cus__loadfl(old_cus, NULL, filenames);
|
||||
if (err != 0) {
|
||||
cus__print_error_msg("codiff", old_cus, old_filename, err);
|
||||
return EXIT_FAILURE;
|
||||
|
@ -812,7 +812,7 @@ failure:
|
|||
/* If old_file is a character device, leave its cus empty */
|
||||
if (!S_ISCHR(st.st_mode)) {
|
||||
filenames[0] = new_filename;
|
||||
err = cus__loadfl(new_cus, filenames);
|
||||
err = cus__loadfl(new_cus, NULL, filenames);
|
||||
if (err != 0) {
|
||||
cus__print_error_msg("codiff", new_cus, new_filename, err);
|
||||
return EXIT_FAILURE;
|
||||
|
|
|
@ -879,7 +879,8 @@ static int cus__fixup_ctf_bitfields(struct cus *self)
|
|||
return err;
|
||||
}
|
||||
|
||||
int ctf__load(struct cus *self, char *filenames[])
|
||||
int ctf__load(struct cus *self, struct conf_load *conf __unused,
|
||||
char *filenames[])
|
||||
{
|
||||
struct ctf_state state;
|
||||
int wordsize;
|
||||
|
|
|
@ -9,7 +9,8 @@
|
|||
*/
|
||||
|
||||
struct cus;
|
||||
struct conf_load;
|
||||
|
||||
int ctf__load(struct cus *self, char *filenames[]);
|
||||
int ctf__load(struct cus *self, struct conf_load *conf, char *filenames[]);
|
||||
|
||||
#endif /* _CTF_LOADER_H_ */
|
||||
|
|
|
@ -49,7 +49,7 @@ int main(int argc __unused, char *argv[])
|
|||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
err = cus__loadfl(cus, argv + 1);
|
||||
err = cus__loadfl(cus, NULL, argv + 1);
|
||||
if (err != 0)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
|
|
|
@ -247,18 +247,24 @@ static int attr_location(Dwarf_Die *die, Dwarf_Op **expr, size_t *exprlen)
|
|||
|
||||
static void *tag__alloc(size_t size)
|
||||
{
|
||||
struct dwarf_tag *dtag;
|
||||
struct tag *self = malloc(size + sizeof(*dtag));
|
||||
struct dwarf_tag *dtag = malloc(sizeof(*dtag));
|
||||
|
||||
if (self != NULL) {
|
||||
dtag = ((void *)self) + size;
|
||||
dtag->tag = self;
|
||||
self->priv = dtag;
|
||||
dtag->type = 0;
|
||||
self->type = 0;
|
||||
self->top_level = 0;
|
||||
if (dtag == NULL)
|
||||
return NULL;
|
||||
|
||||
struct tag *self = malloc(size);
|
||||
|
||||
if (self == NULL) {
|
||||
free(dtag);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dtag->tag = self;
|
||||
self->priv = dtag;
|
||||
dtag->type = 0;
|
||||
self->type = 0;
|
||||
self->top_level = 0;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
@ -1496,31 +1502,32 @@ static void cu__recode_dwarf_types(struct cu *self)
|
|||
}
|
||||
|
||||
static const char *dwarf_tag__decl_file(const struct tag *self,
|
||||
const struct cu *cu __unused)
|
||||
const struct cu *cu)
|
||||
{
|
||||
struct dwarf_tag *dtag = self->priv;
|
||||
return dtag ? strings__ptr(strings, dtag->decl_file) : NULL;
|
||||
return cu->extra_dbg_info ?
|
||||
strings__ptr(strings, dtag->decl_file) : NULL;
|
||||
}
|
||||
|
||||
static uint32_t dwarf_tag__decl_line(const struct tag *self,
|
||||
const struct cu *cu __unused)
|
||||
const struct cu *cu)
|
||||
{
|
||||
struct dwarf_tag *dtag = self->priv;
|
||||
return dtag ? dtag->decl_line : 0;
|
||||
return cu->extra_dbg_info ? dtag->decl_line : 0;
|
||||
}
|
||||
|
||||
static unsigned long long dwarf_tag__orig_id(const struct tag *self,
|
||||
const struct cu *cu __unused)
|
||||
const struct cu *cu)
|
||||
{
|
||||
struct dwarf_tag *dtag = self->priv;
|
||||
return dtag ? dtag->id : 0;
|
||||
return cu->extra_dbg_info ? dtag->id : 0;
|
||||
}
|
||||
|
||||
static unsigned long long dwarf_tag__orig_type(const struct tag *self,
|
||||
const struct cu *cu __unused)
|
||||
const struct cu *cu)
|
||||
{
|
||||
struct dwarf_tag *dtag = self->priv;
|
||||
return dtag ? dtag->type : 0;
|
||||
return cu->extra_dbg_info ? dtag->type : 0;
|
||||
}
|
||||
|
||||
static struct cu_orig_info dwarf_orig_info_ops = {
|
||||
|
@ -1530,6 +1537,14 @@ static struct cu_orig_info dwarf_orig_info_ops = {
|
|||
.tag__orig_type = dwarf_tag__orig_type,
|
||||
};
|
||||
|
||||
static int tag__delete_priv(struct tag *self, struct cu *cu __unused,
|
||||
void *cookie __unused)
|
||||
{
|
||||
free(self->priv);
|
||||
self->priv = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void die__process(Dwarf_Die *die, struct cu *cu)
|
||||
{
|
||||
Dwarf_Die child;
|
||||
|
@ -1560,7 +1575,8 @@ static void die__process(Dwarf_Die *die, struct cu *cu)
|
|||
cu__recode_dwarf_types(cu);
|
||||
}
|
||||
|
||||
static void cus__load_module(struct cus *self, Dwfl_Module *mod, Dwarf *dw)
|
||||
static void cus__load_module(struct cus *self, struct conf_load *conf,
|
||||
Dwfl_Module *mod, Dwarf *dw)
|
||||
{
|
||||
Dwarf_Off off = 0, noff;
|
||||
size_t cuhl;
|
||||
|
@ -1584,19 +1600,28 @@ static void cus__load_module(struct cus *self, Dwfl_Module *mod, Dwarf *dw)
|
|||
build_id, build_id_len);
|
||||
if (cu == NULL)
|
||||
oom("cu__new");
|
||||
cu->extra_dbg_info = conf ? conf->extra_dbg_info : 0;
|
||||
die__process(cu_die, cu);
|
||||
cus__add(self, cu);
|
||||
if (!cu->extra_dbg_info)
|
||||
cu__for_all_tags(cu, tag__delete_priv, NULL);
|
||||
off = noff;
|
||||
}
|
||||
}
|
||||
|
||||
struct process_dwflmod_parms {
|
||||
struct cus *cus;
|
||||
struct conf_load *conf;
|
||||
};
|
||||
|
||||
static int cus__process_dwflmod(Dwfl_Module *dwflmod,
|
||||
void **userdata __unused,
|
||||
const char *name __unused,
|
||||
Dwarf_Addr base __unused,
|
||||
void *arg)
|
||||
{
|
||||
struct cus *self = arg;
|
||||
struct process_dwflmod_parms *parms = arg;
|
||||
struct cus *self = parms->cus;
|
||||
/*
|
||||
* WARNING: Don't remove the seemingly useless call to
|
||||
* dwfl_module_getelf, as it will change dwflmod internal state in a
|
||||
|
@ -1609,7 +1634,7 @@ static int cus__process_dwflmod(Dwfl_Module *dwflmod,
|
|||
Dwarf *dw = dwfl_module_getdwarf(dwflmod, &dwbias);
|
||||
|
||||
if (dw != NULL)
|
||||
cus__load_module(self, dwflmod, dw);
|
||||
cus__load_module(self, parms->conf, dwflmod, dw);
|
||||
/*
|
||||
* XXX We will fall back to try finding other debugging
|
||||
* formats (CTF), so no point in telling this to the user
|
||||
|
@ -1623,7 +1648,8 @@ static int cus__process_dwflmod(Dwfl_Module *dwflmod,
|
|||
return DWARF_CB_OK;
|
||||
}
|
||||
|
||||
static int cus__process_file(struct cus *self, int fd, const char *filename)
|
||||
static int cus__process_file(struct cus *self, struct conf_load *conf, int fd,
|
||||
const char *filename)
|
||||
{
|
||||
/* Duplicate an fd for dwfl_report_offline to swallow. */
|
||||
int dwfl_fd = dup(fd);
|
||||
|
@ -1651,8 +1677,13 @@ static int cus__process_file(struct cus *self, int fd, const char *filename)
|
|||
|
||||
dwfl_report_end(dwfl, NULL, NULL);
|
||||
|
||||
struct process_dwflmod_parms parms = {
|
||||
.cus = self,
|
||||
.conf = conf,
|
||||
};
|
||||
|
||||
/* Process the one or more modules gleaned from this file. */
|
||||
dwfl_getmodules(dwfl, cus__process_dwflmod, self, 0);
|
||||
dwfl_getmodules(dwfl, cus__process_dwflmod, &parms, 0);
|
||||
dwfl_end(dwfl);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1701,7 +1732,7 @@ out:
|
|||
return err;
|
||||
}
|
||||
|
||||
int dwarf__load(struct cus *self, char *filenames[], bool parsed __unused)
|
||||
int dwarf__load(struct cus *self, struct conf_load *conf, char *filenames[])
|
||||
{
|
||||
int err = 0, i = 0;
|
||||
|
||||
|
@ -1716,7 +1747,7 @@ int dwarf__load(struct cus *self, char *filenames[], bool parsed __unused)
|
|||
++i;
|
||||
continue;
|
||||
}
|
||||
cus__process_file(self, fd, filenames[i]);
|
||||
cus__process_file(self, conf, fd, filenames[i]);
|
||||
close(fd);
|
||||
++i;
|
||||
}
|
||||
|
|
|
@ -9,8 +9,9 @@
|
|||
*/
|
||||
|
||||
struct cus;
|
||||
struct conf_load;
|
||||
|
||||
int dwarf__load_filename(struct cus *self, const char *filename);
|
||||
int dwarf__load(struct cus *self, char *filenames[]);
|
||||
int dwarf__load(struct cus *self, struct conf_load *conf, char *filenames[]);
|
||||
|
||||
#endif /* _DWARF_LOADER_H_ */
|
||||
|
|
10
dwarves.c
10
dwarves.c
|
@ -517,8 +517,7 @@ int cu__add_tag(struct cu *self, struct tag *tag, long *id)
|
|||
}
|
||||
|
||||
struct cu *cu__new(const char *name, uint8_t addr_size,
|
||||
const unsigned char *build_id,
|
||||
int build_id_len)
|
||||
const unsigned char *build_id, int build_id_len)
|
||||
{
|
||||
struct cu *self = malloc(sizeof(*self) + build_id_len);
|
||||
|
||||
|
@ -541,6 +540,7 @@ struct cu *cu__new(const char *name, uint8_t addr_size,
|
|||
INIT_LIST_HEAD(&self->tool_list);
|
||||
|
||||
self->addr_size = addr_size;
|
||||
self->extra_dbg_info = 0;
|
||||
|
||||
self->nr_inline_expansions = 0;
|
||||
self->size_inline_expansions = 0;
|
||||
|
@ -2588,9 +2588,9 @@ int cus__load(struct cus *self, const char *filename)
|
|||
return err;
|
||||
}
|
||||
|
||||
int cus__loadfl(struct cus *self, char *filenames[])
|
||||
int cus__loadfl(struct cus *self, struct conf_load *conf, char *filenames[])
|
||||
{
|
||||
int err = dwarf__load(self, filenames);
|
||||
int err = dwarf__load(self, conf, filenames);
|
||||
/*
|
||||
* If dwarf__load fails, try ctf__load. Eventually we should just
|
||||
* register all the shared objects at some directory and ask them
|
||||
|
@ -2601,7 +2601,7 @@ int cus__loadfl(struct cus *self, char *filenames[])
|
|||
* by looking at the list of CUs found:
|
||||
*/
|
||||
if (list_empty(&self->cus))
|
||||
err = ctf__load(self, filenames);
|
||||
err = ctf__load(self, conf, filenames);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
12
dwarves.h
12
dwarves.h
|
@ -21,6 +21,14 @@
|
|||
|
||||
extern struct strings *strings;
|
||||
|
||||
/** struct conf_load - load configuration
|
||||
* @extra_dbg_info - keep original debugging format extra info
|
||||
* (e.g. DWARF's decl_{line,file}, id, etc)
|
||||
*/
|
||||
struct conf_load {
|
||||
bool extra_dbg_info;
|
||||
};
|
||||
|
||||
struct cus {
|
||||
struct list_head cus;
|
||||
};
|
||||
|
@ -104,6 +112,7 @@ struct cu {
|
|||
void *priv;
|
||||
struct cu_orig_info *orig_info;
|
||||
uint8_t addr_size;
|
||||
uint8_t extra_dbg_info:1;
|
||||
uint16_t language;
|
||||
unsigned long nr_inline_expansions;
|
||||
size_t size_inline_expansions;
|
||||
|
@ -665,7 +674,8 @@ extern size_t lexblock__fprintf(const struct lexblock *self,
|
|||
const struct cu *cu, struct function *function,
|
||||
uint16_t indent, FILE *fp);
|
||||
|
||||
extern int cus__loadfl(struct cus *self, char *filenames[]);
|
||||
extern int cus__loadfl(struct cus *self, struct conf_load *conf,
|
||||
char *filenames[]);
|
||||
extern int cus__load(struct cus *self, const char *filename);
|
||||
extern int cus__load_dir(struct cus *self, const char *dirname,
|
||||
const char *filename_mask, const int recursive);
|
||||
|
|
15
pahole.c
15
pahole.c
|
@ -57,6 +57,8 @@ static struct conf_fprintf conf = {
|
|||
.emit_stats = 1,
|
||||
};
|
||||
|
||||
static struct conf_load conf_load;
|
||||
|
||||
struct structure {
|
||||
struct list_head node;
|
||||
struct class *class;
|
||||
|
@ -988,13 +990,14 @@ static error_t pahole__options_parser(int key, char *arg,
|
|||
case 'c': cacheline_size = atoi(arg); break;
|
||||
case 'D': decl_exclude_prefix = arg;
|
||||
decl_exclude_prefix_len = strlen(decl_exclude_prefix);
|
||||
break;
|
||||
conf_load.extra_dbg_info = 1; break;
|
||||
case 'd': recursive = 1; break;
|
||||
case 'E': conf.expand_types = 1; break;
|
||||
case 'f': find_pointers_in_structs = 1;
|
||||
class_name = arg; break;
|
||||
case 'H': nr_holes = atoi(arg); break;
|
||||
case 'I': conf.show_decl_info = 1; break;
|
||||
case 'I': conf.show_decl_info = 1;
|
||||
conf_load.extra_dbg_info = 1; break;
|
||||
case 'i': find_containers = 1;
|
||||
class_name = arg; break;
|
||||
case 'l': conf.show_first_biggest_size_base_type_member = 1; break;
|
||||
|
@ -1002,8 +1005,10 @@ static error_t pahole__options_parser(int key, char *arg,
|
|||
case 'm': formatter = nr_methods_formatter; break;
|
||||
case 'N': formatter = class_name_len_formatter; break;
|
||||
case 'n': formatter = nr_members_formatter; break;
|
||||
case 'O': class_dwarf_offset = strtoul(arg, NULL, 0); break;
|
||||
case 'P': show_packable = 1; break;
|
||||
case 'O': class_dwarf_offset = strtoul(arg, NULL, 0);
|
||||
conf_load.extra_dbg_info = 1; break;
|
||||
case 'P': show_packable = 1;
|
||||
conf_load.extra_dbg_info = 1; break;
|
||||
case 'p': conf.expand_pointers = 1; break;
|
||||
case 'q': conf.emit_stats = 0;
|
||||
conf.suppress_comments = 1;
|
||||
|
@ -1061,7 +1066,7 @@ int main(int argc, char *argv[])
|
|||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
err = cus__loadfl(cus, argv + remaining);
|
||||
err = cus__loadfl(cus, &conf_load, argv + remaining);
|
||||
if (err != 0) {
|
||||
fputs("pahole: No debugging information found\n", stderr);
|
||||
return EXIT_FAILURE;
|
||||
|
|
|
@ -112,7 +112,7 @@ int main(int argc, char *argv[])
|
|||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
err = cus__loadfl(cus, argv + remaining);
|
||||
err = cus__loadfl(cus, NULL, argv + remaining);
|
||||
if (err != 0)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
|
|
13
pfunct.c
13
pfunct.c
|
@ -29,6 +29,8 @@ static struct type_emissions emissions;
|
|||
|
||||
static struct conf_fprintf conf;
|
||||
|
||||
static struct conf_load conf_load;
|
||||
|
||||
struct fn_stats {
|
||||
struct list_head node;
|
||||
struct tag *tag;
|
||||
|
@ -476,13 +478,16 @@ static error_t pfunct__options_parser(int key, char *arg,
|
|||
case 'g': formatter = fn_stats_labels_fmtr; break;
|
||||
case 'G': show_cc_uninlined = 1; break;
|
||||
case 'H': show_cc_inlined = 1; break;
|
||||
case 'i': show_inline_expansions = verbose = 1; break;
|
||||
case 'i': show_inline_expansions = verbose = 1;
|
||||
conf_load.extra_dbg_info = 1; break;
|
||||
case 'I': formatter = fn_stats_inline_exps_fmtr; break;
|
||||
case 'l': conf.show_decl_info = 1; break;
|
||||
case 'l': conf.show_decl_info = 1;
|
||||
conf_load.extra_dbg_info = 1; break;
|
||||
case 't': show_total_inline_expansion_stats = 1; break;
|
||||
case 'T': show_variables = 1; break;
|
||||
case 'N': formatter = fn_stats_name_len_fmtr; break;
|
||||
case 'V': verbose = 1; break;
|
||||
case 'V': verbose = 1;
|
||||
conf_load.extra_dbg_info = 1; break;
|
||||
default: return ARGP_ERR_UNKNOWN;
|
||||
}
|
||||
|
||||
|
@ -513,7 +518,7 @@ int main(int argc, char *argv[])
|
|||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
err = cus__loadfl(cus, argv + remaining);
|
||||
err = cus__loadfl(cus, &conf_load, argv + remaining);
|
||||
if (err != 0)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
|
|
|
@ -330,7 +330,7 @@ int main(int argc, char *argv[])
|
|||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
err = cus__loadfl(cus, argv + remaining);
|
||||
err = cus__loadfl(cus, NULL, argv + remaining);
|
||||
if (err != 0)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
|
|
|
@ -155,7 +155,7 @@ int main(int argc __unused, char *argv[])
|
|||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
err = cus__loadfl(cus, argv + 1);
|
||||
err = cus__loadfl(cus, NULL, argv + 1);
|
||||
if (err != 0)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
|
|
Loading…
Reference in New Issue