dwarf: Detect type loops

[acme@doppio pahole]$ pahole -F ctf /media/tb/debuginfo/usr/lib/debug/usr/bin/greycstoration4integration.debug > /tmp/bla
<ERROR(tag__size:837): detected type loop: type=572, tag=const_type>
<ERROR(tag__size:837): detected type loop: type=572, tag=const_type>
[acme@doppio pahole]$

These type loops are problems in the CTF encoding, that should be fixed, but
should not cause the core code to segfault on an infinite recursion.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
Arnaldo Carvalho de Melo 2009-09-14 17:07:02 -03:00
parent 428f318599
commit 9720415091
3 changed files with 61 additions and 8 deletions

View File

@ -44,6 +44,29 @@ static inline const char *s(const struct cu *self, strings_t i)
return cu__string(self, i);
}
int __tag__has_type_loop(const struct tag *self, const struct tag *type,
char *bf, size_t len, FILE *fp,
const char *fn, int line)
{
char bbf[2048], *abf = bbf;
if (self->type == type->type) {
int printed;
if (bf != NULL)
abf = bf;
else
len = sizeof(bbf);
printed = snprintf(abf, len, "<ERROR(%s:%d): detected type loop: type=%d, tag=%s>",
fn, line, self->type, dwarf_tag_name(self->tag));
if (bf == NULL)
printed = fprintf(fp ?: stderr, "%s\n", abf);
return printed;
}
return 0;
}
static void lexblock__delete_tags(struct tag *tself, struct cu *cu)
{
struct lexblock *self = tag__lexblock(tself);
@ -811,7 +834,8 @@ size_t tag__size(const struct tag *self, const struct cu *cu)
if (type == NULL) {
tag__id_not_found_fprintf(stderr, self->type);
return -1;
}
} else if (tag__has_type_loop(self, type, NULL, 0, NULL))
return -1;
size = tag__size(type, cu);
}

View File

@ -476,6 +476,12 @@ size_t __tag__id_not_found_fprintf(FILE *fp, uint16_t id,
#define tag__id_not_found_fprintf(fp, id) \
__tag__id_not_found_fprintf(fp, id, __func__, __LINE__)
int __tag__has_type_loop(const struct tag *self, const struct tag *type,
char *bf, size_t len, FILE *fp,
const char *fn, int line);
#define tag__has_type_loop(self, type, bf, len, fp) \
__tag__has_type_loop(self, type, bf, len, fp, __func__, __LINE__)
struct ptr_to_member_type {
struct tag tag;
uint16_t containing_type;

View File

@ -345,8 +345,9 @@ static const char *tag__ptr_name(const struct tag *self, const struct cu *cu,
size_t l = tag__id_not_found_snprintf(bf, len,
self->type);
snprintf(bf + l, len - l, " %s", ptr_suffix);
} else {
} else if (!tag__has_type_loop(self, type, bf, len, NULL)) {
char tmpbf[1024];
snprintf(bf, len, "%s %s",
__tag__name(type, cu,
tmpbf, sizeof(tmpbf), NULL),
@ -408,7 +409,7 @@ static const char *__tag__name(const struct tag *self, const struct cu *cu,
type = cu__type(cu, self->type);
if (type == NULL && self->type != 0)
tag__id_not_found_snprintf(bf, len, self->type);
else {
else if (!tag__has_type_loop(self, type, bf, len, NULL)) {
char tmpbf[128];
const char *prefix = "const",
*type_str = __tag__name(type, cu, tmpbf,
@ -423,7 +424,7 @@ static const char *__tag__name(const struct tag *self, const struct cu *cu,
type = cu__type(cu, self->type);
if (type == NULL)
tag__id_not_found_snprintf(bf, len, self->type);
else
else if (!tag__has_type_loop(self, type, bf, len, NULL))
return __tag__name(type, cu, bf, len, pconf);
break;
case DW_TAG_subroutine_type: {
@ -518,9 +519,16 @@ static size_t type__fprintf(struct tag *type, const struct cu *cu,
int nr_indirections = 0;
while (type->tag == DW_TAG_pointer_type && type->type != 0) {
type = cu__type(cu, type->type);
if (type == NULL)
struct tag *ttype = cu__type(cu, type->type);
if (ttype == NULL)
goto out_type_not_found;
else {
printed = tag__has_type_loop(type, ttype,
NULL, 0, fp);
if (printed)
return printed;
}
type = ttype;
++nr_indirections;
}
@ -548,6 +556,9 @@ static size_t type__fprintf(struct tag *type, const struct cu *cu,
int typedef_expanded = 0;
while (tag__is_typedef(type)) {
struct tag *type_type;
int n;
ctype = tag__type(type);
if (typedef_expanded)
printed += fprintf(fp, " -> %s",
@ -557,9 +568,13 @@ static size_t type__fprintf(struct tag *type, const struct cu *cu,
type__name(ctype, cu));
typedef_expanded = 1;
}
type = cu__type(cu, type->type);
if (type == NULL)
type_type = cu__type(cu, type->type);
if (type_type == NULL)
goto out_type_not_found;
n = tag__has_type_loop(type, type_type, NULL, 0, fp);
if (n)
return printed + n;
type = type_type;
}
if (typedef_expanded)
printed += fprintf(fp, " */ ");
@ -578,9 +593,13 @@ static size_t type__fprintf(struct tag *type, const struct cu *cu,
switch (type->tag) {
case DW_TAG_pointer_type:
if (type->type != 0) {
int n;
struct tag *ptype = cu__type(cu, type->type);
if (ptype == NULL)
goto out_type_not_found;
n = tag__has_type_loop(type, ptype, NULL, 0, fp);
if (n)
return printed + n;
if (ptype->tag == DW_TAG_subroutine_type) {
printed += ftype__fprintf(tag__ftype(ptype),
cu, name, 0, 1,
@ -835,12 +854,16 @@ size_t ftype__fprintf_parms(const struct ftype *self,
}
if (type->tag == DW_TAG_pointer_type) {
if (type->type != 0) {
int n;
struct tag *ptype = cu__type(cu, type->type);
if (ptype == NULL) {
printed +=
tag__id_not_found_fprintf(fp, type->type);
continue;
}
n = tag__has_type_loop(type, ptype, NULL, 0, fp);
if (n)
return printed + n;
if (ptype->tag == DW_TAG_subroutine_type) {
printed +=
ftype__fprintf(tag__ftype(ptype),