[LIB]: Move the __emit functions to a separate library, libdwarves_emit
To isolate functionality only used in utilities such as ctracer. Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
This commit is contained in:
parent
93183ec9ee
commit
05351ece16
@ -32,13 +32,18 @@ add_library(dwarves SHARED ${dwarves_LIB_SRCS})
|
||||
set_target_properties(dwarves PROPERTIES VERSION 1.0.0 SOVERSION 1)
|
||||
target_link_libraries(dwarves ${DWARF_LIBRARIES})
|
||||
|
||||
set(dwarves_emit_LIB_SRCS dwarves_emit.c)
|
||||
add_library(dwarves_emit SHARED ${dwarves_emit_LIB_SRCS})
|
||||
set_target_properties(dwarves_emit PROPERTIES VERSION 1.0.0 SOVERSION 1)
|
||||
target_link_libraries(dwarves_emit ${DWARF_LIBRARIES} dwarves)
|
||||
|
||||
set(codiff_SRCS codiff.c)
|
||||
add_executable(codiff ${codiff_SRCS})
|
||||
target_link_libraries(codiff dwarves)
|
||||
|
||||
set(ctracer_SRCS ctracer.c)
|
||||
add_executable(ctracer ${ctracer_SRCS})
|
||||
target_link_libraries(ctracer dwarves)
|
||||
target_link_libraries(ctracer dwarves dwarves_emit)
|
||||
|
||||
set(dtagnames_SRCS dtagnames.c)
|
||||
add_executable(dtagnames ${dtagnames_SRCS})
|
||||
@ -68,7 +73,8 @@ install(TARGETS codiff ctracer dtagnames pahole pdwtags
|
||||
pfunct pglobal prefcnt RUNTIME DESTINATION
|
||||
${CMAKE_INSTALL_PREFIX}/bin)
|
||||
install(TARGETS dwarves LIBRARY DESTINATION ${LIB_INSTALL_DIR})
|
||||
install(FILES dwarves.h DESTINATION ${CMAKE_INSTALL_PREFIX}/include)
|
||||
install(TARGETS dwarves dwarves_emit LIBRARY DESTINATION ${LIB_INSTALL_DIR})
|
||||
install(FILES dwarves.h dwarves_emit.h DESTINATION ${CMAKE_INSTALL_PREFIX}/include)
|
||||
install(FILES ostra/ostra-cg DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
|
||||
install(FILES ostra/python/ostra.py DESTINATION ${LIB_INSTALL_DIR}/ctracer/python)
|
||||
install(FILES lib/Makefile lib/ctracer_jprobe.c
|
||||
|
2
MANIFEST
2
MANIFEST
@ -1,5 +1,7 @@
|
||||
dwarves.c
|
||||
dwarves.h
|
||||
dwarves_emit.c
|
||||
dwarves_emit.h
|
||||
cmake/modules/FindDWARF.cmake
|
||||
CMakeLists.txt
|
||||
codiff.c
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "dwarves_emit.h"
|
||||
#include "dwarves.h"
|
||||
|
||||
/*
|
||||
|
307
dwarves.c
307
dwarves.c
@ -311,7 +311,7 @@ static void __tag__type_not_found(const struct tag *self, const char *fn)
|
||||
|
||||
#define tag__type_not_found(self) __tag__type_not_found(self, __func__)
|
||||
|
||||
static size_t tag__fprintf_decl_info(const struct tag *self, FILE *fp)
|
||||
size_t tag__fprintf_decl_info(const struct tag *self, FILE *fp)
|
||||
{
|
||||
return fprintf(fp, "/* <%llx> %s:%u */\n",
|
||||
(unsigned long long)self->id,
|
||||
@ -379,8 +379,8 @@ static struct type *type__new(Dwarf_Die *die)
|
||||
return self;
|
||||
}
|
||||
|
||||
static size_t typedef__fprintf(const struct tag *tag_self, const struct cu *cu,
|
||||
FILE *fp)
|
||||
size_t typedef__fprintf(const struct tag *tag_self, const struct cu *cu,
|
||||
FILE *fp)
|
||||
{
|
||||
const struct type *self = tag__type(tag_self);
|
||||
const struct tag *type = cu__find_tag_by_id(cu, tag_self->type);
|
||||
@ -430,8 +430,8 @@ static size_t typedef__fprintf(const struct tag *tag_self, const struct cu *cu,
|
||||
tag__name(type, cu, bf, sizeof(bf)), self->name);
|
||||
}
|
||||
|
||||
static size_t enumeration__fprintf(const struct tag *tag_self,
|
||||
const struct conf_fprintf *conf, FILE *fp)
|
||||
size_t enumeration__fprintf(const struct tag *tag_self,
|
||||
const struct conf_fprintf *conf, FILE *fp)
|
||||
{
|
||||
const struct type *self = tag__type(tag_self);
|
||||
struct enumerator *pos;
|
||||
@ -668,46 +668,6 @@ struct cu *cus__find_cu_by_name(const struct cus *self, const char *name)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct type *cus__find_definition(const struct cus *self, const char *name)
|
||||
{
|
||||
struct type *pos;
|
||||
|
||||
if (name == NULL)
|
||||
return NULL;
|
||||
|
||||
list_for_each_entry(pos, self->definitions, node)
|
||||
if (pos->name != NULL && strcmp(pos->name, name) == 0)
|
||||
return pos;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct type *cus__find_fwd_decl(const struct cus *self, const char *name)
|
||||
{
|
||||
struct type *pos;
|
||||
|
||||
list_for_each_entry(pos, self->fwd_decls, node)
|
||||
if (strcmp(pos->name, name) == 0)
|
||||
return pos;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void cus__add_definition(struct cus *self, struct type *type)
|
||||
{
|
||||
type->definition_emitted = 1;
|
||||
if (!list_empty(&type->node))
|
||||
list_del(&type->node);
|
||||
list_add_tail(&type->node, self->definitions);
|
||||
}
|
||||
|
||||
static void cus__add_fwd_decl(struct cus *self, struct type *type)
|
||||
{
|
||||
type->fwd_decl_emitted = 1;
|
||||
if (list_empty(&type->node))
|
||||
list_add_tail(&type->node, self->fwd_decls);
|
||||
}
|
||||
|
||||
struct tag *cu__find_function_by_name(const struct cu *self, const char *name)
|
||||
{
|
||||
struct tag *pos;
|
||||
@ -1847,9 +1807,7 @@ size_t ftype__fprintf(const struct ftype *self, const struct cu *cu,
|
||||
const char *name, const int inlined,
|
||||
const int is_pointer, int type_spacing, FILE *fp)
|
||||
{
|
||||
struct parameter *pos;
|
||||
struct tag *type = cu__find_tag_by_id(cu, self->tag.type);
|
||||
int first_parm = 1;
|
||||
char sbf[128];
|
||||
const char *stype = tag__name(type, cu, sbf, sizeof(sbf));
|
||||
size_t printed = fprintf(fp, "%s%-*s %s%s%s%s",
|
||||
@ -2685,7 +2643,7 @@ size_t class__fprintf(const struct class *self, const struct cu *cu,
|
||||
list_for_each_entry(pos, &tself->members, tag.node) {
|
||||
struct tag *type;
|
||||
|
||||
if (pos->offset != last_offset)
|
||||
if ((int)pos->offset != last_offset)
|
||||
printed +=
|
||||
class__fprintf_cacheline_boundary(last_cacheline,
|
||||
sum, sum_holes,
|
||||
@ -2696,7 +2654,7 @@ size_t class__fprintf(const struct class *self, const struct cu *cu,
|
||||
if (last_offset != -1) {
|
||||
const ssize_t cc_last_size = pos->offset - last_offset;
|
||||
|
||||
if (pos->offset < last_offset) {
|
||||
if ((int)pos->offset < last_offset) {
|
||||
if (!newline++) {
|
||||
fputc('\n', fp);
|
||||
++printed;
|
||||
@ -2809,7 +2767,7 @@ size_t class__fprintf(const struct class *self, const struct cu *cu,
|
||||
* check for bitfields, accounting for only the biggest
|
||||
* of the byte_size in the fields in each bitfield set.
|
||||
*/
|
||||
if (last_offset != pos->offset ||
|
||||
if (last_offset != (int)pos->offset ||
|
||||
pos->bit_size == 0 || last_bit_size == 0) {
|
||||
last_size = size;
|
||||
sum += last_size;
|
||||
@ -3612,255 +3570,6 @@ struct cus *cus__new(struct list_head *definitions,
|
||||
return self;
|
||||
}
|
||||
|
||||
static int cus__emit_enumeration_definitions(struct cus *self, struct tag *tag,
|
||||
const struct conf_fprintf *conf,
|
||||
FILE *fp)
|
||||
{
|
||||
struct type *etype = tag__type(tag);
|
||||
|
||||
/* Have we already emitted this in this CU? */
|
||||
if (etype->definition_emitted)
|
||||
return 0;
|
||||
|
||||
/* Ok, lets look at the previous CUs: */
|
||||
if (cus__find_definition(self, etype->name) != NULL) {
|
||||
/*
|
||||
* Yes, so lets mark it visited on this CU too,
|
||||
* to speed up the lookup.
|
||||
*/
|
||||
etype->definition_emitted = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
enumeration__fprintf(tag, conf, fp);
|
||||
fputs(";", fp);
|
||||
cus__add_definition(self, etype);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int cus__emit_tag_definitions(struct cus *self, struct cu *cu,
|
||||
struct tag *tag, FILE *fp);
|
||||
|
||||
static int cus__emit_typedef_definitions(struct cus *self, struct cu *cu,
|
||||
struct tag *tdef, FILE *fp)
|
||||
{
|
||||
struct type *def = tag__type(tdef);
|
||||
struct tag *type, *ptr_type;
|
||||
int is_pointer = 0;
|
||||
|
||||
/* Have we already emitted this in this CU? */
|
||||
if (def->definition_emitted)
|
||||
return 0;
|
||||
|
||||
/* Ok, lets look at the previous CUs: */
|
||||
if (cus__find_definition(self, def->name) != NULL) {
|
||||
/*
|
||||
* Yes, so lets mark it visited on this CU too,
|
||||
* to speed up the lookup.
|
||||
*/
|
||||
def->definition_emitted = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
type = cu__find_tag_by_id(cu, tdef->type);
|
||||
|
||||
switch (type->tag) {
|
||||
case DW_TAG_array_type:
|
||||
cus__emit_tag_definitions(self, cu, type, fp);
|
||||
break;
|
||||
case DW_TAG_typedef:
|
||||
cus__emit_typedef_definitions(self, cu, type, fp);
|
||||
break;
|
||||
case DW_TAG_pointer_type:
|
||||
ptr_type = cu__find_tag_by_id(cu, type->type);
|
||||
if (ptr_type->tag != DW_TAG_subroutine_type)
|
||||
break;
|
||||
type = ptr_type;
|
||||
is_pointer = 1;
|
||||
/* Fall thru */
|
||||
case DW_TAG_subroutine_type:
|
||||
cus__emit_ftype_definitions(self, cu, tag__ftype(type), fp);
|
||||
break;
|
||||
case DW_TAG_enumeration_type: {
|
||||
const struct type *ctype = tag__type(type);
|
||||
struct conf_fprintf conf = {
|
||||
.suffix = NULL,
|
||||
};
|
||||
|
||||
tag__fprintf_decl_info(type, fp);
|
||||
if (ctype->name == NULL) {
|
||||
fputs("typedef ", fp);
|
||||
conf.suffix = def->name;
|
||||
cus__emit_enumeration_definitions(self, type, &conf, fp);
|
||||
goto out;
|
||||
} else
|
||||
cus__emit_enumeration_definitions(self, type, &conf, fp);
|
||||
}
|
||||
break;
|
||||
case DW_TAG_structure_type:
|
||||
case DW_TAG_union_type: {
|
||||
const struct type *ctype = tag__type(type);
|
||||
|
||||
if (ctype->name == NULL) {
|
||||
if (cus__emit_type_definitions(self, cu, type, fp))
|
||||
type__emit(type, cu, "typedef", def->name, fp);
|
||||
goto out;
|
||||
} else if (cus__emit_type_definitions(self, cu, type, fp))
|
||||
type__emit(type, cu, NULL, NULL, fp);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Recheck if the typedef was emitted, as there are cases, like
|
||||
* wait_queue_t in the Linux kernel, that is against struct
|
||||
* __wait_queue, that has a wait_queue_func_t member, a function
|
||||
* typedef that has as one of its parameters a... wait_queue_t, that
|
||||
* will thus be emitted before the function typedef, making a no go to
|
||||
* redefine the typedef after struct __wait_queue.
|
||||
*/
|
||||
if (!def->definition_emitted) {
|
||||
typedef__fprintf(tdef, cu, fp);
|
||||
fputs(";\n", fp);
|
||||
}
|
||||
out:
|
||||
cus__add_definition(self, def);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int cus__emit_fwd_decl(struct cus *self, struct type *ctype, FILE *fp)
|
||||
{
|
||||
/* Have we already emitted this in this CU? */
|
||||
if (ctype->fwd_decl_emitted)
|
||||
return 0;
|
||||
|
||||
/* Ok, lets look at the previous CUs: */
|
||||
if (cus__find_fwd_decl(self, ctype->name) != NULL) {
|
||||
/*
|
||||
* Yes, so lets mark it visited on this CU too,
|
||||
* to speed up the lookup.
|
||||
*/
|
||||
ctype->fwd_decl_emitted = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
fprintf(fp, "%s %s;\n",
|
||||
ctype->tag.tag == DW_TAG_union_type ? "union" : "struct",
|
||||
ctype->name);
|
||||
cus__add_fwd_decl(self, ctype);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int cus__emit_tag_definitions(struct cus *self, struct cu *cu,
|
||||
struct tag *tag, FILE *fp)
|
||||
{
|
||||
struct tag *type = cu__find_tag_by_id(cu, tag->type);
|
||||
int pointer = 0;
|
||||
|
||||
if (type == NULL)
|
||||
return 0;
|
||||
next_indirection:
|
||||
switch (type->tag) {
|
||||
case DW_TAG_pointer_type:
|
||||
case DW_TAG_reference_type:
|
||||
pointer = 1;
|
||||
/* Fall thru */
|
||||
case DW_TAG_array_type:
|
||||
case DW_TAG_const_type:
|
||||
case DW_TAG_volatile_type:
|
||||
type = cu__find_tag_by_id(cu, type->type);
|
||||
if (type == NULL)
|
||||
return 0;
|
||||
goto next_indirection;
|
||||
case DW_TAG_typedef:
|
||||
return cus__emit_typedef_definitions(self, cu, type, fp);
|
||||
case DW_TAG_enumeration_type:
|
||||
if (tag__type(type)->name != NULL) {
|
||||
tag__fprintf_decl_info(type, fp);
|
||||
return cus__emit_enumeration_definitions(self, type,
|
||||
NULL, fp);
|
||||
}
|
||||
break;
|
||||
case DW_TAG_structure_type:
|
||||
case DW_TAG_union_type:
|
||||
if (pointer)
|
||||
return cus__emit_fwd_decl(self, tag__type(type), fp);
|
||||
if (cus__emit_type_definitions(self, cu, type, fp))
|
||||
type__emit(type, cu, NULL, NULL, fp);
|
||||
return 1;
|
||||
case DW_TAG_subroutine_type:
|
||||
return cus__emit_ftype_definitions(self, cu,
|
||||
tag__ftype(type), fp);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cus__emit_ftype_definitions(struct cus *self, struct cu *cu,
|
||||
struct ftype *ftype, FILE *fp)
|
||||
{
|
||||
struct parameter *pos;
|
||||
/* First check the function return type */
|
||||
int printed = cus__emit_tag_definitions(self, cu, &ftype->tag, fp);
|
||||
|
||||
/* Then its parameters */
|
||||
list_for_each_entry(pos, &ftype->parms, tag.node)
|
||||
if (cus__emit_tag_definitions(self, cu, &pos->tag, fp))
|
||||
printed = 1;
|
||||
|
||||
if (printed)
|
||||
fputc('\n', fp);
|
||||
return printed;
|
||||
}
|
||||
|
||||
int cus__emit_type_definitions(struct cus *self, struct cu *cu,
|
||||
struct tag *tag, FILE *fp)
|
||||
{
|
||||
struct type *ctype = tag__type(tag);
|
||||
struct class_member *pos;
|
||||
int printed = 0;
|
||||
|
||||
if (ctype->definition_emitted)
|
||||
return 0;
|
||||
|
||||
/* Ok, lets look at the previous CUs: */
|
||||
if (cus__find_definition(self, ctype->name) != NULL) {
|
||||
ctype->definition_emitted = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
cus__add_definition(self, ctype);
|
||||
|
||||
list_for_each_entry(pos, &ctype->members, tag.node)
|
||||
if (cus__emit_tag_definitions(self, cu, &pos->tag, fp))
|
||||
printed = 1;
|
||||
|
||||
if (printed)
|
||||
fputc('\n', fp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void type__emit(struct tag *tag_self, struct cu *cu,
|
||||
const char *prefix, const char *suffix, FILE *fp)
|
||||
{
|
||||
struct type *ctype = tag__type(tag_self);
|
||||
|
||||
if (tag_self->tag == DW_TAG_structure_type)
|
||||
class__find_holes(tag__class(tag_self), cu);
|
||||
|
||||
if (ctype->name != NULL || suffix != NULL || prefix != NULL) {
|
||||
struct conf_fprintf conf = {
|
||||
.prefix = prefix,
|
||||
.suffix = suffix,
|
||||
.emit_stats = 1,
|
||||
};
|
||||
tag__fprintf(tag_self, cu, &conf, fp);
|
||||
|
||||
if (tag_self->tag != DW_TAG_structure_type)
|
||||
fputc(';', fp);
|
||||
fputc('\n', fp);
|
||||
}
|
||||
}
|
||||
|
||||
void dwarves__init(size_t user_cacheline_size)
|
||||
{
|
||||
if (user_cacheline_size == 0) {
|
||||
|
12
dwarves.h
12
dwarves.h
@ -282,6 +282,11 @@ extern struct class *class__reorganize(struct class *self,
|
||||
const int verbose, FILE *fp);
|
||||
extern size_t class__fprintf(const 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 conf_fprintf *conf, FILE *fp);
|
||||
extern size_t typedef__fprintf(const struct tag *tag_self, const struct cu *cu,
|
||||
FILE *fp);
|
||||
extern size_t tag__fprintf_decl_info(const struct tag *self, FILE *fp);
|
||||
extern size_t tag__fprintf(const struct tag *self, const struct cu *cu,
|
||||
const struct conf_fprintf *conf, FILE *fp);
|
||||
|
||||
@ -312,13 +317,6 @@ extern struct tag *cus__find_struct_by_name(const struct cus *self,
|
||||
extern struct tag *cus__find_function_by_name(const struct cus *self,
|
||||
struct cu **cu,
|
||||
const char *name);
|
||||
extern int cus__emit_ftype_definitions(struct cus *self, struct cu *cu,
|
||||
struct ftype *ftype, FILE *fp);
|
||||
extern int cus__emit_type_definitions(struct cus *self, struct cu *cu,
|
||||
struct tag *tag, FILE *fp);
|
||||
extern int cus__emit_fwd_decl(struct cus *self, struct type *ctype, FILE *fp);
|
||||
extern void type__emit(struct tag *tag_self, struct cu *cu,
|
||||
const char *prefix, const char *suffix, FILE *fp);
|
||||
|
||||
extern struct tag *cu__find_tag_by_id(const struct cu *self,
|
||||
const Dwarf_Off id);
|
||||
|
307
dwarves_emit.c
Normal file
307
dwarves_emit.c
Normal file
@ -0,0 +1,307 @@
|
||||
/*
|
||||
Copyright (C) 2006 Mandriva Conectiva S.A.
|
||||
Copyright (C) 2006 Arnaldo Carvalho de Melo <acme@mandriva.com>
|
||||
Copyright (C) 2007 Red Hat Inc.
|
||||
Copyright (C) 2007 Arnaldo Carvalho de Melo <acme@redhat.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 <string.h>
|
||||
|
||||
#include "list.h"
|
||||
#include "dwarves_emit.h"
|
||||
#include "dwarves.h"
|
||||
|
||||
static void cus__add_definition(struct cus *self, struct type *type)
|
||||
{
|
||||
type->definition_emitted = 1;
|
||||
if (!list_empty(&type->node))
|
||||
list_del(&type->node);
|
||||
list_add_tail(&type->node, self->definitions);
|
||||
}
|
||||
|
||||
static void cus__add_fwd_decl(struct cus *self, struct type *type)
|
||||
{
|
||||
type->fwd_decl_emitted = 1;
|
||||
if (list_empty(&type->node))
|
||||
list_add_tail(&type->node, self->fwd_decls);
|
||||
}
|
||||
|
||||
static struct type *cus__find_definition(const struct cus *self,
|
||||
const char *name)
|
||||
{
|
||||
struct type *pos;
|
||||
|
||||
if (name == NULL)
|
||||
return NULL;
|
||||
|
||||
list_for_each_entry(pos, self->definitions, node)
|
||||
if (pos->name != NULL && strcmp(pos->name, name) == 0)
|
||||
return pos;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct type *cus__find_fwd_decl(const struct cus *self,
|
||||
const char *name)
|
||||
{
|
||||
struct type *pos;
|
||||
|
||||
list_for_each_entry(pos, self->fwd_decls, node)
|
||||
if (strcmp(pos->name, name) == 0)
|
||||
return pos;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int cus__emit_enumeration_definitions(struct cus *self, struct tag *tag,
|
||||
const struct conf_fprintf *conf,
|
||||
FILE *fp)
|
||||
{
|
||||
struct type *etype = tag__type(tag);
|
||||
|
||||
/* Have we already emitted this in this CU? */
|
||||
if (etype->definition_emitted)
|
||||
return 0;
|
||||
|
||||
/* Ok, lets look at the previous CUs: */
|
||||
if (cus__find_definition(self, etype->name) != NULL) {
|
||||
/*
|
||||
* Yes, so lets mark it visited on this CU too,
|
||||
* to speed up the lookup.
|
||||
*/
|
||||
etype->definition_emitted = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
enumeration__fprintf(tag, conf, fp);
|
||||
fputs(";", fp);
|
||||
cus__add_definition(self, etype);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int cus__emit_tag_definitions(struct cus *self, struct cu *cu,
|
||||
struct tag *tag, FILE *fp);
|
||||
|
||||
static int cus__emit_typedef_definitions(struct cus *self, struct cu *cu,
|
||||
struct tag *tdef, FILE *fp)
|
||||
{
|
||||
struct type *def = tag__type(tdef);
|
||||
struct tag *type, *ptr_type;
|
||||
int is_pointer = 0;
|
||||
|
||||
/* Have we already emitted this in this CU? */
|
||||
if (def->definition_emitted)
|
||||
return 0;
|
||||
|
||||
/* Ok, lets look at the previous CUs: */
|
||||
if (cus__find_definition(self, def->name) != NULL) {
|
||||
/*
|
||||
* Yes, so lets mark it visited on this CU too,
|
||||
* to speed up the lookup.
|
||||
*/
|
||||
def->definition_emitted = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
type = cu__find_tag_by_id(cu, tdef->type);
|
||||
|
||||
switch (type->tag) {
|
||||
case DW_TAG_array_type:
|
||||
cus__emit_tag_definitions(self, cu, type, fp);
|
||||
break;
|
||||
case DW_TAG_typedef:
|
||||
cus__emit_typedef_definitions(self, cu, type, fp);
|
||||
break;
|
||||
case DW_TAG_pointer_type:
|
||||
ptr_type = cu__find_tag_by_id(cu, type->type);
|
||||
if (ptr_type->tag != DW_TAG_subroutine_type)
|
||||
break;
|
||||
type = ptr_type;
|
||||
is_pointer = 1;
|
||||
/* Fall thru */
|
||||
case DW_TAG_subroutine_type:
|
||||
cus__emit_ftype_definitions(self, cu, tag__ftype(type), fp);
|
||||
break;
|
||||
case DW_TAG_enumeration_type: {
|
||||
const struct type *ctype = tag__type(type);
|
||||
struct conf_fprintf conf = {
|
||||
.suffix = NULL,
|
||||
};
|
||||
|
||||
tag__fprintf_decl_info(type, fp);
|
||||
if (ctype->name == NULL) {
|
||||
fputs("typedef ", fp);
|
||||
conf.suffix = def->name;
|
||||
cus__emit_enumeration_definitions(self, type, &conf, fp);
|
||||
goto out;
|
||||
} else
|
||||
cus__emit_enumeration_definitions(self, type, &conf, fp);
|
||||
}
|
||||
break;
|
||||
case DW_TAG_structure_type:
|
||||
case DW_TAG_union_type: {
|
||||
const struct type *ctype = tag__type(type);
|
||||
|
||||
if (ctype->name == NULL) {
|
||||
if (cus__emit_type_definitions(self, cu, type, fp))
|
||||
type__emit(type, cu, "typedef", def->name, fp);
|
||||
goto out;
|
||||
} else if (cus__emit_type_definitions(self, cu, type, fp))
|
||||
type__emit(type, cu, NULL, NULL, fp);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Recheck if the typedef was emitted, as there are cases, like
|
||||
* wait_queue_t in the Linux kernel, that is against struct
|
||||
* __wait_queue, that has a wait_queue_func_t member, a function
|
||||
* typedef that has as one of its parameters a... wait_queue_t, that
|
||||
* will thus be emitted before the function typedef, making a no go to
|
||||
* redefine the typedef after struct __wait_queue.
|
||||
*/
|
||||
if (!def->definition_emitted) {
|
||||
typedef__fprintf(tdef, cu, fp);
|
||||
fputs(";\n", fp);
|
||||
}
|
||||
out:
|
||||
cus__add_definition(self, def);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int cus__emit_fwd_decl(struct cus *self, struct type *ctype, FILE *fp)
|
||||
{
|
||||
/* Have we already emitted this in this CU? */
|
||||
if (ctype->fwd_decl_emitted)
|
||||
return 0;
|
||||
|
||||
/* Ok, lets look at the previous CUs: */
|
||||
if (cus__find_fwd_decl(self, ctype->name) != NULL) {
|
||||
/*
|
||||
* Yes, so lets mark it visited on this CU too,
|
||||
* to speed up the lookup.
|
||||
*/
|
||||
ctype->fwd_decl_emitted = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
fprintf(fp, "%s %s;\n",
|
||||
ctype->tag.tag == DW_TAG_union_type ? "union" : "struct",
|
||||
ctype->name);
|
||||
cus__add_fwd_decl(self, ctype);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int cus__emit_tag_definitions(struct cus *self, struct cu *cu,
|
||||
struct tag *tag, FILE *fp)
|
||||
{
|
||||
struct tag *type = cu__find_tag_by_id(cu, tag->type);
|
||||
int pointer = 0;
|
||||
|
||||
if (type == NULL)
|
||||
return 0;
|
||||
next_indirection:
|
||||
switch (type->tag) {
|
||||
case DW_TAG_pointer_type:
|
||||
case DW_TAG_reference_type:
|
||||
pointer = 1;
|
||||
/* Fall thru */
|
||||
case DW_TAG_array_type:
|
||||
case DW_TAG_const_type:
|
||||
case DW_TAG_volatile_type:
|
||||
type = cu__find_tag_by_id(cu, type->type);
|
||||
if (type == NULL)
|
||||
return 0;
|
||||
goto next_indirection;
|
||||
case DW_TAG_typedef:
|
||||
return cus__emit_typedef_definitions(self, cu, type, fp);
|
||||
case DW_TAG_enumeration_type:
|
||||
if (tag__type(type)->name != NULL) {
|
||||
tag__fprintf_decl_info(type, fp);
|
||||
return cus__emit_enumeration_definitions(self, type,
|
||||
NULL, fp);
|
||||
}
|
||||
break;
|
||||
case DW_TAG_structure_type:
|
||||
case DW_TAG_union_type:
|
||||
if (pointer)
|
||||
return cus__emit_fwd_decl(self, tag__type(type), fp);
|
||||
if (cus__emit_type_definitions(self, cu, type, fp))
|
||||
type__emit(type, cu, NULL, NULL, fp);
|
||||
return 1;
|
||||
case DW_TAG_subroutine_type:
|
||||
return cus__emit_ftype_definitions(self, cu,
|
||||
tag__ftype(type), fp);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cus__emit_ftype_definitions(struct cus *self, struct cu *cu,
|
||||
struct ftype *ftype, FILE *fp)
|
||||
{
|
||||
struct parameter *pos;
|
||||
/* First check the function return type */
|
||||
int printed = cus__emit_tag_definitions(self, cu, &ftype->tag, fp);
|
||||
|
||||
/* Then its parameters */
|
||||
list_for_each_entry(pos, &ftype->parms, tag.node)
|
||||
if (cus__emit_tag_definitions(self, cu, &pos->tag, fp))
|
||||
printed = 1;
|
||||
|
||||
if (printed)
|
||||
fputc('\n', fp);
|
||||
return printed;
|
||||
}
|
||||
|
||||
int cus__emit_type_definitions(struct cus *self, struct cu *cu,
|
||||
struct tag *tag, FILE *fp)
|
||||
{
|
||||
struct type *ctype = tag__type(tag);
|
||||
struct class_member *pos;
|
||||
int printed = 0;
|
||||
|
||||
if (ctype->definition_emitted)
|
||||
return 0;
|
||||
|
||||
/* Ok, lets look at the previous CUs: */
|
||||
if (cus__find_definition(self, ctype->name) != NULL) {
|
||||
ctype->definition_emitted = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
cus__add_definition(self, ctype);
|
||||
|
||||
list_for_each_entry(pos, &ctype->members, tag.node)
|
||||
if (cus__emit_tag_definitions(self, cu, &pos->tag, fp))
|
||||
printed = 1;
|
||||
|
||||
if (printed)
|
||||
fputc('\n', fp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void type__emit(struct tag *tag_self, struct cu *cu,
|
||||
const char *prefix, const char *suffix, FILE *fp)
|
||||
{
|
||||
struct type *ctype = tag__type(tag_self);
|
||||
|
||||
if (tag_self->tag == DW_TAG_structure_type)
|
||||
class__find_holes(tag__class(tag_self), cu);
|
||||
|
||||
if (ctype->name != NULL || suffix != NULL || prefix != NULL) {
|
||||
struct conf_fprintf conf = {
|
||||
.prefix = prefix,
|
||||
.suffix = suffix,
|
||||
.emit_stats = 1,
|
||||
};
|
||||
tag__fprintf(tag_self, cu, &conf, fp);
|
||||
|
||||
if (tag_self->tag != DW_TAG_structure_type)
|
||||
fputc(';', fp);
|
||||
fputc('\n', fp);
|
||||
}
|
||||
}
|
29
dwarves_emit.h
Normal file
29
dwarves_emit.h
Normal file
@ -0,0 +1,29 @@
|
||||
#ifndef _DWARVES_EMIT_H_
|
||||
#define _DWARVES_EMIT_H_ 1
|
||||
/*
|
||||
Copyright (C) 2006 Mandriva Conectiva S.A.
|
||||
Copyright (C) 2006 Arnaldo Carvalho de Melo <acme@mandriva.com>
|
||||
Copyright (C) 2007 Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
|
||||
|
||||
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 <stdio.h>
|
||||
|
||||
struct cus;
|
||||
struct cu;
|
||||
struct ftype;
|
||||
struct tag;
|
||||
struct type;
|
||||
|
||||
extern int cus__emit_ftype_definitions(struct cus *self, struct cu *cu,
|
||||
struct ftype *ftype, FILE *fp);
|
||||
extern int cus__emit_type_definitions(struct cus *self, struct cu *cu,
|
||||
struct tag *tag, FILE *fp);
|
||||
extern int cus__emit_fwd_decl(struct cus *self, struct type *ctype, FILE *fp);
|
||||
extern void type__emit(struct tag *tag_self, struct cu *cu,
|
||||
const char *prefix, const char *suffix, FILE *fp);
|
||||
|
||||
#endif /* _DWARVES_EMIT_H_ */
|
@ -86,12 +86,15 @@ rm -rf %{buildroot}
|
||||
%files -n %{libname}%{libver}
|
||||
%defattr(0644,root,root,0755)
|
||||
%{_libdir}/%{libname}.so.*
|
||||
%{_libdir}/%{libname}_emit.so.*
|
||||
|
||||
%files -n %{libname}%{libver}-devel
|
||||
%defattr(0644,root,root,0755)
|
||||
%doc MANIFEST README
|
||||
%{_includedir}/dwarves.h
|
||||
%{_includedir}/dwarves_emit.h
|
||||
%{_libdir}/%{libname}.so
|
||||
%{_libdir}/%{libname}_emit.so
|
||||
|
||||
%changelog
|
||||
* Tue Apr 3 2007 Arnaldo Carvalho de Melo <acme@redhat.com>
|
||||
|
Loading…
Reference in New Issue
Block a user