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  <tom@tromey.com>

	* 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
This commit is contained in:
Tom Tromey 2020-02-08 13:40:54 -07:00
parent 3054dd5470
commit 162dce5526
5 changed files with 253 additions and 168 deletions

View File

@ -1,3 +1,14 @@
2020-02-08 Tom Tromey <tom@tromey.com>
* 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 <tom@tromey.com>
* dwarf2read.c (abbrev_table_up, struct abbrev_info)

View File

@ -1003,6 +1003,7 @@ COMMON_SFILES = \
dwarf2loc.c \
dwarf2read.c \
dwarf2/abbrev.c \
dwarf2/attribute.c \
dwarf2/leb.c \
dwarf2/section.c \
eval.c \

122
gdb/dwarf2/attribute.c Normal file
View File

@ -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 <http://www.gnu.org/licenses/>. */
#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;
}
}

118
gdb/dwarf2/attribute.h Normal file
View File

@ -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 <http://www.gnu.org/licenses/>. */
#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 */

View File

@ -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. */