|  | // attributes.h -- object attributes for gold   -*- C++ -*- | 
|  |  | 
|  | // Copyright (C) 2009-2025 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) |