If we don't cache the attrcnt and use bitfields for the has_children and code we can reduce the size of struct Dwarf Abbrev from 32 to 24 bytes on 64bit architectures and from 28 to 20 bytes on 32bit arches.
Signed-off-by: Mark Wielaard <m...@klomp.org> --- libdw/ChangeLog | 7 +++++++ libdw/dwarf_getabbrev.c | 7 +++---- libdw/dwarf_getattrcnt.c | 19 +++++++++++++++++-- libdw/libdwP.h | 15 +++++++-------- 4 files changed, 34 insertions(+), 14 deletions(-) diff --git a/libdw/ChangeLog b/libdw/ChangeLog index 3e3b7169..c284dbbd 100644 --- a/libdw/ChangeLog +++ b/libdw/ChangeLog @@ -1,3 +1,10 @@ +2017-12-26 Mark Wielaard <m...@klomp.org> + + * libdwP.h (struct Dwarf_Abbrev): Pack struct. Remove attrcnt, + use bitfields for has_children and code. + * dwarf_getabbrev.c (__libdw_getabbrev): Don't count attrs. + * dwarf_getattrcnt.c (dwarf_getattrcnt): Count attrs. + 2017-12-26 Mark Wielaard <m...@klomp.org> * memory-access.h (__libdw_get_uleb128_unchecked): New function. diff --git a/libdw/dwarf_getabbrev.c b/libdw/dwarf_getabbrev.c index ef51b847..a3a68b37 100644 --- a/libdw/dwarf_getabbrev.c +++ b/libdw/dwarf_getabbrev.c @@ -1,5 +1,5 @@ /* Get abbreviation at given offset. - Copyright (C) 2003, 2004, 2005, 2006, 2014 Red Hat, Inc. + Copyright (C) 2003, 2004, 2005, 2006, 2014, 2017 Red Hat, Inc. This file is part of elfutils. Written by Ulrich Drepper <drep...@redhat.com>, 2003. @@ -121,8 +121,7 @@ __libdw_getabbrev (Dwarf *dbg, struct Dwarf_CU *cu, Dwarf_Off offset, abb->attrp = (unsigned char *) abbrevp; abb->offset = offset; - /* Skip over all the attributes and count them while doing so. */ - abb->attrcnt = 0; + /* Skip over all the attributes and check rest of the abbrev is valid. */ unsigned int attrname; unsigned int attrform; do @@ -134,7 +133,7 @@ __libdw_getabbrev (Dwarf *dbg, struct Dwarf_CU *cu, Dwarf_Off offset, goto invalid; get_uleb128 (attrform, abbrevp, end); } - while (attrname != 0 && attrform != 0 && ++abb->attrcnt); + while (attrname != 0 && attrform != 0); /* Return the length to the caller if she asked for it. */ if (lengthp != NULL) diff --git a/libdw/dwarf_getattrcnt.c b/libdw/dwarf_getattrcnt.c index 2bfb4ac5..a05976d4 100644 --- a/libdw/dwarf_getattrcnt.c +++ b/libdw/dwarf_getattrcnt.c @@ -1,5 +1,5 @@ /* Get number of attributes of abbreviation. - Copyright (C) 2003, 2004 Red Hat, Inc. + Copyright (C) 2003, 2004, 2017 Red Hat, Inc. This file is part of elfutils. Written by Ulrich Drepper <drep...@redhat.com>, 2003. @@ -40,7 +40,22 @@ dwarf_getattrcnt (Dwarf_Abbrev *abbrev, size_t *attrcntp) if (abbrev == NULL) return -1; - *attrcntp = abbrev->attrcnt; + const unsigned char *abbrevp = abbrev->attrp; + + /* Skip over all the attributes and count them while doing so. */ + int attrcnt = 0; + unsigned int attrname; + unsigned int attrform; + do + { + /* We can use unchecked since they were checked when the Dwrf_Abbrev + was created. */ + get_uleb128_unchecked (attrname, abbrevp); + get_uleb128_unchecked (attrform, abbrevp); + } + while (attrname != 0 && attrform != 0 && ++attrcnt); + + *attrcntp = attrcnt; return 0; } diff --git a/libdw/libdwP.h b/libdw/libdwP.h index 82b47d09..fbb8ed08 100644 --- a/libdw/libdwP.h +++ b/libdw/libdwP.h @@ -1,5 +1,5 @@ /* Internal definitions for libdwarf. - Copyright (C) 2002-2011, 2013-2016 Red Hat, Inc. + Copyright (C) 2002-2011, 2013-2017 Red Hat, Inc. This file is part of elfutils. Written by Ulrich Drepper <drep...@redhat.com>, 2002. @@ -212,13 +212,12 @@ struct Dwarf /* Abbreviation representation. */ struct Dwarf_Abbrev { - Dwarf_Off offset; - unsigned char *attrp; - unsigned int attrcnt; - unsigned int code; - unsigned int tag; - bool has_children; -}; + Dwarf_Off offset; /* Offset to start of abbrev into .debug_abbrev. */ + unsigned char *attrp; /* Pointer to start of attribute name/form pairs. */ + bool has_children : 1; /* Whether or not the DIE has children. */ + unsigned int code : 31; /* The (unique) abbrev code. */ + unsigned int tag; /* The tag of the DIE. */ +} attribute_packed; #include "dwarf_abbrev_hash.h" -- 2.14.3