/* Get attributes of the DIE. Copyright (C) 2004 Red Hat, Inc. Written by Ulrich Drepper , 2004. This program is Open Source software; you can redistribute it and/or modify it under the terms of the Open Software License version 1.0 as published by the Open Source Initiative. You should have received a copy of the Open Software License along with this program; if not, you may obtain a copy of the Open Software License version 1.0 from http://www.opensource.org/licenses/osl.php or by writing the Open Source Initiative c/o Lawrence Rosen, Esq., 3001 King Ranch Road, Ukiah, CA 95482. */ #ifdef HAVE_CONFIG_H # include #endif #include "libdwP.h" ptrdiff_t dwarf_getattrs (Dwarf_Die *die, int (*callback) (Dwarf_Attribute *, void *), void *arg, ptrdiff_t offset) { if (die == NULL) return -1l; unsigned char *die_addr = die->addr; /* Get the abbreviation code. */ unsigned int u128; get_uleb128 (u128, die_addr); if (die->abbrev == NULL) /* Find the abbreviation. */ die->abbrev = __libdw_findabbrev (die->cu, u128); if (die->abbrev == (Dwarf_Abbrev *) -1l) { __libdw_seterrno (DWARF_E_INVALID_DWARF); return -1l; } /* This is where the attributes start. */ unsigned char *attrp = die->abbrev->attrp + offset; /* Go over the list of attributes. */ Dwarf *dbg = die->cu->dbg; while (1) { /* Are we still in bounds? */ if (unlikely (attrp >= ((unsigned char *) dbg->sectiondata[IDX_debug_abbrev]->d_buf + dbg->sectiondata[IDX_debug_abbrev]->d_size))) { __libdw_seterrno (DWARF_E_INVALID_DWARF); return -1; } /* Get attribute name and form. */ Dwarf_Attribute attr; // XXX Fix bound checks get_uleb128 (attr.code, attrp); get_uleb128 (attr.form, attrp); /* We can stop if we found the attribute with value zero. */ if (attr.code == 0 && attr.form == 0) return 0; /* Fill in the rest. */ attr.valp = die_addr; attr.cu = die->cu; /* Now call the callback function. */ if (callback (&attr, arg) != DWARF_CB_OK) return attrp - die->abbrev->attrp; /* Skip over the rest of this attribute (if there is any). */ if (attr.form != 0) { size_t len = __libdw_form_val_len (dbg, die->cu, attr.form, die_addr); if (unlikely (len == (size_t) -1l)) /* Something wrong with the file. */ return -1l; // XXX We need better boundary checks. die_addr += len; } } /* NOTREACHED */ }