| // 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) |