C++程序  |  153行  |  3.12 KB

/*
 * Copyright 2011, The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ELF_RELOC_H
#define ELF_RELOC_H

#include "ELFTypes.h"
#include "utils/rsl_assert.h"

#include <llvm/ADT/OwningPtr.h>
#include <string>
#include <stdint.h>

template <unsigned Bitwidth>
class ELFReloc_CRTP {
public:
  ELF_TYPE_INTRO_TO_TEMPLATE_SCOPE(Bitwidth);

protected:
  size_t index;

  addr_t    r_offset;
  relinfo_t r_info;
  addend_t  r_addend;

protected:
  ELFReloc_CRTP() : index(0), r_offset(0), r_addend(0) { }
  ~ELFReloc_CRTP() { }

public:
  size_t getIndex() const {
    return index;
  }

  addr_t getOffset() const {
    return r_offset;
  }

  addend_t getAddend() const {
    return r_addend;
  }

  bool isValid() const {
    // FIXME: Should check the correctness of the relocation entite.
    return true;
  }

  template <typename Archiver>
  static ELFRelocTy *readRel(Archiver &AR, size_t index);

  template <typename Archiver>
  static ELFRelocTy *readRela(Archiver &AR, size_t index);

  void print(bool shouldPrintHeader = false) const;

private:
  ELFRelocTy *concrete() {
    return static_cast<ELFRelocTy *>(this);
  }

  ELFRelocTy const *concrete() const {
    return static_cast<ELFRelocTy const *>(this);
  }

  template <typename Archiver>
  bool serializeRel(Archiver &AR) {
    rsl_assert(r_addend == 0 && "r_addend should be zero before serialization.");

    AR.prologue(TypeTraits<ELFRelocRelTy>::size);

    AR & r_offset;
    AR & r_info;

    AR.epilogue(TypeTraits<ELFRelocRelTy>::size);
    return AR;
  }

  template <typename Archiver>
  bool serializeRela(Archiver &AR) {
    AR.prologue(TypeTraits<ELFRelocRelaTy>::size);

    AR & r_offset;
    AR & r_info;
    AR & r_addend;

    AR.epilogue(TypeTraits<ELFRelocRelaTy>::size);
    return AR;
  }

};

template <>
class ELFReloc<32> : public ELFReloc_CRTP<32> {
  friend class ELFReloc_CRTP<32>;

private:
  ELFReloc() {
  }

public:
  word_t getSymTabIndex() const {
#define ELF32_R_SYM(i)  ((i)>>8)
    return ELF32_R_SYM(this->r_info);
#undef ELF32_R_SYM
  }

  word_t getType() const {
#define ELF32_R_TYPE(i)   ((unsigned char)(i))
    return ELF32_R_TYPE(this->r_info);
#undef ELF32_R_TYPE
  }

};

template <>
class ELFReloc<64> : public ELFReloc_CRTP<64> {
  friend class ELFReloc_CRTP<64>;

private:
  ELFReloc() {
  }

public:
  xword_t getSymTabIndex() const {
#define ELF64_R_SYM(i)    ((i)>>32)
    return ELF64_R_SYM(this->r_info);
#undef ELF64_R_SYM
  }

  xword_t getType() const {
#define ELF64_R_TYPE(i)   ((i)&0xffffffffL)
    return ELF64_R_TYPE(this->r_info);
#undef ELF64_R_TYPE
  }
};

#include "impl/ELFReloc.hxx"

#endif // ELF_RELOC_H