Commit | Line | Data |
---|---|---|
4f787271 DK |
1 | // attributes.h -- object attributes for gold -*- C++ -*- |
2 | ||
2571583a | 3 | // Copyright (C) 2009-2017 Free Software Foundation, Inc. |
4f787271 DK |
4 | // Written by Doug Kwan <dougkwan@google.com>. |
5 | // This file contains code adapted from BFD. | |
6 | ||
7 | // This file is part of gold. | |
8 | ||
9 | // This program is free software; you can redistribute it and/or modify | |
10 | // it under the terms of the GNU General Public License as published by | |
11 | // the Free Software Foundation; either version 3 of the License, or | |
12 | // (at your option) any later version. | |
13 | ||
14 | // This program is distributed in the hope that it will be useful, | |
15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | // GNU General Public License for more details. | |
18 | ||
19 | // You should have received a copy of the GNU General Public License | |
20 | // along with this program; if not, write to the Free Software | |
21 | // Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, | |
22 | // MA 02110-1301, USA. | |
23 | ||
24 | // Handle object attributes. | |
25 | ||
26 | #ifndef GOLD_ATTRIBUTES_H | |
27 | #define GOLD_ATTRIBUTES_H | |
28 | ||
29 | #include <map> | |
30 | ||
31 | #include "parameters.h" | |
32 | #include "target.h" | |
33 | #include "output.h" | |
34 | #include "reduced_debug_output.h" | |
35 | ||
36 | namespace gold | |
37 | { | |
38 | ||
39 | // Object attribute values. The attribute tag is not stored in this object. | |
40 | ||
41 | class Object_attribute | |
42 | { | |
43 | public: | |
44 | // The value of an object attribute. The type indicates whether the | |
45 | // attribute holds and integer, a string, or both. It can also indicate that | |
46 | // there can be no default (i.e. all values must be written to file, even | |
47 | // zero). | |
48 | enum | |
49 | { | |
50 | ATTR_TYPE_FLAG_INT_VAL = (1 << 0), | |
51 | ATTR_TYPE_FLAG_STR_VAL = (1 << 1), | |
52 | ATTR_TYPE_FLAG_NO_DEFAULT = (1 << 2) | |
53 | }; | |
54 | ||
55 | // Object attributes may either be defined by the processor ABI, index | |
56 | // OBJ_ATTR_PROC in the *_obj_attributes arrays, or be GNU-specific | |
57 | // (and possibly also processor-specific), index OBJ_ATTR_GNU. | |
58 | enum | |
59 | { | |
60 | OBJ_ATTR_PROC, | |
61 | OBJ_ATTR_GNU, | |
62 | OBJ_ATTR_FIRST = OBJ_ATTR_PROC, | |
63 | OBJ_ATTR_LAST = OBJ_ATTR_GNU | |
64 | }; | |
65 | ||
66 | // The following object attribute tags are taken as generic, for all | |
67 | // targets and for "gnu" where there is no target standard. | |
68 | enum | |
69 | { | |
70 | Tag_NULL = 0, | |
71 | Tag_File = 1, | |
72 | Tag_Section = 2, | |
73 | Tag_Symbol = 3, | |
74 | Tag_compatibility = 32 | |
75 | }; | |
76 | ||
77 | Object_attribute() | |
78 | : type_(0), int_value_(0), string_value_() | |
79 | { } | |
80 | ||
81 | // Copying constructor. We need to implement this to copy the string value. | |
82 | Object_attribute(const Object_attribute& oa) | |
83 | : type_(oa.type_), int_value_(oa.int_value_), string_value_(oa.string_value_) | |
84 | { } | |
85 | ||
86 | ~Object_attribute() | |
87 | { } | |
88 | ||
89 | // Assignment operator. We need to implement this to copy the string value. | |
90 | Object_attribute& | |
91 | operator=(const Object_attribute& source) | |
92 | { | |
93 | this->type_ = source.type_; | |
94 | this->int_value_ = source.int_value_; | |
95 | this->string_value_ = source.string_value_; | |
96 | return *this; | |
97 | } | |
98 | ||
99 | // Return attribute type. | |
100 | int | |
101 | type() const | |
102 | { return this->type_; } | |
103 | ||
104 | // Set attribute type. | |
105 | void | |
2ea97941 ILT |
106 | set_type(int type) |
107 | { this->type_ = type; } | |
4f787271 DK |
108 | |
109 | // Return integer value. | |
110 | unsigned int | |
111 | int_value() const | |
112 | { return this->int_value_; } | |
113 | ||
114 | // Set integer value. | |
115 | void | |
116 | set_int_value(unsigned int i) | |
117 | { this->int_value_ = i; } | |
118 | ||
119 | // Return string value. | |
120 | const std::string& | |
121 | string_value() const | |
122 | { return this->string_value_; } | |
123 | ||
124 | // Set string value. | |
125 | void | |
126 | set_string_value(const std::string& s) | |
127 | { this->string_value_ = s; } | |
128 | ||
129 | void | |
130 | set_string_value(const char* s) | |
131 | { this->string_value_ = s; } | |
132 | ||
133 | // Whether attribute type has integer value. | |
134 | static bool | |
135 | attribute_type_has_int_value(int type) | |
136 | { return (type & ATTR_TYPE_FLAG_INT_VAL) != 0; } | |
137 | ||
138 | // Whether attribute type has string value. | |
139 | static bool | |
140 | attribute_type_has_string_value(int type) | |
141 | { return (type & ATTR_TYPE_FLAG_STR_VAL) != 0; } | |
142 | ||
143 | // Whether attribute type has no default value. | |
144 | static bool | |
145 | attribute_type_has_no_default(int type) | |
146 | { return (type & ATTR_TYPE_FLAG_NO_DEFAULT) != 0; } | |
147 | ||
148 | // Whether this has default value (0/""). | |
149 | bool | |
150 | is_default_attribute() const; | |
151 | ||
152 | // Return ULEB128 encoded size of tag and attribute. | |
153 | size_t | |
154 | size(int tag) const; | |
155 | ||
156 | // Whether this matches another object attribute in merging. | |
157 | bool | |
158 | matches(const Object_attribute& oa) const; | |
159 | ||
160 | // Write to attribute with tag to BUFFER. | |
161 | void | |
162 | write(int tag, std::vector<unsigned char>* buffer) const; | |
163 | ||
164 | // Determine what arguments an attribute tag takes. | |
165 | static int | |
ca09d69a | 166 | arg_type(int vendor, int tag) |
4f787271 DK |
167 | { |
168 | switch (vendor) | |
169 | { | |
170 | case OBJ_ATTR_PROC: | |
171 | return parameters->target().attribute_arg_type(tag); | |
172 | case OBJ_ATTR_GNU: | |
173 | return Object_attribute::gnu_arg_type(tag); | |
174 | default: | |
175 | gold_unreachable(); | |
176 | } | |
177 | } | |
178 | ||
179 | private: | |
180 | // Determine whether a GNU object attribute tag takes an integer, a | |
181 | // string or both. */ | |
182 | static int | |
ca09d69a | 183 | gnu_arg_type(int tag) |
4f787271 DK |
184 | { |
185 | // Except for Tag_compatibility, for GNU attributes we follow the | |
186 | // same rule ARM ones > 32 follow: odd-numbered tags take strings | |
187 | // and even-numbered tags take integers. In addition, tag & 2 is | |
188 | // nonzero for architecture-independent tags and zero for | |
189 | // architecture-dependent ones. | |
190 | if (tag == Object_attribute::Tag_compatibility) | |
191 | return ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_STR_VAL; | |
192 | else | |
193 | return (tag & 1) != 0 ? ATTR_TYPE_FLAG_STR_VAL : ATTR_TYPE_FLAG_INT_VAL; | |
194 | } | |
195 | ||
196 | // Attribute type. | |
197 | int type_; | |
198 | // Integer value. | |
199 | int int_value_; | |
200 | // String value. | |
201 | std::string string_value_; | |
202 | }; | |
203 | ||
204 | // This class contains attributes of a particular vendor. | |
205 | ||
206 | class Vendor_object_attributes | |
207 | { | |
208 | public: | |
209 | // The maximum number of known object attributes for any target. | |
210 | static const int NUM_KNOWN_ATTRIBUTES = 71; | |
211 | ||
212 | Vendor_object_attributes(int vendor) | |
213 | : vendor_(vendor), other_attributes_() | |
214 | { } | |
215 | ||
216 | // Copying constructor. | |
217 | Vendor_object_attributes(const Vendor_object_attributes&); | |
218 | ||
219 | ~Vendor_object_attributes() | |
220 | { | |
221 | for (Other_attributes::iterator p = this->other_attributes_.begin(); | |
222 | p != this->other_attributes_.end(); | |
223 | ++p) | |
224 | delete p->second; | |
225 | } | |
226 | ||
227 | // Size of this in number of bytes. | |
228 | size_t | |
229 | size() const; | |
230 | ||
231 | // Name of this written vendor subsection. | |
232 | const char* | |
233 | name() const | |
234 | { | |
235 | return (this->vendor_ == Object_attribute::OBJ_ATTR_PROC | |
236 | ? parameters->target().attributes_vendor() | |
237 | : "gnu"); | |
238 | } | |
239 | ||
240 | // Return an array of known attributes. | |
241 | Object_attribute* | |
242 | known_attributes() | |
243 | { return &this->known_attributes_[0]; } | |
244 | ||
245 | const Object_attribute* | |
246 | known_attributes() const | |
247 | { return &this->known_attributes_[0]; } | |
248 | ||
249 | typedef std::map<int, Object_attribute*> Other_attributes; | |
250 | ||
251 | // Return attributes other than the known ones. | |
252 | Other_attributes* | |
253 | other_attributes() | |
254 | { return &this->other_attributes_; } | |
255 | ||
256 | const Other_attributes* | |
257 | other_attributes() const | |
258 | { return &this->other_attributes_; } | |
259 | ||
9b547ce6 | 260 | // Return a new attribute associated with TAG. |
4f787271 DK |
261 | Object_attribute* |
262 | new_attribute(int tag); | |
263 | ||
264 | // Get an attribute | |
265 | Object_attribute* | |
266 | get_attribute(int tag); | |
267 | ||
268 | const Object_attribute* | |
269 | get_attribute(int tag) const; | |
270 | ||
271 | // Write to BUFFER. | |
272 | void | |
273 | write(std::vector<unsigned char>* buffer) const; | |
274 | ||
275 | private: | |
276 | // Vendor of the object attributes. | |
277 | int vendor_; | |
278 | // Attributes with known tags. There are store in an array for fast | |
279 | // access. | |
280 | Object_attribute known_attributes_[NUM_KNOWN_ATTRIBUTES]; | |
281 | // Attributes with known tags. There are stored in a sorted container. | |
282 | Other_attributes other_attributes_; | |
283 | }; | |
284 | ||
285 | // This class contains contents of an attributes section. | |
286 | ||
287 | class Attributes_section_data | |
288 | { | |
289 | public: | |
290 | // Construct an Attributes_section_data object by parsing section contents | |
291 | // in VIEW of SIZE. | |
292 | Attributes_section_data(const unsigned char* view, section_size_type size); | |
293 | ||
294 | // Copying constructor. | |
295 | Attributes_section_data(const Attributes_section_data& asd) | |
296 | { | |
297 | for (int vendor = Object_attribute::OBJ_ATTR_FIRST; | |
298 | vendor <= Object_attribute::OBJ_ATTR_LAST; | |
299 | ++vendor) | |
300 | this->vendor_object_attributes_[vendor] = | |
301 | new Vendor_object_attributes(*asd.vendor_object_attributes_[vendor]); | |
302 | } | |
303 | ||
304 | ~Attributes_section_data() | |
305 | { | |
306 | for (int vendor = Object_attribute::OBJ_ATTR_FIRST; | |
307 | vendor <= Object_attribute::OBJ_ATTR_LAST; | |
308 | ++vendor) | |
309 | delete this->vendor_object_attributes_[vendor]; | |
310 | } | |
311 | ||
312 | // Return the size of this as number of bytes. | |
313 | size_t | |
314 | size() const; | |
315 | ||
316 | // Return an array of known attributes. | |
317 | Object_attribute* | |
318 | known_attributes(int vendor) | |
319 | { | |
320 | gold_assert(vendor >= OBJ_ATTR_FIRST && vendor <= OBJ_ATTR_LAST); | |
321 | return this->vendor_object_attributes_[vendor]->known_attributes(); | |
322 | } | |
323 | ||
324 | const Object_attribute* | |
325 | known_attributes(int vendor) const | |
326 | { | |
327 | gold_assert(vendor >= OBJ_ATTR_FIRST && vendor <= OBJ_ATTR_LAST); | |
328 | return this->vendor_object_attributes_[vendor]->known_attributes(); | |
329 | } | |
330 | ||
331 | // Return the other attributes. | |
332 | Vendor_object_attributes::Other_attributes* | |
333 | other_attributes(int vendor) | |
334 | { | |
335 | gold_assert(vendor >= OBJ_ATTR_FIRST && vendor <= OBJ_ATTR_LAST); | |
336 | return this->vendor_object_attributes_[vendor]->other_attributes(); | |
337 | } | |
338 | ||
339 | // Return the other attributes. | |
340 | const Vendor_object_attributes::Other_attributes* | |
341 | other_attributes(int vendor) const | |
342 | { | |
343 | gold_assert(vendor >= OBJ_ATTR_FIRST && vendor <= OBJ_ATTR_LAST); | |
344 | return this->vendor_object_attributes_[vendor]->other_attributes(); | |
345 | } | |
346 | ||
347 | // Return an attribute. | |
348 | Object_attribute* | |
349 | get_attribute(int vendor, int tag) | |
350 | { | |
351 | gold_assert(vendor >= OBJ_ATTR_FIRST && vendor <= OBJ_ATTR_LAST); | |
352 | return this->vendor_object_attributes_[vendor]->get_attribute(tag); | |
353 | } | |
354 | ||
355 | const Object_attribute* | |
356 | get_attribute(int vendor, int tag) const | |
357 | { | |
358 | gold_assert(vendor >= OBJ_ATTR_FIRST && vendor <= OBJ_ATTR_LAST); | |
359 | return this->vendor_object_attributes_[vendor]->get_attribute(tag); | |
360 | } | |
361 | ||
362 | // Merge target-independent attributes from another Attributes_section_data | |
363 | // of an object called NAME. | |
364 | void | |
365 | merge(const char* name, const Attributes_section_data* pasd); | |
366 | ||
367 | // Write to byte stream in an unsigned char vector. | |
368 | void | |
369 | write(std::vector<unsigned char>*) const; | |
370 | ||
371 | private: | |
372 | // For convenience. | |
373 | static const int OBJ_ATTR_FIRST = Object_attribute::OBJ_ATTR_FIRST; | |
374 | static const int OBJ_ATTR_LAST = Object_attribute::OBJ_ATTR_LAST; | |
375 | ||
376 | // Vendor object attributes. | |
377 | Vendor_object_attributes* vendor_object_attributes_[OBJ_ATTR_LAST+1]; | |
378 | }; | |
379 | ||
380 | // This class is used for writing out an Attribute_section_data. | |
381 | ||
382 | class Output_attributes_section_data : public Output_section_data | |
383 | { | |
384 | public: | |
385 | Output_attributes_section_data(const Attributes_section_data& asd) | |
386 | : Output_section_data(1), attributes_section_data_(asd) | |
387 | { } | |
388 | ||
389 | protected: | |
5b07cd84 CC |
390 | // Write to a map file. |
391 | void | |
392 | do_print_to_mapfile(Mapfile* mapfile) const | |
393 | { mapfile->print_output_data(this, _("** attributes")); } | |
394 | ||
4f787271 DK |
395 | // Write the data to the output file. |
396 | void | |
397 | do_write(Output_file*); | |
398 | ||
399 | // Set final data size. | |
400 | void | |
401 | set_final_data_size() | |
402 | { this->set_data_size(attributes_section_data_.size()); } | |
403 | ||
404 | private: | |
405 | // Attributes_section_data corresponding to this. | |
406 | const Attributes_section_data& attributes_section_data_; | |
407 | }; | |
408 | ||
409 | } // End namespace gold. | |
410 | ||
411 | #endif // !defined(GOLD_ATTRIBUTES_H) |