1/*
2 * Copyright 2011, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef ELF_RELOC_H
18#define ELF_RELOC_H
19
20#include "ELFTypes.h"
21#include "utils/rsl_assert.h"
22
23#include <string>
24#include <stdint.h>
25
26template <unsigned Bitwidth>
27class ELFReloc_CRTP {
28public:
29  ELF_TYPE_INTRO_TO_TEMPLATE_SCOPE(Bitwidth);
30
31protected:
32  size_t index;
33
34  addr_t    r_offset;
35  relinfo_t r_info;
36  addend_t  r_addend;
37
38protected:
39  ELFReloc_CRTP() : index(0), r_offset(0), r_addend(0) { }
40  ~ELFReloc_CRTP() { }
41
42public:
43  size_t getIndex() const {
44    return index;
45  }
46
47  addr_t getOffset() const {
48    return r_offset;
49  }
50
51  addend_t getAddend() const {
52    return r_addend;
53  }
54
55  bool isValid() const {
56    // FIXME: Should check the correctness of the relocation entite.
57    return true;
58  }
59
60  template <typename Archiver>
61  static ELFRelocTy *readRel(Archiver &AR, size_t index);
62
63  template <typename Archiver>
64  static ELFRelocTy *readRela(Archiver &AR, size_t index);
65
66  void print(bool shouldPrintHeader = false) const;
67
68private:
69  ELFRelocTy *concrete() {
70    return static_cast<ELFRelocTy *>(this);
71  }
72
73  ELFRelocTy const *concrete() const {
74    return static_cast<ELFRelocTy const *>(this);
75  }
76
77  template <typename Archiver>
78  bool serializeRel(Archiver &AR) {
79    rsl_assert(r_addend == 0 && "r_addend should be zero before serialization.");
80
81    AR.prologue(TypeTraits<ELFRelocRelTy>::size);
82
83    AR & r_offset;
84    AR & r_info;
85
86    AR.epilogue(TypeTraits<ELFRelocRelTy>::size);
87    return AR;
88  }
89
90  template <typename Archiver>
91  bool serializeRela(Archiver &AR) {
92    AR.prologue(TypeTraits<ELFRelocRelaTy>::size);
93
94    AR & r_offset;
95    AR & r_info;
96    AR & r_addend;
97
98    AR.epilogue(TypeTraits<ELFRelocRelaTy>::size);
99    return AR;
100  }
101
102};
103
104template <>
105class ELFReloc<32> : public ELFReloc_CRTP<32> {
106  friend class ELFReloc_CRTP<32>;
107
108private:
109  ELFReloc() {
110  }
111
112public:
113  word_t getSymTabIndex() const {
114#define ELF32_R_SYM(i)  ((i)>>8)
115    return ELF32_R_SYM(this->r_info);
116#undef ELF32_R_SYM
117  }
118
119  word_t getType() const {
120#define ELF32_R_TYPE(i)   ((unsigned char)(i))
121    return ELF32_R_TYPE(this->r_info);
122#undef ELF32_R_TYPE
123  }
124
125};
126
127template <>
128class ELFReloc<64> : public ELFReloc_CRTP<64> {
129  friend class ELFReloc_CRTP<64>;
130
131private:
132  ELFReloc() {
133  }
134
135public:
136  xword_t getSymTabIndex() const {
137#define ELF64_R_SYM(i)    ((i)>>32)
138    return ELF64_R_SYM(this->r_info);
139#undef ELF64_R_SYM
140  }
141
142  xword_t getType() const {
143#define ELF64_R_TYPE(i)   ((i)&0xffffffffL)
144    return ELF64_R_TYPE(this->r_info);
145#undef ELF64_R_TYPE
146  }
147};
148
149#include "impl/ELFReloc.hxx"
150
151#endif // ELF_RELOC_H
152