From 162dce5526debd7fbc3a4516c37ee6178bab6e5b Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Sat, 8 Feb 2020 13:40:54 -0700 Subject: [PATCH] Create dwarf2/attribute.[ch] This moves the attribute-related code out of dwarf2read.c and into the new files dwarf2/attribute.[ch]. gdb/ChangeLog 2020-02-08 Tom Tromey * dwarf2read.c (struct attribute, DW_STRING) (DW_STRING_IS_CANONICAL, DW_UNSND, DW_BLOCK, DW_SND, DW_ADDR) (DW_SIGNATURE, struct dwarf_block, attr_value_as_address) (attr_form_is_block, attr_form_is_section_offset) (attr_form_is_constant, attr_form_is_ref): Move. * dwarf2/attribute.h: New file. * dwarf2/attribute.c: New file, from dwarf2read.c. * Makefile.in (COMMON_SFILES): Add dwarf2/attribute.c. Change-Id: I1ea4c146256a1b9e38b66f1c605d782a14eeded7 --- gdb/ChangeLog | 11 +++ gdb/Makefile.in | 1 + gdb/dwarf2/attribute.c | 122 +++++++++++++++++++++++++++++ gdb/dwarf2/attribute.h | 118 ++++++++++++++++++++++++++++ gdb/dwarf2read.c | 169 +---------------------------------------- 5 files changed, 253 insertions(+), 168 deletions(-) create mode 100644 gdb/dwarf2/attribute.c create mode 100644 gdb/dwarf2/attribute.h diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 5b6feb6cb8f..741d4bfbc45 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,14 @@ +2020-02-08 Tom Tromey + + * dwarf2read.c (struct attribute, DW_STRING) + (DW_STRING_IS_CANONICAL, DW_UNSND, DW_BLOCK, DW_SND, DW_ADDR) + (DW_SIGNATURE, struct dwarf_block, attr_value_as_address) + (attr_form_is_block, attr_form_is_section_offset) + (attr_form_is_constant, attr_form_is_ref): Move. + * dwarf2/attribute.h: New file. + * dwarf2/attribute.c: New file, from dwarf2read.c. + * Makefile.in (COMMON_SFILES): Add dwarf2/attribute.c. + 2020-02-08 Tom Tromey * dwarf2read.c (abbrev_table_up, struct abbrev_info) diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 12abfa43f7b..b726ae8cb26 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -1003,6 +1003,7 @@ COMMON_SFILES = \ dwarf2loc.c \ dwarf2read.c \ dwarf2/abbrev.c \ + dwarf2/attribute.c \ dwarf2/leb.c \ dwarf2/section.c \ eval.c \ diff --git a/gdb/dwarf2/attribute.c b/gdb/dwarf2/attribute.c new file mode 100644 index 00000000000..75a2fa3774b --- /dev/null +++ b/gdb/dwarf2/attribute.c @@ -0,0 +1,122 @@ +/* DWARF attributes + + Copyright (C) 1994-2020 Free Software Foundation, Inc. + + Adapted by Gary Funck (gary@intrepid.com), Intrepid Technology, + Inc. with support from Florida State University (under contract + with the Ada Joint Program Office), and Silicon Graphics, Inc. + Initial contribution by Brent Benson, Harris Computer Systems, Inc., + based on Fred Fish's (Cygnus Support) implementation of DWARF 1 + support. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include "defs.h" +#include "dwarf2/attribute.h" + +/* See attribute.h. */ + +CORE_ADDR +attr_value_as_address (struct attribute *attr) +{ + CORE_ADDR addr; + + if (attr->form != DW_FORM_addr && attr->form != DW_FORM_addrx + && attr->form != DW_FORM_GNU_addr_index) + { + /* Aside from a few clearly defined exceptions, attributes that + contain an address must always be in DW_FORM_addr form. + Unfortunately, some compilers happen to be violating this + requirement by encoding addresses using other forms, such + as DW_FORM_data4 for example. For those broken compilers, + we try to do our best, without any guarantee of success, + to interpret the address correctly. It would also be nice + to generate a complaint, but that would require us to maintain + a list of legitimate cases where a non-address form is allowed, + as well as update callers to pass in at least the CU's DWARF + version. This is more overhead than what we're willing to + expand for a pretty rare case. */ + addr = DW_UNSND (attr); + } + else + addr = DW_ADDR (attr); + + return addr; +} + +/* See attribute.h. */ + +int +attr_form_is_block (const struct attribute *attr) +{ + return (attr == NULL ? 0 : + attr->form == DW_FORM_block1 + || attr->form == DW_FORM_block2 + || attr->form == DW_FORM_block4 + || attr->form == DW_FORM_block + || attr->form == DW_FORM_exprloc); +} + +/* See attribute.h. */ + +int +attr_form_is_section_offset (const struct attribute *attr) +{ + return (attr->form == DW_FORM_data4 + || attr->form == DW_FORM_data8 + || attr->form == DW_FORM_sec_offset); +} + +/* See attribute.h. */ + +int +attr_form_is_constant (const struct attribute *attr) +{ + switch (attr->form) + { + case DW_FORM_sdata: + case DW_FORM_udata: + case DW_FORM_data1: + case DW_FORM_data2: + case DW_FORM_data4: + case DW_FORM_data8: + case DW_FORM_implicit_const: + return 1; + default: + return 0; + } +} + +/* DW_ADDR is always stored already as sect_offset; despite for the forms + besides DW_FORM_ref_addr it is stored as cu_offset in the DWARF file. */ + +int +attr_form_is_ref (const struct attribute *attr) +{ + switch (attr->form) + { + case DW_FORM_ref_addr: + case DW_FORM_ref1: + case DW_FORM_ref2: + case DW_FORM_ref4: + case DW_FORM_ref8: + case DW_FORM_ref_udata: + case DW_FORM_GNU_ref_alt: + return 1; + default: + return 0; + } +} diff --git a/gdb/dwarf2/attribute.h b/gdb/dwarf2/attribute.h new file mode 100644 index 00000000000..11c6cb929d9 --- /dev/null +++ b/gdb/dwarf2/attribute.h @@ -0,0 +1,118 @@ +/* DWARF attributes + + Copyright (C) 1994-2020 Free Software Foundation, Inc. + + Adapted by Gary Funck (gary@intrepid.com), Intrepid Technology, + Inc. with support from Florida State University (under contract + with the Ada Joint Program Office), and Silicon Graphics, Inc. + Initial contribution by Brent Benson, Harris Computer Systems, Inc., + based on Fred Fish's (Cygnus Support) implementation of DWARF 1 + support. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef GDB_DWARF2_ATTRIBUTE_H +#define GDB_DWARF2_ATTRIBUTE_H + +#include "dwarf2.h" + +/* Blocks are a bunch of untyped bytes. */ +struct dwarf_block +{ + size_t size; + + /* Valid only if SIZE is not zero. */ + const gdb_byte *data; +}; + +/* Attributes have a name and a value. */ +struct attribute +{ + ENUM_BITFIELD(dwarf_attribute) name : 16; + ENUM_BITFIELD(dwarf_form) form : 15; + + /* Has DW_STRING already been updated by dwarf2_canonicalize_name? This + field should be in u.str (existing only for DW_STRING) but it is kept + here for better struct attribute alignment. */ + unsigned int string_is_canonical : 1; + + union + { + const char *str; + struct dwarf_block *blk; + ULONGEST unsnd; + LONGEST snd; + CORE_ADDR addr; + ULONGEST signature; + } + u; +}; + +/* Get at parts of an attribute structure. */ + +#define DW_STRING(attr) ((attr)->u.str) +#define DW_STRING_IS_CANONICAL(attr) ((attr)->string_is_canonical) +#define DW_UNSND(attr) ((attr)->u.unsnd) +#define DW_BLOCK(attr) ((attr)->u.blk) +#define DW_SND(attr) ((attr)->u.snd) +#define DW_ADDR(attr) ((attr)->u.addr) +#define DW_SIGNATURE(attr) ((attr)->u.signature) + +/* Read the given attribute value as an address, taking the attribute's + form into account. */ + +extern CORE_ADDR attr_value_as_address (struct attribute *attr); + +/* Check if the attribute's form is a DW_FORM_block* + if so return true else false. */ + +extern int attr_form_is_block (const struct attribute *attr); + +/* Return non-zero if ATTR's value is a section offset --- classes + lineptr, loclistptr, macptr or rangelistptr --- or zero, otherwise. + You may use DW_UNSND (attr) to retrieve such offsets. + + Section 7.5.4, "Attribute Encodings", explains that no attribute + may have a value that belongs to more than one of these classes; it + would be ambiguous if we did, because we use the same forms for all + of them. */ + +extern int attr_form_is_section_offset (const struct attribute *attr); + +/* Return non-zero if ATTR's value falls in the 'constant' class, or + zero otherwise. When this function returns true, you can apply + dwarf2_get_attr_constant_value to it. + + However, note that for some attributes you must check + attr_form_is_section_offset before using this test. DW_FORM_data4 + and DW_FORM_data8 are members of both the constant class, and of + the classes that contain offsets into other debug sections + (lineptr, loclistptr, macptr or rangelistptr). The DWARF spec says + that, if an attribute's can be either a constant or one of the + section offset classes, DW_FORM_data4 and DW_FORM_data8 should be + taken as section offsets, not constants. + + DW_FORM_data16 is not considered as dwarf2_get_attr_constant_value + cannot handle that. */ + +extern int attr_form_is_constant (const struct attribute *attr); + +/* DW_ADDR is always stored already as sect_offset; despite for the forms + besides DW_FORM_ref_addr it is stored as cu_offset in the DWARF file. */ + +extern int attr_form_is_ref (const struct attribute *attr); + +#endif /* GDB_DWARF2_ATTRIBUTE_H */ diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 59ed073a994..02bf1ef3d44 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -31,6 +31,7 @@ #include "defs.h" #include "dwarf2read.h" #include "dwarf2/abbrev.h" +#include "dwarf2/attribute.h" #include "dwarf-index-cache.h" #include "dwarf-index-common.h" #include "dwarf2/leb.h" @@ -1233,29 +1234,6 @@ struct partial_die_info : public allocate_on_obstack } }; -/* Attributes have a name and a value. */ -struct attribute - { - ENUM_BITFIELD(dwarf_attribute) name : 16; - ENUM_BITFIELD(dwarf_form) form : 15; - - /* Has DW_STRING already been updated by dwarf2_canonicalize_name? This - field should be in u.str (existing only for DW_STRING) but it is kept - here for better struct attribute alignment. */ - unsigned int string_is_canonical : 1; - - union - { - const char *str; - struct dwarf_block *blk; - ULONGEST unsnd; - LONGEST snd; - CORE_ADDR addr; - ULONGEST signature; - } - u; - }; - /* This data structure holds a complete die structure. */ struct die_info { @@ -1292,25 +1270,6 @@ struct die_info struct attribute attrs[1]; }; -/* Get at parts of an attribute structure. */ - -#define DW_STRING(attr) ((attr)->u.str) -#define DW_STRING_IS_CANONICAL(attr) ((attr)->string_is_canonical) -#define DW_UNSND(attr) ((attr)->u.unsnd) -#define DW_BLOCK(attr) ((attr)->u.blk) -#define DW_SND(attr) ((attr)->u.snd) -#define DW_ADDR(attr) ((attr)->u.addr) -#define DW_SIGNATURE(attr) ((attr)->u.signature) - -/* Blocks are a bunch of untyped bytes. */ -struct dwarf_block - { - size_t size; - - /* Valid only if SIZE is not zero. */ - const gdb_byte *data; - }; - /* FIXME: We might want to set this from BFD via bfd_arch_bits_per_byte, but this would require a corresponding change in unpack_field_as_long and friends. */ @@ -1780,14 +1739,6 @@ static struct die_info *dwarf_alloc_die (struct dwarf2_cu *, int); static void dwarf_decode_macros (struct dwarf2_cu *, unsigned int, int); -static int attr_form_is_block (const struct attribute *); - -static int attr_form_is_section_offset (const struct attribute *); - -static int attr_form_is_constant (const struct attribute *); - -static int attr_form_is_ref (const struct attribute *); - static void fill_in_loclist_baton (struct dwarf2_cu *cu, struct dwarf2_loclist_baton *baton, const struct attribute *attr); @@ -2050,37 +2001,6 @@ line_header_eq_voidp (const void *item_lhs, const void *item_rhs) -/* Read the given attribute value as an address, taking the attribute's - form into account. */ - -static CORE_ADDR -attr_value_as_address (struct attribute *attr) -{ - CORE_ADDR addr; - - if (attr->form != DW_FORM_addr && attr->form != DW_FORM_addrx - && attr->form != DW_FORM_GNU_addr_index) - { - /* Aside from a few clearly defined exceptions, attributes that - contain an address must always be in DW_FORM_addr form. - Unfortunately, some compilers happen to be violating this - requirement by encoding addresses using other forms, such - as DW_FORM_data4 for example. For those broken compilers, - we try to do our best, without any guarantee of success, - to interpret the address correctly. It would also be nice - to generate a complaint, but that would require us to maintain - a list of legitimate cases where a non-address form is allowed, - as well as update callers to pass in at least the CU's DWARF - version. This is more overhead than what we're willing to - expand for a pretty rare case. */ - addr = DW_UNSND (attr); - } - else - addr = DW_ADDR (attr); - - return addr; -} - /* See declaration. */ dwarf2_per_objfile::dwarf2_per_objfile (struct objfile *objfile_, @@ -24814,93 +24734,6 @@ dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset, include_hash.get ()); } -/* Check if the attribute's form is a DW_FORM_block* - if so return true else false. */ - -static int -attr_form_is_block (const struct attribute *attr) -{ - return (attr == NULL ? 0 : - attr->form == DW_FORM_block1 - || attr->form == DW_FORM_block2 - || attr->form == DW_FORM_block4 - || attr->form == DW_FORM_block - || attr->form == DW_FORM_exprloc); -} - -/* Return non-zero if ATTR's value is a section offset --- classes - lineptr, loclistptr, macptr or rangelistptr --- or zero, otherwise. - You may use DW_UNSND (attr) to retrieve such offsets. - - Section 7.5.4, "Attribute Encodings", explains that no attribute - may have a value that belongs to more than one of these classes; it - would be ambiguous if we did, because we use the same forms for all - of them. */ - -static int -attr_form_is_section_offset (const struct attribute *attr) -{ - return (attr->form == DW_FORM_data4 - || attr->form == DW_FORM_data8 - || attr->form == DW_FORM_sec_offset); -} - -/* Return non-zero if ATTR's value falls in the 'constant' class, or - zero otherwise. When this function returns true, you can apply - dwarf2_get_attr_constant_value to it. - - However, note that for some attributes you must check - attr_form_is_section_offset before using this test. DW_FORM_data4 - and DW_FORM_data8 are members of both the constant class, and of - the classes that contain offsets into other debug sections - (lineptr, loclistptr, macptr or rangelistptr). The DWARF spec says - that, if an attribute's can be either a constant or one of the - section offset classes, DW_FORM_data4 and DW_FORM_data8 should be - taken as section offsets, not constants. - - DW_FORM_data16 is not considered as dwarf2_get_attr_constant_value - cannot handle that. */ - -static int -attr_form_is_constant (const struct attribute *attr) -{ - switch (attr->form) - { - case DW_FORM_sdata: - case DW_FORM_udata: - case DW_FORM_data1: - case DW_FORM_data2: - case DW_FORM_data4: - case DW_FORM_data8: - case DW_FORM_implicit_const: - return 1; - default: - return 0; - } -} - - -/* DW_ADDR is always stored already as sect_offset; despite for the forms - besides DW_FORM_ref_addr it is stored as cu_offset in the DWARF file. */ - -static int -attr_form_is_ref (const struct attribute *attr) -{ - switch (attr->form) - { - case DW_FORM_ref_addr: - case DW_FORM_ref1: - case DW_FORM_ref2: - case DW_FORM_ref4: - case DW_FORM_ref8: - case DW_FORM_ref_udata: - case DW_FORM_GNU_ref_alt: - return 1; - default: - return 0; - } -} - /* Return the .debug_loc section to use for CU. For DWO files use .debug_loc.dwo. */ -- 2.30.2