Commit | Line | Data |
---|---|---|
4f787271 DK |
1 | // attributes.cc -- object attributes for gold |
2 | ||
82704155 | 3 | // Copyright (C) 2009-2019 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 | #include "gold.h" | |
25 | ||
26 | #include <limits> | |
27 | ||
28 | #include "attributes.h" | |
29 | #include "elfcpp.h" | |
30 | #include "target.h" | |
31 | #include "parameters.h" | |
32 | #include "int_encoding.h" | |
33 | ||
34 | namespace gold | |
35 | { | |
36 | ||
37 | // Object_attribute methods. | |
38 | ||
39 | // Return size of attribute encode in ULEB128. | |
40 | ||
41 | size_t | |
42 | Object_attribute::size(int tag) const | |
43 | { | |
44 | // Attributes with default values are not written out. | |
45 | if (this->is_default_attribute()) | |
46 | return 0; | |
47 | ||
2ea97941 | 48 | size_t size = get_length_as_unsigned_LEB_128(tag); |
4f787271 | 49 | if (Object_attribute::attribute_type_has_int_value(this->type_)) |
2ea97941 | 50 | size += get_length_as_unsigned_LEB_128(this->int_value_); |
4f787271 | 51 | if (Object_attribute::attribute_type_has_string_value(this->type_)) |
2ea97941 ILT |
52 | size += this->string_value_.size() + 1; |
53 | return size; | |
4f787271 DK |
54 | } |
55 | ||
56 | // Whether this has the default value (0/""). | |
57 | ||
58 | bool | |
59 | Object_attribute::is_default_attribute() const | |
60 | { | |
61 | if (Object_attribute::attribute_type_has_int_value(this->type_) | |
62 | && this->int_value_ != 0) | |
63 | return false; | |
64 | if (Object_attribute::attribute_type_has_string_value(this->type_) | |
65 | && !this->string_value_.empty()) | |
66 | return false; | |
67 | if (Object_attribute::attribute_type_has_no_default(this->type_)) | |
68 | return false; | |
69 | ||
70 | return true; | |
71 | } | |
72 | ||
73 | // Whether this matches another Object_attribute OA in merging. | |
74 | // Two Object_attributes match if they have the same values. | |
75 | ||
76 | bool | |
77 | Object_attribute::matches(const Object_attribute& oa) const | |
78 | { | |
79 | return ((this->int_value_ != oa.int_value_) | |
80 | && (this->string_value_ == oa.string_value_)); | |
81 | } | |
82 | ||
83 | // Write this with TAG to a BUFFER. | |
84 | ||
85 | void | |
86 | Object_attribute::write( | |
87 | int tag, | |
88 | std::vector<unsigned char>* buffer) const | |
89 | { | |
90 | // No need to write default attributes. | |
91 | if (this->is_default_attribute()) | |
92 | return; | |
93 | ||
94 | // Write tag. | |
95 | write_unsigned_LEB_128(buffer, convert_types<uint64_t, int>(tag)); | |
96 | ||
97 | // Write integer value. | |
98 | if (Object_attribute::attribute_type_has_int_value(this->type_)) | |
99 | write_unsigned_LEB_128(buffer, | |
100 | convert_types<uint64_t, int>(this->int_value_)); | |
101 | ||
102 | // Write string value. | |
103 | if (Object_attribute::attribute_type_has_string_value(this->type_)) | |
104 | { | |
105 | const unsigned char* start = | |
106 | reinterpret_cast<const unsigned char*>(this->string_value_.c_str()); | |
107 | const unsigned char* end = start + this->string_value_.size() + 1; | |
108 | buffer->insert(buffer->end(), start, end); | |
109 | } | |
110 | } | |
111 | ||
112 | // Vendor_object_attributes methods. | |
113 | ||
114 | // Copying constructor. | |
115 | ||
116 | Vendor_object_attributes::Vendor_object_attributes( | |
117 | const Vendor_object_attributes& voa) | |
118 | { | |
119 | this->vendor_ = voa.vendor_; | |
120 | ||
121 | for (int i = 0; i < NUM_KNOWN_ATTRIBUTES; ++i) | |
122 | this->known_attributes_[i] = voa.known_attributes_[i]; | |
123 | ||
124 | // We do not handle attribute deletion. So this must be empty. | |
125 | gold_assert(this->other_attributes_.empty()); | |
126 | ||
127 | for (Other_attributes::const_iterator p = voa.other_attributes_.begin(); | |
128 | p != voa.other_attributes_.end(); | |
129 | ++p) | |
130 | this->other_attributes_[p->first] = new Object_attribute(*(p->second)); | |
131 | } | |
132 | ||
133 | // Size of this in number of bytes. | |
134 | ||
135 | size_t | |
136 | Vendor_object_attributes::size() const | |
137 | { | |
138 | if (this->name() == NULL) | |
139 | return 0; | |
140 | ||
141 | size_t data_size = 0; | |
142 | for (int i = 4; i < NUM_KNOWN_ATTRIBUTES; ++i) | |
143 | data_size += this->known_attributes_[i].size(i); | |
144 | ||
145 | for (Other_attributes::const_iterator p = this->other_attributes_.begin(); | |
146 | p != this->other_attributes_.end(); | |
147 | ++p) | |
148 | data_size += p->second->size(p->first); | |
149 | ||
150 | // <size> <vendor_name> NUL 0x1 <size> | |
151 | return ((data_size != 0 | |
152 | || this->vendor_ == Object_attribute::OBJ_ATTR_PROC) | |
153 | ? data_size + strlen(this->name()) + 2 + 2 * 4 | |
154 | : 0); | |
155 | } | |
156 | ||
157 | // Return a new attribute associated with TAG. | |
158 | ||
159 | Object_attribute* | |
160 | Vendor_object_attributes::new_attribute(int tag) | |
161 | { | |
162 | int type = Object_attribute::arg_type(this->vendor_, tag); | |
163 | ||
164 | if (tag < NUM_KNOWN_ATTRIBUTES) | |
165 | { | |
166 | this->known_attributes_[tag].set_type(type); | |
167 | return &this->known_attributes_[tag]; | |
168 | } | |
169 | else | |
170 | { | |
171 | Object_attribute* attr = new Object_attribute(); | |
172 | ||
173 | // This should be the first time we insert this. | |
174 | std::pair<Other_attributes::iterator, bool> ins = | |
175 | this->other_attributes_.insert(std::make_pair(tag, attr)); | |
176 | gold_assert(ins.second); | |
177 | ||
178 | attr->set_type(type); | |
179 | return attr; | |
180 | } | |
181 | } | |
182 | ||
183 | // Return an attribute associated with TAG. | |
184 | ||
185 | Object_attribute* | |
186 | Vendor_object_attributes::get_attribute(int tag) | |
187 | { | |
188 | if (tag < NUM_KNOWN_ATTRIBUTES) | |
189 | return &this->known_attributes_[tag]; | |
190 | else | |
191 | { | |
192 | Other_attributes::iterator p = | |
193 | this->other_attributes_.find(tag); | |
194 | return p != this->other_attributes_.end() ? p->second : NULL; | |
195 | } | |
196 | } | |
197 | ||
198 | const Object_attribute* | |
199 | Vendor_object_attributes::get_attribute(int tag) const | |
200 | { | |
201 | if (tag < NUM_KNOWN_ATTRIBUTES) | |
202 | return &this->known_attributes_[tag]; | |
203 | else | |
204 | { | |
205 | Other_attributes::const_iterator p = | |
206 | this->other_attributes_.find(tag); | |
207 | return p != this->other_attributes_.end() ? p->second : NULL; | |
208 | } | |
209 | } | |
210 | ||
211 | // Write attributes to BUFFER. | |
212 | ||
213 | void | |
214 | Vendor_object_attributes::write(std::vector<unsigned char>* buffer) const | |
215 | { | |
216 | // Write subsection size. | |
217 | size_t voa_size = this->size(); | |
218 | uint32_t voa_size_as_u32 = convert_types<uint32_t, size_t>(voa_size); | |
219 | insert_into_vector<32>(buffer, voa_size_as_u32); | |
220 | ||
221 | // Write vendor name. | |
222 | const unsigned char* vendor_start = | |
223 | reinterpret_cast<const unsigned char*>(this->name()); | |
224 | size_t vendor_length = strlen(this->name()) + 1; | |
225 | const unsigned char* vendor_end = vendor_start + vendor_length; | |
226 | buffer->insert(buffer->end(), vendor_start, vendor_end); | |
227 | ||
228 | // Write file tag. | |
229 | buffer->push_back(Object_attribute::Tag_File); | |
230 | ||
231 | // Write attributes size. | |
232 | uint32_t attributes_size_as_u32 = | |
233 | convert_types<uint32_t, size_t>(voa_size - 4 - vendor_length); | |
234 | insert_into_vector<32>(buffer, attributes_size_as_u32); | |
235 | ||
236 | // Write known attributes, skipping any defaults. | |
237 | for (int i = 4; i < NUM_KNOWN_ATTRIBUTES; ++i) | |
238 | { | |
239 | // A target may write known attributes in a special order. | |
240 | // Call target hook to remap tags. Attributes_order is the identity | |
241 | // function if no re-ordering is required. | |
242 | int tag = parameters->target().attributes_order(i); | |
243 | this->known_attributes_[tag].write(tag, buffer); | |
244 | } | |
245 | ||
246 | // Write other attributes. | |
247 | for (Other_attributes::const_iterator q = this->other_attributes_.begin(); | |
248 | q != this->other_attributes_.end(); | |
249 | ++q) | |
250 | q->second->write(q->first, buffer); | |
251 | } | |
252 | ||
253 | // Attributes_section_data methods. | |
254 | ||
255 | // Compute encoded size of this. | |
256 | ||
257 | size_t | |
258 | Attributes_section_data::size() const | |
259 | { | |
260 | size_t data_size = 0; | |
261 | for(int vendor = OBJ_ATTR_FIRST; vendor <= OBJ_ATTR_LAST; ++vendor) | |
262 | data_size += this->vendor_object_attributes_[vendor]->size(); | |
263 | ||
264 | // 'A' <sections for each vendor> | |
265 | return data_size != 0 ? data_size + 1 : 0; | |
266 | } | |
267 | ||
268 | // Construct an Attributes_section_data object by parsing section contents | |
2ea97941 | 269 | // specified by VIEW and SIZE. |
4f787271 DK |
270 | |
271 | Attributes_section_data::Attributes_section_data( | |
272 | const unsigned char* view, | |
2ea97941 | 273 | section_size_type size) |
4f787271 DK |
274 | { |
275 | for (int vendor = OBJ_ATTR_FIRST; vendor <= OBJ_ATTR_LAST; ++vendor) | |
276 | this->vendor_object_attributes_[vendor] = | |
277 | new Vendor_object_attributes(vendor); | |
278 | ||
ca09d69a | 279 | const unsigned char* p = view; |
4f787271 | 280 | p = view; |
ca419a6f | 281 | if (size > 0 && p != NULL && *(p++) == 'A') |
4f787271 | 282 | { |
2ea97941 ILT |
283 | size--; |
284 | while (size > 0) | |
4f787271 DK |
285 | { |
286 | // Size of vendor attributes section. | |
287 | section_size_type section_size = | |
288 | convert_to_section_size_type(read_from_pointer<32>(&p)); | |
289 | ||
2ea97941 ILT |
290 | if (section_size > size) |
291 | section_size = size; | |
292 | size -= section_size; | |
4f787271 DK |
293 | |
294 | const char* section_name = reinterpret_cast<const char*>(p); | |
295 | section_size_type section_name_size = strlen(section_name) + 1; | |
296 | section_size -= section_name_size + 4; | |
297 | ||
298 | int vendor; | |
ca09d69a | 299 | const char* std_section = parameters->target().attributes_vendor(); |
4f787271 DK |
300 | if (std_section != NULL && strcmp(section_name, std_section) == 0) |
301 | vendor = Object_attribute::OBJ_ATTR_PROC; | |
302 | else if (strcmp(section_name, "gnu") == 0) | |
303 | vendor = Object_attribute::OBJ_ATTR_GNU; | |
304 | else | |
305 | { | |
306 | // Other vendor section. Ignore it. | |
307 | p += section_name_size + section_size; | |
308 | continue; | |
309 | } | |
310 | p += section_name_size; | |
311 | ||
312 | while (section_size > 0) | |
313 | { | |
314 | const unsigned char* subsection_start = p; | |
315 | ||
316 | // Read vendor subsection index and size. | |
317 | size_t uleb128_len; | |
318 | uint64_t val = read_unsigned_LEB_128(p, &uleb128_len); | |
319 | p += uleb128_len; | |
320 | ||
321 | int tag = convert_types<int, uint64_t>(val); | |
322 | section_size_type subsection_size = | |
323 | convert_to_section_size_type(read_from_pointer<32>(&p)); | |
324 | section_size -= subsection_size; | |
325 | subsection_size -= (p - subsection_start); | |
326 | ||
327 | const unsigned char* end = p + subsection_size; | |
328 | switch (tag) | |
329 | { | |
330 | case Object_attribute::Tag_File: | |
331 | while (p < end) | |
332 | { | |
333 | val = read_unsigned_LEB_128(p, &uleb128_len); | |
334 | p += uleb128_len; | |
335 | tag = convert_types<int, uint64_t>(val); | |
336 | Vendor_object_attributes* pvoa = | |
337 | this->vendor_object_attributes_[vendor]; | |
338 | Object_attribute* attr = pvoa->new_attribute(tag); | |
339 | const char* string_arg; | |
340 | unsigned int int_arg; | |
341 | ||
342 | int type = Object_attribute::arg_type(vendor, tag); | |
343 | switch (type | |
344 | & (Object_attribute::ATTR_TYPE_FLAG_INT_VAL | |
345 | | Object_attribute::ATTR_TYPE_FLAG_STR_VAL)) | |
346 | { | |
347 | case (Object_attribute::ATTR_TYPE_FLAG_INT_VAL | |
348 | | Object_attribute::ATTR_TYPE_FLAG_STR_VAL): | |
349 | val = read_unsigned_LEB_128(p, &uleb128_len); | |
350 | p += uleb128_len; | |
351 | int_arg = convert_types<unsigned int, uint64_t>(val); | |
352 | string_arg = reinterpret_cast<const char *>(p); | |
353 | attr->set_int_value(int_arg); | |
354 | p += strlen(string_arg) + 1; | |
355 | break; | |
356 | case Object_attribute::ATTR_TYPE_FLAG_STR_VAL: | |
357 | string_arg = reinterpret_cast<const char *>(p); | |
358 | attr->set_string_value(string_arg); | |
359 | p += strlen(string_arg) + 1; | |
360 | break; | |
361 | case Object_attribute::ATTR_TYPE_FLAG_INT_VAL: | |
362 | val = read_unsigned_LEB_128(p, &uleb128_len); | |
363 | p += uleb128_len; | |
364 | int_arg = convert_types<unsigned int, uint64_t>(val); | |
365 | attr->set_int_value(int_arg); | |
366 | break; | |
367 | default: | |
368 | gold_unreachable(); | |
369 | } | |
370 | } | |
371 | break; | |
372 | case Object_attribute::Tag_Section: | |
373 | case Object_attribute::Tag_Symbol: | |
374 | // Don't have anywhere convenient to attach these. | |
375 | // Fall through for now. | |
376 | default: | |
377 | // Ignore things we don't know about. | |
378 | p += subsection_size; | |
379 | subsection_size = 0; | |
380 | break; | |
381 | } | |
382 | } | |
383 | } | |
384 | } | |
385 | } | |
386 | ||
387 | // Merge target-independent attributes from another Attribute_section_data | |
388 | // ASD from an object called NAME into this. | |
389 | ||
390 | void | |
391 | Attributes_section_data::merge( | |
392 | const char* name, | |
393 | const Attributes_section_data* pasd) | |
394 | { | |
395 | // The only common attribute is currently Tag_compatibility, | |
396 | // accepted in both processor and "gnu" sections. | |
397 | for (int vendor = OBJ_ATTR_FIRST; vendor <= OBJ_ATTR_LAST; ++vendor) | |
398 | { | |
399 | // Handle Tag_compatibility. The tags are only compatible if the flags | |
400 | // are identical and, if the flags are '1', the strings are identical. | |
401 | // If the flags are non-zero, then we can only use the string "gnu". | |
402 | const Object_attribute* in_attr = | |
403 | &pasd->known_attributes(vendor)[Object_attribute::Tag_compatibility]; | |
404 | Object_attribute* out_attr = | |
405 | &this->known_attributes(vendor)[Object_attribute::Tag_compatibility]; | |
406 | ||
407 | if (in_attr->int_value() > 0 | |
408 | && in_attr->string_value() != "gnu") | |
409 | { | |
410 | gold_error(_("%s: must be processed by '%s' toolchain"), | |
411 | name, in_attr->string_value().c_str()); | |
412 | return; | |
413 | } | |
414 | ||
415 | if (in_attr->int_value() != out_attr->int_value() | |
416 | || in_attr->string_value() != out_attr->string_value()) | |
417 | { | |
418 | gold_error(_("%s: object tag '%d, %s' is " | |
419 | "incompatible with tag '%d, %s'"), | |
420 | name, in_attr->int_value(), | |
421 | in_attr->string_value().c_str(), | |
422 | out_attr->int_value(), | |
423 | out_attr->string_value().c_str()); | |
424 | } | |
425 | } | |
426 | } | |
427 | ||
428 | // Write to a buffer. | |
429 | ||
430 | void | |
431 | Attributes_section_data::write(std::vector<unsigned char>* buffer) const | |
432 | { | |
433 | buffer->push_back('A'); | |
434 | for (int vendor = OBJ_ATTR_FIRST; vendor <= OBJ_ATTR_LAST; ++vendor) | |
435 | if (this->vendor_object_attributes_[vendor]->size() != 0) | |
436 | this->vendor_object_attributes_[vendor]->write(buffer); | |
437 | } | |
438 | ||
439 | // Methods for Output_attributes_section_data. | |
440 | ||
441 | // Write attributes section data to file OF. | |
442 | ||
443 | void | |
444 | Output_attributes_section_data::do_write(Output_file* of) | |
445 | { | |
2ea97941 | 446 | off_t offset = this->offset(); |
4f787271 DK |
447 | const section_size_type oview_size = |
448 | convert_to_section_size_type(this->data_size()); | |
2ea97941 | 449 | unsigned char* const oview = of->get_output_view(offset, oview_size); |
4f787271 DK |
450 | |
451 | std::vector<unsigned char> buffer; | |
452 | this->attributes_section_data_.write(&buffer); | |
453 | gold_assert(convert_to_section_size_type(buffer.size()) == oview_size); | |
250acde3 | 454 | memcpy(oview, &buffer.front(), buffer.size()); |
4f787271 DK |
455 | of->write_output_view(this->offset(), oview_size, oview); |
456 | } | |
457 | ||
458 | } // End namespace gold. |