diff options
Diffstat (limited to 'gold/attributes.h')
-rw-r--r-- | gold/attributes.h | 406 |
1 files changed, 406 insertions, 0 deletions
diff --git a/gold/attributes.h b/gold/attributes.h new file mode 100644 index 0000000..7c4baf4 --- /dev/null +++ b/gold/attributes.h @@ -0,0 +1,406 @@ +// attributes.h -- object attributes for gold -*- C++ -*- + +// Copyright 2009 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 asssociated 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 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) |