aboutsummaryrefslogtreecommitdiff
path: root/gold/attributes.h
blob: 20f6b38cc4dde12966b2d0c544cddc5da9404968 (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
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
// attributes.h -- object attributes for gold   -*- C++ -*-

// Copyright (C) 2009-2017 Free Software Foundation, Inc.
// Written by Doug Kwan <dougkwan@google.com>.
// This file contains code adapted from BFD.

// This file is part of gold.

// 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, write to the Free Software
// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
// MA 02110-1301, USA.

// Handle object attributes.

#ifndef GOLD_ATTRIBUTES_H
#define GOLD_ATTRIBUTES_H

#include <map>

#include "parameters.h"
#include "target.h"
#include "output.h"
#include "reduced_debug_output.h"

namespace gold
{

// Object attribute values.  The attribute tag is not stored in this object.

class Object_attribute
{
 public:
  // The value of an object attribute.  The type indicates whether the
  // attribute holds and integer, a string, or both.  It can also indicate that
  // there can be no default (i.e. all values must be written to file, even
  // zero).
  enum
  {
    ATTR_TYPE_FLAG_INT_VAL = (1 << 0),
    ATTR_TYPE_FLAG_STR_VAL = (1 << 1),
    ATTR_TYPE_FLAG_NO_DEFAULT = (1 << 2)
  };

  // Object attributes may either be defined by the processor ABI, index
  // OBJ_ATTR_PROC in the *_obj_attributes arrays, or be GNU-specific
  // (and possibly also processor-specific), index OBJ_ATTR_GNU.
  enum
  {
    OBJ_ATTR_PROC,
    OBJ_ATTR_GNU,
    OBJ_ATTR_FIRST = OBJ_ATTR_PROC,
    OBJ_ATTR_LAST = OBJ_ATTR_GNU
  };

  // The following object attribute tags are taken as generic, for all
  // targets and for "gnu" where there is no target standard. 
  enum
  {
    Tag_NULL = 0,
    Tag_File = 1,
    Tag_Section = 2,
    Tag_Symbol = 3,
    Tag_compatibility = 32
  };

  Object_attribute()
   : type_(0), int_value_(0), string_value_()
  { }

  // Copying constructor.  We need to implement this to copy the string value.
  Object_attribute(const Object_attribute& oa)
   : type_(oa.type_), int_value_(oa.int_value_), string_value_(oa.string_value_)
  { }

  ~Object_attribute()
  { }

  // Assignment operator.  We need to implement this to copy the string value.
  Object_attribute&
  operator=(const Object_attribute& source)
  {
    this->type_ = source.type_;
    this->int_value_ = source.int_value_;
    this->string_value_ = source.string_value_;
    return *this;
  }

  // Return attribute type.
  int
  type() const
  { return this->type_; }

  // Set attribute type.
  void
  set_type(int type)
  { this->type_ = type; }

  // Return integer value.
  unsigned int
  int_value() const
  { return this->int_value_; }

  // Set integer value.
  void
  set_int_value(unsigned int i)
  { this->int_value_ = i; }

  // Return string value.
  const std::string&
  string_value() const
  { return this->string_value_; }

  // Set string value.
  void
  set_string_value(const std::string& s)
  { this->string_value_ = s; }

  void
  set_string_value(const char* s)
  { this->string_value_ = s; }

  // Whether attribute type has integer value.
  static bool
  attribute_type_has_int_value(int type)
  { return (type & ATTR_TYPE_FLAG_INT_VAL) != 0; }

  // Whether attribute type has string value.
  static bool
  attribute_type_has_string_value(int type)
  { return (type & ATTR_TYPE_FLAG_STR_VAL) != 0; }

  // Whether attribute type has no default value.
  static bool
  attribute_type_has_no_default(int type)
  { return (type & ATTR_TYPE_FLAG_NO_DEFAULT) != 0; }

  // Whether this has default value (0/"").
  bool
  is_default_attribute() const;

  // Return ULEB128 encoded size of tag and attribute.  
  size_t
  size(int tag) const;

  // Whether this matches another object attribute in merging.
  bool
  matches(const Object_attribute& oa) const;
  
  // Write to attribute with tag to BUFFER.
  void
  write(int tag, std::vector<unsigned char>* buffer) const;

  // Determine what arguments an attribute tag takes.
  static int
  arg_type(int vendor, int tag)
  {
    switch (vendor)
      {
      case OBJ_ATTR_PROC:
	return parameters->target().attribute_arg_type(tag);
      case OBJ_ATTR_GNU:
	return Object_attribute::gnu_arg_type(tag);
      default:
	gold_unreachable();
     }
  }

 private:
  // Determine whether a GNU object attribute tag takes an integer, a
  // string or both.  */
  static int
  gnu_arg_type(int tag)
  {
    // Except for Tag_compatibility, for GNU attributes we follow the
    // same rule ARM ones > 32 follow: odd-numbered tags take strings
    // and even-numbered tags take integers.  In addition, tag & 2 is
    // nonzero for architecture-independent tags and zero for
    // architecture-dependent ones.
    if (tag == Object_attribute::Tag_compatibility)
      return ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_STR_VAL;
    else
      return (tag & 1) != 0 ? ATTR_TYPE_FLAG_STR_VAL : ATTR_TYPE_FLAG_INT_VAL;
  }

  // Attribute type.
  int type_;
  // Integer value.
  int int_value_;
  // String value.
  std::string string_value_;
};

// This class contains attributes of a particular vendor.

class Vendor_object_attributes
{
 public:
  // The maximum number of known object attributes for any target.
  static const int NUM_KNOWN_ATTRIBUTES = 71;

  Vendor_object_attributes(int vendor)
    : vendor_(vendor), other_attributes_() 
  { }

  // Copying constructor.
  Vendor_object_attributes(const Vendor_object_attributes&);

  ~Vendor_object_attributes()
  {
    for (Other_attributes::iterator p = this->other_attributes_.begin();
	 p != this->other_attributes_.end();
	 ++p)
      delete p->second;
  }

  // Size of this in number of bytes.
  size_t
  size() const;
  
  // Name of this written vendor subsection.
  const char*
  name() const
  {
    return (this->vendor_ == Object_attribute::OBJ_ATTR_PROC
	    ? parameters->target().attributes_vendor()
	    : "gnu");
  }

  // Return an array of known attributes.
  Object_attribute*
  known_attributes()
  { return &this->known_attributes_[0]; }

  const Object_attribute*
  known_attributes() const
  { return &this->known_attributes_[0]; }

  typedef std::map<int, Object_attribute*> Other_attributes;

  // Return attributes other than the known ones.
  Other_attributes*
  other_attributes()
  { return &this->other_attributes_; }

  const Other_attributes*
  other_attributes() const
  { return &this->other_attributes_; }

  // Return a new attribute associated with TAG.
  Object_attribute*
  new_attribute(int tag);

  // Get an attribute
  Object_attribute*
  get_attribute(int tag);

  const Object_attribute*
  get_attribute(int tag) const;

  // Write to BUFFER.
  void
  write(std::vector<unsigned char>* buffer) const;

 private:
  // Vendor of the object attributes.
  int vendor_;
  // Attributes with known tags.  There are store in an array for fast
  // access.
  Object_attribute known_attributes_[NUM_KNOWN_ATTRIBUTES];
  // Attributes with known tags.  There are stored in a sorted container.
  Other_attributes other_attributes_;
};

// This class contains contents of an attributes section.

class Attributes_section_data
{
 public:
  // Construct an Attributes_section_data object by parsing section contents
  // in VIEW of SIZE.
  Attributes_section_data(const unsigned char* view, section_size_type size);

  // Copying constructor.
  Attributes_section_data(const Attributes_section_data& asd)
  {
    for (int vendor = Object_attribute::OBJ_ATTR_FIRST;
	 vendor <= Object_attribute::OBJ_ATTR_LAST;
	 ++vendor)
      this->vendor_object_attributes_[vendor] =
	new Vendor_object_attributes(*asd.vendor_object_attributes_[vendor]);
  }
  
  ~Attributes_section_data()
  {
    for (int vendor = Object_attribute::OBJ_ATTR_FIRST;
	 vendor <= Object_attribute::OBJ_ATTR_LAST;
	 ++vendor)
      delete this->vendor_object_attributes_[vendor];
  }
 
  // Return the size of this as number of bytes.
  size_t
  size() const;

  // Return an array of known attributes.
  Object_attribute*
  known_attributes(int vendor)
  {
    gold_assert(vendor >= OBJ_ATTR_FIRST && vendor <= OBJ_ATTR_LAST);
    return this->vendor_object_attributes_[vendor]->known_attributes();
  }

  const Object_attribute*
  known_attributes(int vendor) const
  {
    gold_assert(vendor >= OBJ_ATTR_FIRST && vendor <= OBJ_ATTR_LAST);
    return this->vendor_object_attributes_[vendor]->known_attributes();
  }

  // Return the other attributes.
  Vendor_object_attributes::Other_attributes*
  other_attributes(int vendor)
  {
    gold_assert(vendor >= OBJ_ATTR_FIRST && vendor <= OBJ_ATTR_LAST);
    return this->vendor_object_attributes_[vendor]->other_attributes();
  }

  // Return the other attributes.
  const Vendor_object_attributes::Other_attributes*
  other_attributes(int vendor) const
  {
    gold_assert(vendor >= OBJ_ATTR_FIRST && vendor <= OBJ_ATTR_LAST);
    return this->vendor_object_attributes_[vendor]->other_attributes();
  }

  // Return an attribute.
  Object_attribute*
  get_attribute(int vendor, int tag)
  {
    gold_assert(vendor >= OBJ_ATTR_FIRST && vendor <= OBJ_ATTR_LAST);
    return this->vendor_object_attributes_[vendor]->get_attribute(tag);
  }
  
  const Object_attribute*
  get_attribute(int vendor, int tag) const
  {
    gold_assert(vendor >= OBJ_ATTR_FIRST && vendor <= OBJ_ATTR_LAST);
    return this->vendor_object_attributes_[vendor]->get_attribute(tag);
  }
  
  // Merge target-independent attributes from another Attributes_section_data
  // of an object called NAME.
  void
  merge(const char* name, const Attributes_section_data* pasd);

  // Write to byte stream in an unsigned char vector.
  void
  write(std::vector<unsigned char>*) const;

 private:
  // For convenience.
  static const int OBJ_ATTR_FIRST = Object_attribute::OBJ_ATTR_FIRST;
  static const int OBJ_ATTR_LAST = Object_attribute::OBJ_ATTR_LAST;

  // Vendor object attributes.
  Vendor_object_attributes* vendor_object_attributes_[OBJ_ATTR_LAST+1];
};

// This class is used for writing out an Attribute_section_data.

class Output_attributes_section_data : public Output_section_data
{
 public:
  Output_attributes_section_data(const Attributes_section_data& asd)
    : Output_section_data(1), attributes_section_data_(asd)
  { }

 protected:
  // Write to a map file.
  void
  do_print_to_mapfile(Mapfile* mapfile) const
  { mapfile->print_output_data(this, _("** attributes")); }

  // Write the data to the output file.
  void
  do_write(Output_file*);
  
  // Set final data size.
  void
  set_final_data_size()
  { this->set_data_size(attributes_section_data_.size()); }

 private:
  // Attributes_section_data corresponding to this.
  const Attributes_section_data& attributes_section_data_;
};

} // End namespace gold.

#endif	// !defined(GOLD_ATTRIBUTES_H)