C++程序  |  121行  |  3.77 KB

//===- ELFAttribute.h -----------------------------------------------------===//
//
//                     The MCLinker Project
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef MCLD_TARGET_ELFATTRIBUTE_H_
#define MCLD_TARGET_ELFATTRIBUTE_H_

#include "mcld/Support/MemoryRegion.h"
#include "mcld/Target/ELFAttributeData.h"

#include <llvm/ADT/SmallVector.h>
#include <llvm/ADT/StringRef.h>

namespace mcld {

class ELFAttributeData;
class GNULDBackend;
class Input;
class LDSection;
class LinkerConfig;

/** \class ELFAttribute
 *  \brief ELFAttribute is the attribute section in an ELF file.
 */
class ELFAttribute {
 public:
  // ARM [ABI-addenda], 2.2.3.
  static const char FormatVersion = 'A';
  static const size_t FormatVersionFieldSize = sizeof(FormatVersion);  // a byte
  static const size_t SubsectionLengthFieldSize = 4;  // a 4-byte integer

  // MinimalELFAttributeSubsectionSize is the minimal number of bytes a valid
  // subsection in ELF attribute section should have.
  static const size_t MinimalELFAttributeSubsectionSize =
      1 /* Tag_File, see ARM [ABI-addenda], 2.2.4 */ +
      4 /* byte-size, see ARM [ABI-addenda], 2.2.4 */;

  // MinimalELFAttributeSectionSize is the minimal number of bytes a valid ELF
  // attribute section should have.
  static const size_t MinimalELFAttributeSectionSize =
      FormatVersionFieldSize + SubsectionLengthFieldSize +
      2 /* vendor-name, a char plus '\0', see ARM [ABI-addenda], 2.2.3 */ +
      1 * MinimalELFAttributeSubsectionSize;

 public:
  ELFAttribute(const GNULDBackend& pBackend, const LinkerConfig& pConfig)
      : m_Backend(pBackend), m_Config(pConfig) {}

  ~ELFAttribute();

 public:
  /// merge - merge attributes from input (attribute) section
  bool merge(const Input& pInput, LDSection& pInputAttrSectHdr);

  /// sizeOutput - calculate the number of bytes required to encode this
  /// attribute data section
  size_t sizeOutput() const;

  /// emit - encode and write out this attribute section
  size_t emit(MemoryRegion& pRegion) const;

  inline const GNULDBackend& backend() const { return m_Backend; }

  inline const LinkerConfig& config() const { return m_Config; }

  // Place vendor's attribute data under the management.
  void registerAttributeData(ELFAttributeData& pAttrData);

 private:
  /** \class Subsection
   *  \brief A helper class to wrap ELFAttributeData and to provide general
   *  interfaces for ELFAttribute to operate on
   */
  class Subsection {
   public:
    Subsection(ELFAttribute& pParent, ELFAttributeData& pAttrData)
        : m_Parent(pParent), m_AttrData(pAttrData) {}

   public:
    bool isMyAttribute(llvm::StringRef pVendorName) const {
      return (m_AttrData.getVendorName() == pVendorName);
    }

    /// merge -  Merge the attributes from the section in the input data.
    bool merge(const Input& pInput, ConstAddress pData, size_t pSize);

    /// sizeOutput - calculate the number of bytes required to encode this
    /// subsection
    size_t sizeOutput() const;

    /// emit - write out this attribute subsection to the buffer.
    size_t emit(char* pBuf) const;

   private:
    // The attribute section this subsection belongs to
    ELFAttribute& m_Parent;

    // The attribute data containing in this subsection
    ELFAttributeData& m_AttrData;
  };

  // Obtain the corresponding subsection of the specified vendor
  Subsection* getSubsection(llvm::StringRef pVendorName) const;

 private:
  const GNULDBackend& m_Backend;

  const LinkerConfig& m_Config;

  // There is at most two subsections ("aeabi" and "gnu") in most cases.
  llvm::SmallVector<Subsection*, 2> m_Subsections;
};

}  // namespace mcld

#endif  // MCLD_TARGET_ELFATTRIBUTE_H_