summaryrefslogtreecommitdiff
path: root/dwarflint/dwarf_gnu.cc
blob: 97f28d050138737ae128f4b6d0a2aab1a75aab23 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
/* Pedantic checking of DWARF files
   Copyright (C) 2010, 2011 Red Hat, Inc.
   This file is part of elfutils.

   This file 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.

   elfutils 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 "dwarf_version-imp.hh"
#include "../libdw/dwarf.h"

namespace
{
  struct dwarf_gnu_attributes
    : public attribute_table
  {
    void unused (__attribute__ ((unused)) attribute const &attrib) const {}
    dwarf_gnu_attributes ()
    {
      // It's rather hard to find any reference on some of the GNU
      // extensions.  So we simply mark these with unused.

      // The MIPS documentation claims that these are "apparently only
      // output in DWARF1, not DWARF2".  I found nothing particular
      // about how these are used.
      unused (const_attribute (DW_AT_sf_names));
      unused (const_attribute (DW_AT_src_info));
      unused (const_attribute (DW_AT_mac_info));
      unused (const_attribute (DW_AT_src_coords));
      unused (const_attribute (DW_AT_body_begin));
      unused (const_attribute (DW_AT_body_end));

      add (flag_attribute (DW_AT_GNU_vector));

      // xxx these are glass cl_GNU_mutexlistptr.  data4 and data8 are
      // supposed to have this class.  So how do we smuggle this class
      // to whatever DW_FORM_data4 and DW_FORM_data8 have in current
      // version?  For now, just claim it's plain old constant.
      // http://gcc.gnu.org/wiki/ThreadSafetyAnnotationsInDWARF
      add (const_attribute (DW_AT_GNU_guarded_by));
      add (const_attribute (DW_AT_GNU_pt_guarded_by));
      add (const_attribute (DW_AT_GNU_guarded));
      add (const_attribute (DW_AT_GNU_pt_guarded));
      add (const_attribute (DW_AT_GNU_locks_excluded));
      add (const_attribute (DW_AT_GNU_exclusive_locks_required));
      add (const_attribute (DW_AT_GNU_shared_locks_required));

      // Contains a shallower 8-byte signature of the type described
      // in the type unit.  This is nominally a const_attribute, but
      // we do the checking ourselves in form_allowed.
      // http://gcc.gnu.org/wiki/DwarfSeparateTypeInfo
      add (const_attribute (DW_AT_GNU_odr_signature));

      // http://gcc.gnu.org/wiki/TemplateParmsDwarf
      add (string_attribute (DW_AT_GNU_template_name));

      // GNU extensions for representation of call sites
      // http://www.dwarfstd.org/ShowIssue.php?issue=100909.2
      add (attribute (DW_AT_GNU_call_site_value, cl_exprloc));
      add (attribute (DW_AT_GNU_call_site_data_value, cl_exprloc));
      add (attribute (DW_AT_GNU_call_site_target, cl_exprloc));
      add (attribute (DW_AT_GNU_call_site_target_clobbered, cl_exprloc));
      add (flag_attribute (DW_AT_GNU_tail_call));
      add (flag_attribute (DW_AT_GNU_all_tail_call_sites));
      add (flag_attribute (DW_AT_GNU_all_call_sites));
      add (flag_attribute (DW_AT_GNU_all_source_call_sites));
    }
  };

  struct dwarf_gnu_ext_t
    : public std_dwarf
  {
    dwarf_gnu_ext_t ()
      : std_dwarf (dwarf_gnu_attributes (), form_table ())
    {}

    virtual bool
    form_allowed (attribute const *attr, form const *form) const
    {
      // Without -gstrict-dwarf gcc allows usage of attributes from
      // later versions. One strange case is DW_AT_ranges in version 2
      // since that version doesn't actually define a rangelistptr
      // class. So we just allow data4 or data8 here.
      if (attr->name () == DW_AT_ranges)
	{
	  form_width_t width = form->width (NULL);
	  return (form->classes ()[cl_constant]
		  && (width == fw_4 || width == fw_8));
	}

      // upper_bound is allowed to also be a block (dwarf3 in dwarf2).
      if (attr->name () == DW_AT_upper_bound)
	return form->classes ()[cl_block];

      if (attr->name () == DW_AT_GNU_odr_signature)
	return form->classes ()[cl_constant] && form->width (NULL) == fw_8;
      else
	return std_dwarf::form_allowed (attr, form);
    }
  };
}

dwarf_version const *
dwarf_gnu_ext ()
{
  static dwarf_gnu_ext_t dw;
  return &dw;
}