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