summaryrefslogtreecommitdiff
path: root/dwarflint/dwarf_version.hh
blob: c8a0e6a31f0c52f5e007b78adc150f048addc8e8 (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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
/* Dwarf version tables.

   Copyright (C) 2009, 2010, 2011 Red Hat, Inc.
   This file is part of Red Hat elfutils.

   Red Hat elfutils 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; version 2 of the License.

   Red Hat 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 Red Hat elfutils; if not, write to the Free Software Foundation,
   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.

   Red Hat elfutils is an included package of the Open Invention Network.
   An included package of the Open Invention Network is a package for which
   Open Invention Network licensees cross-license their patents.  No patent
   license is granted, either expressly or impliedly, by designation as an
   included package.  Should you wish to participate in the Open Invention
   Network licensing program, please visit www.openinventionnetwork.com
   <http://www.openinventionnetwork.com>.  */

#ifndef DWARFLINT_DWARF_VERSION_HH
#define DWARFLINT_DWARF_VERSION_HH

#include <bitset>
#include <iosfwd>
#include "check_debug_info.ii"
#include "dwarf_version.ii"

enum dw_class
  {
    cl_indirect,
    cl_address,
    cl_block,
    cl_constant,
    cl_exprloc,
    cl_flag,
    cl_reference,
    cl_string,
    cl_loclistptr,
    cl_lineptr,
    cl_macptr,
    cl_rangelistptr,
    max_dw_class
  };

class dw_class_set
  : public std::bitset<max_dw_class>
{
public:
  dw_class_set (dw_class a = max_dw_class, dw_class b = max_dw_class,
		dw_class c = max_dw_class, dw_class d = max_dw_class,
		dw_class e = max_dw_class);
};

enum form_width_t
  {
    fw_0 = 0,
    fw_1 = 1,
    fw_2 = 2,
    fw_4 = 4,
    fw_8 = 8,
    fw_sleb,
    fw_uleb,
    fw_unknown,
  };

/// Special forms for use in DWARF tables.  These never leak out to
/// the user of dwarf_version.
enum form_width_special_t
  {
    fw_offset = fw_unknown + 1,
    fw_address,
  };

enum storage_class_t
  {
    sc_value,
    sc_block,
    sc_string,
  };

class form
{
  int const _m_name;
  dw_class_set const _m_classes;
  int const _m_width;
  storage_class_t const _m_storclass;

public:
  form (int a_name, dw_class_set a_classes,
	form_width_t a_width, storage_class_t a_storclass);

  form (int a_name, dw_class_set a_classes,
	form_width_special_t a_width, storage_class_t a_storclass);

  int
  name () const
  {
    return _m_name;
  }

  /// Answer set of DWARF classes that this form can have.
  dw_class_set const &
  classes () const
  {
    return _m_classes;
  }

  /// Return width of data stored with given form.  CU may be NULL if
  /// you are sure that the form size doesn't depend on bitness of
  /// address_size or offset_size.
  ///
  /// Forms for which width makes no sense (namely those in the
  /// storage class of sc_string) get fw_unknown.  Unknown forms get
  /// an assert.
  ///
  /// Return value is never fw_offset or fw_address.  These get
  /// resolved to fw_4 or fw_8 depending on corresponding value in
  /// CU_HEAD.
  form_width_t width (cu_head const *cu_head) const;

  /// Return storage class of given form.  Closely related to width.
  storage_class_t
  storage_class () const
  {
    return _m_storclass;
  }
};
std::ostream &operator << (std::ostream &os, form const &obj);


class attribute
{
  int const _m_name;
  dw_class_set const _m_classes;

public:
  /// NB this ctor automatically adds cl_indirect to a_classes.
  attribute (int a_name, dw_class_set const &a_classes);

  int
  name () const
  {
    return _m_name;
  }

  /// Answer set of DWARF classes that this form can have.
  dw_class_set const &
  classes () const
  {
    return _m_classes;
  }
};
std::ostream &operator << (std::ostream &os, attribute const &obj);

class dwarf_version
{
public:
  /// Return form object for given form name.  Return NULL for unknown
  /// forms.
  virtual form const *get_form (int form_name) const = 0;

  /// Return attribute object for given attribute name.  Return NULL
  /// for unknown attributes;
  virtual attribute const *get_attribute (int attribute_name) const = 0;

  /// If more than one class ends up as a candidate after the request
  /// to form_class, this function is called to resolve the ambiguity.
  virtual dw_class
  ambiguous_class (__attribute__ ((unused)) form const *form,
		   __attribute__ ((unused)) attribute const *attribute,
		   __attribute__ ((unused)) dw_class_set const &candidates)
    const
  {
    return max_dw_class; // = we don't know.  This will assert back in caller.
  }

  /// Shortcut for get_form (form_name) != NULL.
  bool form_allowed (int form_name) const;

  /// Figure out whether, in given DWARF version, given attribute is
  /// allowed to have given form.
  virtual bool form_allowed (int attribute_name, int form_name) const;

  /// Answer a class of FORM given ATTRIBUTE as a context.  If there's
  /// exactly one candidate class, that's the one answered.  If
  /// there's more, ambiguous_class is called to resolve the
  /// ambiguity.  If there's no candidate, then the request is
  /// invalid, you must validate the form via form_allowed before
  /// calling this.
  dw_class form_class (form const *form, attribute const *attribute) const;


  /// Return dwarf_version object for given DWARF version.
  static dwarf_version const *get (unsigned version)
    __attribute__ ((pure));

  /// Return dwarf_version object for latest supported DWARF version.
  static dwarf_version const *get_latest ()
    __attribute__ ((pure));

  /// Return dwarf_version that represents SOURCE extended with
  /// EXTENSION.  Currently this probably has no use, but one obvious
  /// candidate usage is representing GNU extensions over core DWARF.
  /// Extension can contain overrides of the source dwarf_version
  /// object, and these overrides take precedence.
  static dwarf_version const *extend (dwarf_version const *source,
				      dwarf_version const *extension);
};

/// Check that the form is suitable for the DW_AT_sibling attribute.
enum sibling_form_suitable_t
  {
    sfs_ok,      ///< This form is OK for DW_AT_sibling
    sfs_long,    ///< Global reference form, unnecessary for DW_AT_sibling
    sfs_invalid, ///< This form isn't allowed at DW_AT_sibling
  };
sibling_form_suitable_t sibling_form_suitable (dwarf_version const *ver,
					       int form);

#endif//DWARFLINT_DWARF_VERSION_HH