C++程序  |  149行  |  3.87 KB

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

#ifndef MCLD_FRAGMENT_STUB_H_
#define MCLD_FRAGMENT_STUB_H_

#include "mcld/Fragment/Fragment.h"
#include "mcld/Fragment/Relocation.h"

#include <llvm/Support/DataTypes.h>

#include <string>
#include <vector>

namespace mcld {

class BranchIsland;
class IRBuilder;
class Relocation;
class ResolveInfo;

class Stub : public Fragment {
 public:
  typedef Relocation::DWord DWord;
  typedef Relocation::SWord SWord;
  typedef Relocation::Type Type;

  class Fixup {
   public:
    Fixup(DWord pOffset, SWord pAddend, Type pType)
        : m_Offset(pOffset), m_Addend(pAddend), m_Type(pType) {}

    ~Fixup() {}

    DWord offset() const { return m_Offset; }

    SWord addend() const { return m_Addend; }

    Type type() const { return m_Type; }

   private:
    DWord m_Offset;
    SWord m_Addend;
    Type m_Type;
  };

 public:
  typedef std::vector<Fixup*> FixupListType;
  typedef FixupListType::iterator fixup_iterator;
  typedef FixupListType::const_iterator const_fixup_iterator;

 public:
  Stub();

  virtual ~Stub();

  /// clone - clone function for stub factory to create the corresponding stub
  Stub* clone() { return doClone(); }

  /// isMyDuty - return true when the pReloc is problematic and the stub is able
  /// to fix it!
  virtual bool isMyDuty(const Relocation& pReloc,
                        uint64_t pSource,
                        uint64_t pTargetSymValue) const {
    return false;
  }

  virtual bool isMyDuty(const FragmentRef& pFragRef) const {
    return false;
  }

  /// name - name of this stub
  virtual const std::string& name() const = 0;

  /// getContent - content of the stub
  virtual const uint8_t* getContent() const = 0;

  /// size - size of the stub
  virtual size_t size() const = 0;

  /// alignment - alignment of the stub
  virtual size_t alignment() const = 0;

  /// symInfo - ResolveInfo of this Stub
  ResolveInfo* symInfo() { return m_pSymInfo; }

  const ResolveInfo* symInfo() const { return m_pSymInfo; }

  /// symValue - initial value for stub's symbol
  virtual uint64_t initSymValue() const { return 0x0; }

  ///  -----  Fixup  -----  ///
  fixup_iterator fixup_begin() { return m_FixupList.begin(); }

  const_fixup_iterator fixup_begin() const { return m_FixupList.begin(); }

  fixup_iterator fixup_end() { return m_FixupList.end(); }

  const_fixup_iterator fixup_end() const { return m_FixupList.end(); }

  size_t fixup_size() const { return m_FixupList.size(); }

  virtual void applyFixup(Relocation& pSrcReloc,
                          IRBuilder& pBuilder,
                          BranchIsland& pIsland);

  virtual void applyFixup(FragmentRef& pSrcFragRef,
                          IRBuilder& pBuilder,
                          BranchIsland& pIsland);

  /// ----- modifiers ----- ///
  void setSymInfo(ResolveInfo* pSymInfo);

  // Stub is a kind of Fragment with type of Stub
  static bool classof(const Fragment* F) {
    return F->getKind() == Fragment::Stub;
  }

  static bool classof(const Stub*) { return true; }

 protected:
  /// addFixup - add a fixup for this stub to build a relocation
  void addFixup(DWord pOffset, SWord pAddend, Type pType);

  /// addFixup - add a fixup from a existing fixup of the prototype
  void addFixup(const Fixup& pFixup);

  const FixupListType& getFixupList() const { return m_FixupList; }
  FixupListType&       getFixupList()       { return m_FixupList; }

 private:
  /// doClone - when adding a backend stub, we should implement this function
  virtual Stub* doClone() = 0;

 private:
  ResolveInfo* m_pSymInfo;
  FixupListType m_FixupList;
};

}  // namespace mcld

#endif  // MCLD_FRAGMENT_STUB_H_