5bc698ab1b
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
575 lines
16 KiB
C
575 lines
16 KiB
C
#ifndef _DWARVES_H_
|
|
#define _DWARVES_H_ 1
|
|
/*
|
|
Copyright (C) 2006 Mandriva Conectiva S.A.
|
|
Copyright (C) 2006 Arnaldo Carvalho de Melo <acme@mandriva.com>
|
|
|
|
This program is free software; you can redistribute it and/or modify it
|
|
under the terms of version 2 of the GNU General Public License as
|
|
published by the Free Software Foundation.
|
|
*/
|
|
|
|
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <dwarf.h>
|
|
#include <elfutils/libdw.h>
|
|
|
|
#include "list.h"
|
|
|
|
struct argp;
|
|
|
|
struct cus {
|
|
struct list_head cus;
|
|
struct list_head priv_definitions; /* struct type entries */
|
|
struct list_head priv_fwd_decls; /* struct class entries */
|
|
struct list_head *definitions;
|
|
struct list_head *fwd_decls;
|
|
};
|
|
|
|
struct cu {
|
|
struct list_head node;
|
|
struct list_head tags;
|
|
struct list_head tool_list; /* To be used by tools such as ctracer */
|
|
const char *name;
|
|
uint8_t addr_size;
|
|
uint16_t language;
|
|
unsigned long nr_inline_expansions;
|
|
size_t size_inline_expansions;
|
|
uint32_t nr_functions_changed;
|
|
uint32_t nr_structures_changed;
|
|
size_t max_len_changed_item;
|
|
size_t function_bytes_added;
|
|
size_t function_bytes_removed;
|
|
int build_id_len;
|
|
unsigned char build_id[0];
|
|
};
|
|
|
|
struct tag {
|
|
struct list_head node;
|
|
Dwarf_Off type;
|
|
Dwarf_Off id;
|
|
const char *decl_file;
|
|
uint16_t decl_line;
|
|
uint16_t tag;
|
|
uint16_t refcnt;
|
|
uint16_t recursivity_level;
|
|
};
|
|
|
|
static inline int tag__is_enumeration(const struct tag *self)
|
|
{
|
|
return self->tag == DW_TAG_enumeration_type;
|
|
}
|
|
|
|
static inline int tag__is_namespace(const struct tag *self)
|
|
{
|
|
return self->tag == DW_TAG_namespace;
|
|
}
|
|
|
|
static inline int tag__is_struct(const struct tag *self)
|
|
{
|
|
return self->tag == DW_TAG_structure_type;
|
|
}
|
|
|
|
static inline int tag__is_union(const struct tag *self)
|
|
{
|
|
return self->tag == DW_TAG_union_type;
|
|
}
|
|
|
|
struct namespace {
|
|
struct tag tag;
|
|
const char *name;
|
|
struct list_head tags;
|
|
uint16_t nr_tags;
|
|
};
|
|
|
|
static inline struct namespace *tag__namespace(const struct tag *self)
|
|
{
|
|
return (struct namespace *)self;
|
|
}
|
|
|
|
/**
|
|
* namespace__for_each_tag - iterate thru all the tags
|
|
* @self: struct namespace instance to iterate
|
|
* @pos: struct tag iterator
|
|
*/
|
|
#define namespace__for_each_tag(self, pos) \
|
|
list_for_each_entry(pos, &(self)->tags, node)
|
|
|
|
/**
|
|
* struct type - base type for enumerations, structs and unions
|
|
*
|
|
* @nr_members: number of DW_TAG_member entries
|
|
* @nr_tags: number of tags
|
|
*/
|
|
struct type {
|
|
struct namespace namespace;
|
|
struct list_head node;
|
|
Dwarf_Off specification;
|
|
size_t size;
|
|
uint16_t nr_members;
|
|
uint8_t declaration; /* only one bit used */
|
|
uint8_t definition_emitted:1;
|
|
uint8_t fwd_decl_emitted:1;
|
|
};
|
|
|
|
static inline struct class *type__class(const struct type *self)
|
|
{
|
|
return (struct class *)self;
|
|
}
|
|
|
|
/**
|
|
* type__for_each_tag - iterate thru all the tags
|
|
* @self: struct type instance to iterate
|
|
* @pos: struct tag iterator
|
|
*/
|
|
#define type__for_each_tag(self, pos) \
|
|
list_for_each_entry(pos, &(self)->namespace.tags, node)
|
|
|
|
/**
|
|
* type__for_each_enumerator - iterate thru the enumerator entries
|
|
* @self: struct type instance to iterate
|
|
* @pos: struct enumerator iterator
|
|
*/
|
|
#define type__for_each_enumerator(self, pos) \
|
|
list_for_each_entry(pos, &(self)->namespace.tags, tag.node)
|
|
|
|
/**
|
|
* type__for_each_member - iterate thru the entries that use space
|
|
* (data members and inheritance entries)
|
|
* @self: struct type instance to iterate
|
|
* @pos: struct class_member iterator
|
|
*/
|
|
#define type__for_each_member(self, pos) \
|
|
list_for_each_entry(pos, &(self)->namespace.tags, tag.node) \
|
|
if (!(pos->tag.tag == DW_TAG_member || \
|
|
pos->tag.tag == DW_TAG_inheritance)) \
|
|
continue; \
|
|
else
|
|
|
|
/**
|
|
* type__for_each_data_member - iterate thru the data member entries
|
|
* @self: struct type instance to iterate
|
|
* @pos: struct class_member iterator
|
|
*/
|
|
#define type__for_each_data_member(self, pos) \
|
|
list_for_each_entry(pos, &(self)->namespace.tags, tag.node) \
|
|
if (pos->tag.tag != DW_TAG_member) \
|
|
continue; \
|
|
else
|
|
|
|
/**
|
|
* type__for_each_member_safe - safely iterate thru the entries that use space
|
|
* (data members and inheritance entries)
|
|
* @self: struct type instance to iterate
|
|
* @pos: struct class_member iterator
|
|
* @n: struct class_member temp iterator
|
|
*/
|
|
#define type__for_each_member_safe(self, pos, n) \
|
|
list_for_each_entry_safe(pos, n, &(self)->namespace.tags, tag.node) \
|
|
if (pos->tag.tag != DW_TAG_member) \
|
|
continue; \
|
|
else
|
|
|
|
/**
|
|
* type__for_each_data_member_safe - safely iterate thru the data member entries
|
|
* @self: struct type instance to iterate
|
|
* @pos: struct class_member iterator
|
|
* @n: struct class_member temp iterator
|
|
*/
|
|
#define type__for_each_data_member_safe(self, pos, n) \
|
|
list_for_each_entry_safe(pos, n, &(self)->namespace.tags, tag.node) \
|
|
if (pos->tag.tag != DW_TAG_member) \
|
|
continue; \
|
|
else
|
|
|
|
static inline struct type *tag__type(const struct tag *self)
|
|
{
|
|
return (struct type *)self;
|
|
}
|
|
|
|
struct class {
|
|
struct type type;
|
|
struct list_head vtable;
|
|
uint16_t nr_vtable_entries;
|
|
uint8_t nr_holes;
|
|
uint8_t nr_bit_holes;
|
|
uint16_t padding;
|
|
uint8_t bit_padding;
|
|
void *priv;
|
|
};
|
|
|
|
static inline struct class *tag__class(const struct tag *self)
|
|
{
|
|
return (struct class *)self;
|
|
}
|
|
|
|
static inline struct tag *class__tag(const struct class *self)
|
|
{
|
|
return (struct tag *)self;
|
|
}
|
|
|
|
extern struct class *class__clone(const struct class *from,
|
|
const char *new_class_name);
|
|
extern void class__delete(struct class *self);
|
|
|
|
static inline struct list_head *class__tags(struct class *self)
|
|
{
|
|
return &self->type.namespace.tags;
|
|
}
|
|
|
|
extern const char *type__name(struct type *self, const struct cu *cu);
|
|
|
|
static inline const char *class__name(struct class *self,
|
|
const struct cu *cu)
|
|
{
|
|
return type__name(&self->type, cu);
|
|
}
|
|
|
|
static inline int class__is_struct(const struct class *self)
|
|
{
|
|
return tag__is_struct(&self->type.namespace.tag);
|
|
}
|
|
|
|
struct base_type {
|
|
struct tag tag;
|
|
const char *name;
|
|
size_t size;
|
|
};
|
|
|
|
static inline struct base_type *tag__base_type(const struct tag *self)
|
|
{
|
|
return (struct base_type *)self;
|
|
}
|
|
|
|
struct array_type {
|
|
struct tag tag;
|
|
uint32_t *nr_entries;
|
|
uint8_t dimensions;
|
|
};
|
|
|
|
static inline struct array_type *tag__array_type(const struct tag *self)
|
|
{
|
|
return (struct array_type *)self;
|
|
}
|
|
|
|
struct class_member {
|
|
struct tag tag;
|
|
char *name;
|
|
uint32_t offset;
|
|
uint8_t bit_offset;
|
|
uint8_t bit_size;
|
|
uint8_t bit_hole; /* If there is a bit hole before the next
|
|
one (or the end of the struct) */
|
|
uint8_t bitfield_end:1; /* Is this the last entry in a bitfield? */
|
|
uint8_t visited:1;
|
|
uint8_t accessibility:2; /* DW_ACCESS_{public,protected,private} */
|
|
uint8_t virtuality:2; /* DW_VIRTUALITY_{none,virtual,pure_virtual} */
|
|
uint16_t hole; /* If there is a hole before the next
|
|
one (or the end of the struct) */
|
|
};
|
|
|
|
static inline struct class_member *tag__class_member(const struct tag *self)
|
|
{
|
|
return (struct class_member *)self;
|
|
}
|
|
|
|
extern size_t class_member__size(const struct class_member *self,
|
|
const struct cu *cu);
|
|
extern void class_member__delete(struct class_member *self);
|
|
|
|
struct lexblock {
|
|
struct tag tag;
|
|
struct list_head tags;
|
|
Dwarf_Addr low_pc;
|
|
Dwarf_Addr high_pc;
|
|
uint16_t nr_inline_expansions;
|
|
uint16_t nr_labels;
|
|
uint16_t nr_variables;
|
|
uint16_t nr_lexblocks;
|
|
size_t size_inline_expansions;
|
|
};
|
|
|
|
static inline struct lexblock *tag__lexblock(const struct tag *self)
|
|
{
|
|
return (struct lexblock *)self;
|
|
}
|
|
|
|
/*
|
|
* tag.tag can be DW_TAG_subprogram_type or DW_TAG_subroutine_type.
|
|
*/
|
|
struct ftype {
|
|
struct tag tag;
|
|
struct list_head parms;
|
|
uint16_t nr_parms;
|
|
uint8_t unspec_parms; /* just one bit is needed */
|
|
};
|
|
|
|
static inline struct ftype *tag__ftype(const struct tag *self)
|
|
{
|
|
return (struct ftype *)self;
|
|
}
|
|
|
|
/**
|
|
* ftype__for_each_parameter - iterate thru all the parameters
|
|
* @self: struct ftype instance to iterate
|
|
* @pos: struct parameter iterator
|
|
*/
|
|
#define ftype__for_each_parameter(self, pos) \
|
|
list_for_each_entry(pos, &(self)->parms, tag.node)
|
|
|
|
struct function {
|
|
struct ftype proto;
|
|
struct lexblock lexblock;
|
|
const char *name;
|
|
char *linkage_name;
|
|
Dwarf_Off abstract_origin;
|
|
Dwarf_Off specification;
|
|
size_t cu_total_size_inline_expansions;
|
|
uint16_t cu_total_nr_inline_expansions;
|
|
uint8_t inlined:2;
|
|
uint8_t external:1;
|
|
uint8_t accessibility:2; /* DW_ACCESS_{public,protected,private} */
|
|
uint8_t virtuality:2; /* DW_VIRTUALITY_{none,virtual,pure_virtual} */
|
|
int16_t vtable_entry;
|
|
struct list_head vtable_node;
|
|
/* fields used by tools */
|
|
struct list_head tool_node;
|
|
void *priv;
|
|
};
|
|
|
|
static inline struct function *tag__function(const struct tag *self)
|
|
{
|
|
return (struct function *)self;
|
|
}
|
|
|
|
/**
|
|
* function__for_each_parameter - iterate thru all the parameters
|
|
* @self: struct function instance to iterate
|
|
* @pos: struct parameter iterator
|
|
*/
|
|
#define function__for_each_parameter(self, pos) \
|
|
ftype__for_each_parameter(&self->proto, pos)
|
|
|
|
struct parameter {
|
|
struct tag tag;
|
|
char *name;
|
|
Dwarf_Off abstract_origin;
|
|
};
|
|
|
|
static inline struct parameter *tag__parameter(const struct tag *self)
|
|
{
|
|
return (struct parameter *)self;
|
|
}
|
|
|
|
extern Dwarf_Off parameter__type(struct parameter *self, const struct cu *cu);
|
|
extern const char *parameter__name(struct parameter *self, const struct cu *cu);
|
|
|
|
enum vlocation {
|
|
LOCATION_UNKNOWN,
|
|
LOCATION_LOCAL,
|
|
LOCATION_GLOBAL,
|
|
LOCATION_REGISTER,
|
|
LOCATION_OPTIMIZED
|
|
};
|
|
|
|
struct variable {
|
|
struct tag tag;
|
|
char *name;
|
|
Dwarf_Off abstract_origin;
|
|
uint8_t external:1;
|
|
uint8_t declaration:1;
|
|
enum vlocation location;
|
|
};
|
|
|
|
static inline struct variable *tag__variable(const struct tag *self)
|
|
{
|
|
return (struct variable *)self;
|
|
}
|
|
|
|
struct inline_expansion {
|
|
struct tag tag;
|
|
size_t size;
|
|
Dwarf_Addr low_pc;
|
|
Dwarf_Addr high_pc;
|
|
};
|
|
|
|
static inline struct inline_expansion *
|
|
tag__inline_expansion(const struct tag *self)
|
|
{
|
|
return (struct inline_expansion *)self;
|
|
}
|
|
|
|
struct label {
|
|
struct tag tag;
|
|
char *name;
|
|
Dwarf_Addr low_pc;
|
|
};
|
|
|
|
struct enumerator {
|
|
struct tag tag;
|
|
const char *name;
|
|
uint32_t value;
|
|
};
|
|
|
|
struct conf_fprintf {
|
|
const char *prefix;
|
|
const char *suffix;
|
|
int32_t type_spacing;
|
|
int32_t name_spacing;
|
|
uint32_t base_offset;
|
|
uint8_t indent;
|
|
uint8_t expand_types:1;
|
|
uint8_t expand_pointers:1;
|
|
uint8_t rel_offset:1;
|
|
uint8_t emit_stats:1;
|
|
uint8_t suppress_comments:1;
|
|
uint8_t suppress_offset_comment:1;
|
|
uint8_t show_decl_info:1;
|
|
uint8_t show_only_data_members:1;
|
|
uint8_t no_semicolon:1;
|
|
};
|
|
|
|
extern void dwarves__init(size_t user_cacheline_size);
|
|
|
|
extern void class__find_holes(struct class *self, const struct cu *cu);
|
|
extern int class__has_hole_ge(const struct class *self, const uint16_t size);
|
|
extern size_t class__fprintf(struct class *self, const struct cu *cu,
|
|
const struct conf_fprintf *conf, FILE *fp);
|
|
extern size_t enumeration__fprintf(const struct tag *tag_self,
|
|
const struct cu *cu,
|
|
const struct conf_fprintf *conf, FILE *fp);
|
|
extern size_t typedef__fprintf(const struct tag *tag_self, const struct cu *cu,
|
|
const struct conf_fprintf *conf, FILE *fp);
|
|
extern size_t tag__fprintf_decl_info(const struct tag *self, FILE *fp);
|
|
extern size_t tag__fprintf(struct tag *self, const struct cu *cu,
|
|
const struct conf_fprintf *conf, FILE *fp);
|
|
|
|
extern const char *function__name(struct function *self, const struct cu *cu);
|
|
extern size_t function__fprintf_stats(const struct tag *tag_self,
|
|
const struct cu *cu,
|
|
FILE *fp);
|
|
|
|
extern size_t lexblock__fprintf(const struct lexblock *self,
|
|
const struct cu *cu, struct function *function,
|
|
uint16_t indent, FILE *fp);
|
|
|
|
extern struct cus *cus__new(struct list_head *definitions,
|
|
struct list_head *fwd_decls);
|
|
extern int cus__loadfl(struct cus *self, struct argp *argp,
|
|
int argc, char *argv[]);
|
|
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);
|
|
extern void cus__print_error_msg(const char *progname, const char *filename,
|
|
const int err);
|
|
extern struct cu *cus__find_cu_by_name(const struct cus *self,
|
|
const char *name);
|
|
extern struct tag *cu__find_base_type_by_name(const struct cu *self,
|
|
const char *name);
|
|
extern struct tag *cus__find_struct_by_name(const struct cus *self,
|
|
struct cu **cu,
|
|
const char *name,
|
|
const int include_decls);
|
|
extern struct tag *cus__find_function_by_name(const struct cus *self,
|
|
struct cu **cu,
|
|
const char *name);
|
|
extern struct tag *cus__find_tag_by_id(const struct cus *self,
|
|
struct cu **cu, const Dwarf_Off id);
|
|
|
|
extern struct tag *cu__find_tag_by_id(const struct cu *self,
|
|
const Dwarf_Off id);
|
|
extern struct tag *cu__find_first_typedef_of_type(const struct cu *self,
|
|
const Dwarf_Off type);
|
|
extern struct tag *cu__find_struct_by_name(const struct cu *cu,
|
|
const char *name,
|
|
const int include_decls);
|
|
extern void cu__account_inline_expansions(struct cu *self);
|
|
extern int cu__for_each_tag(struct cu *self,
|
|
int (*iterator)(struct tag *tag,
|
|
struct cu *cu,
|
|
void *cookie),
|
|
void *cookie,
|
|
struct tag *(*filter)(struct tag *tag,
|
|
struct cu *cu,
|
|
void *cookie));
|
|
extern void cus__for_each_cu(struct cus *self,
|
|
int (*iterator)(struct cu *cu,
|
|
void *cookie),
|
|
void *cookie,
|
|
struct cu *(*filter)(struct cu *cu));
|
|
|
|
extern const struct class_member *
|
|
class__find_bit_hole(const struct class *self,
|
|
const struct class_member *trailer,
|
|
const size_t bit_hole_size);
|
|
|
|
extern struct tag *cu__find_function_by_name(const struct cu *cu,
|
|
const char *name);
|
|
|
|
static inline size_t function__size(const struct function *self)
|
|
{
|
|
return self->lexblock.high_pc - self->lexblock.low_pc;
|
|
}
|
|
|
|
static inline int function__declared_inline(const struct function *self)
|
|
{
|
|
return (self->inlined == DW_INL_declared_inlined ||
|
|
self->inlined == DW_INL_declared_not_inlined);
|
|
}
|
|
|
|
static inline int function__inlined(const struct function *self)
|
|
{
|
|
return (self->inlined == DW_INL_inlined ||
|
|
self->inlined == DW_INL_declared_inlined);
|
|
}
|
|
|
|
extern size_t ftype__fprintf(const struct ftype *self, const struct cu *cu,
|
|
const char *name, const int inlined,
|
|
const int is_pointer, const int type_spacing,
|
|
FILE *fp);
|
|
extern int ftype__has_parm_of_type(const struct ftype *self,
|
|
const struct tag *target,
|
|
const struct cu *cu);
|
|
|
|
extern const char *tag__name(const struct tag *self, const struct cu *cu,
|
|
char *bf, size_t len);
|
|
extern size_t tag__size(const struct tag *self, const struct cu *cu);
|
|
extern size_t tag__nr_cachelines(const struct tag *self, const struct cu *cu);
|
|
|
|
extern struct class_member *type__find_member_by_name(const struct type *self,
|
|
const char *name);
|
|
extern uint32_t type__nr_members_of_type(const struct type *self,
|
|
const Dwarf_Off type);
|
|
extern struct class_member *type__last_member(struct type *self);
|
|
|
|
static inline struct class_member *
|
|
class__find_member_by_name(const struct class *self, const char *name)
|
|
{
|
|
return type__find_member_by_name(&self->type, name);
|
|
}
|
|
|
|
static inline uint16_t class__nr_members(const struct class *self)
|
|
{
|
|
return self->type.nr_members;
|
|
}
|
|
|
|
static inline size_t class__size(const struct class *self)
|
|
{
|
|
return self->type.size;
|
|
}
|
|
|
|
static inline int class__is_declaration(const struct class *self)
|
|
{
|
|
return self->type.declaration;
|
|
}
|
|
|
|
extern const char *variable__name(const struct variable *self,
|
|
const struct cu *cu);
|
|
extern const char *variable__type_name(const struct variable *self,
|
|
const struct cu *cu,
|
|
char *bf, size_t len);
|
|
|
|
extern const char *dwarf_tag_name(const uint32_t tag);
|
|
#endif /* _DWARVES_H_ */
|