aboutsummaryrefslogtreecommitdiff
path: root/gold/attributes.h
diff options
context:
space:
mode:
Diffstat (limited to 'gold/attributes.h')
-rw-r--r--gold/attributes.h406
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)