HIP: Heterogenous-computing Interface for Portability
elfio_relocation.hpp
1 /*
2 Copyright (C) 2001-2015 by Serge Lamikhov-Center
3 
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
10 
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13 
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 THE SOFTWARE.
21 */
22 
23 #ifndef ELFIO_RELOCATION_HPP
24 #define ELFIO_RELOCATION_HPP
25 
26 namespace ELFIO {
27 
28 template <typename T>
30 template <>
32  static int get_r_sym(Elf_Xword info) { return ELF32_R_SYM((Elf_Word)info); }
33  static int get_r_type(Elf_Xword info) { return ELF32_R_TYPE((Elf_Word)info); }
34 };
35 template <>
37  static int get_r_sym(Elf_Xword info) { return ELF32_R_SYM((Elf_Word)info); }
38  static int get_r_type(Elf_Xword info) { return ELF32_R_TYPE((Elf_Word)info); }
39 };
40 template <>
42  static int get_r_sym(Elf_Xword info) { return ELF64_R_SYM(info); }
43  static int get_r_type(Elf_Xword info) { return ELF64_R_TYPE(info); }
44 };
45 template <>
47  static int get_r_sym(Elf_Xword info) { return ELF64_R_SYM(info); }
48  static int get_r_type(Elf_Xword info) { return ELF64_R_TYPE(info); }
49 };
50 
51 
52 //------------------------------------------------------------------------------
54  public:
55  //------------------------------------------------------------------------------
56  relocation_section_accessor(const elfio& elf_file_, section* section_)
57  : elf_file(elf_file_), relocation_section(section_) {}
58 
59  //------------------------------------------------------------------------------
60  Elf_Xword get_entries_num() const {
61  Elf_Xword nRet = 0;
62 
63  if (0 != relocation_section->get_entry_size()) {
64  nRet = relocation_section->get_size() / relocation_section->get_entry_size();
65  }
66 
67  return nRet;
68  }
69 
70  //------------------------------------------------------------------------------
71  bool get_entry(Elf_Xword index, Elf64_Addr& offset, Elf_Word& symbol, Elf_Word& type,
72  Elf_Sxword& addend) const {
73  if (index >= get_entries_num()) { // Is index valid
74  return false;
75  }
76 
77  if (elf_file.get_class() == ELFCLASS32) {
78  if (SHT_REL == relocation_section->get_type()) {
79  generic_get_entry_rel<Elf32_Rel>(index, offset, symbol, type, addend);
80  } else if (SHT_RELA == relocation_section->get_type()) {
81  generic_get_entry_rela<Elf32_Rela>(index, offset, symbol, type, addend);
82  }
83  } else {
84  if (SHT_REL == relocation_section->get_type()) {
85  generic_get_entry_rel<Elf64_Rel>(index, offset, symbol, type, addend);
86  } else if (SHT_RELA == relocation_section->get_type()) {
87  generic_get_entry_rela<Elf64_Rela>(index, offset, symbol, type, addend);
88  }
89  }
90 
91  return true;
92  }
93 
94  //------------------------------------------------------------------------------
95  bool get_entry(Elf_Xword index, Elf64_Addr& offset, Elf64_Addr& symbolValue,
96  std::string& symbolName, Elf_Word& type, Elf_Sxword& addend,
97  Elf_Sxword& calcValue) const {
98  // Do regular job
99  Elf_Word symbol;
100  bool ret = get_entry(index, offset, symbol, type, addend);
101 
102  // Find the symbol
103  Elf_Xword size;
104  unsigned char bind;
105  unsigned char symbolType;
106  Elf_Half section;
107  unsigned char other;
108 
109  symbol_section_accessor symbols(elf_file, elf_file.sections[get_symbol_table_index()]);
110  ret = ret && symbols.get_symbol(symbol, symbolName, symbolValue, size, bind, symbolType,
111  section, other);
112 
113  if (ret) { // Was it successful?
114  switch (type) {
115  case R_386_NONE: // none
116  calcValue = 0;
117  break;
118  case R_386_32: // S + A
119  calcValue = symbolValue + addend;
120  break;
121  case R_386_PC32: // S + A - P
122  calcValue = symbolValue + addend - offset;
123  break;
124  case R_386_GOT32: // G + A - P
125  calcValue = 0;
126  break;
127  case R_386_PLT32: // L + A - P
128  calcValue = 0;
129  break;
130  case R_386_COPY: // none
131  calcValue = 0;
132  break;
133  case R_386_GLOB_DAT: // S
134  case R_386_JMP_SLOT: // S
135  calcValue = symbolValue;
136  break;
137  case R_386_RELATIVE: // B + A
138  calcValue = addend;
139  break;
140  case R_386_GOTOFF: // S + A - GOT
141  calcValue = 0;
142  break;
143  case R_386_GOTPC: // GOT + A - P
144  calcValue = 0;
145  break;
146  default: // Not recognized symbol!
147  calcValue = 0;
148  break;
149  }
150  }
151 
152  return ret;
153  }
154 
155  //------------------------------------------------------------------------------
156  void add_entry(Elf64_Addr offset, Elf_Xword info) {
157  if (elf_file.get_class() == ELFCLASS32) {
158  generic_add_entry<Elf32_Rel>(offset, info);
159  } else {
160  generic_add_entry<Elf64_Rel>(offset, info);
161  }
162  }
163 
164  //------------------------------------------------------------------------------
165  void add_entry(Elf64_Addr offset, Elf_Word symbol, unsigned char type) {
166  Elf_Xword info;
167  if (elf_file.get_class() == ELFCLASS32) {
168  info = ELF32_R_INFO((Elf_Xword)symbol, type);
169  } else {
170  info = ELF64_R_INFO((Elf_Xword)symbol, type);
171  }
172 
173  add_entry(offset, info);
174  }
175 
176  //------------------------------------------------------------------------------
177  void add_entry(Elf64_Addr offset, Elf_Xword info, Elf_Sxword addend) {
178  if (elf_file.get_class() == ELFCLASS32) {
179  generic_add_entry<Elf32_Rela>(offset, info, addend);
180  } else {
181  generic_add_entry<Elf64_Rela>(offset, info, addend);
182  }
183  }
184 
185  //------------------------------------------------------------------------------
186  void add_entry(Elf64_Addr offset, Elf_Word symbol, unsigned char type, Elf_Sxword addend) {
187  Elf_Xword info;
188  if (elf_file.get_class() == ELFCLASS32) {
189  info = ELF32_R_INFO((Elf_Xword)symbol, type);
190  } else {
191  info = ELF64_R_INFO((Elf_Xword)symbol, type);
192  }
193 
194  add_entry(offset, info, addend);
195  }
196 
197  //------------------------------------------------------------------------------
198  void add_entry(string_section_accessor str_writer, const char* str,
199  symbol_section_accessor sym_writer, Elf64_Addr value, Elf_Word size,
200  unsigned char sym_info, unsigned char other, Elf_Half shndx, Elf64_Addr offset,
201  unsigned char type) {
202  Elf_Word str_index = str_writer.add_string(str);
203  Elf_Word sym_index = sym_writer.add_symbol(str_index, value, size, sym_info, other, shndx);
204  add_entry(offset, sym_index, type);
205  }
206 
207  //------------------------------------------------------------------------------
208  private:
209  //------------------------------------------------------------------------------
210  Elf_Half get_symbol_table_index() const { return (Elf_Half)relocation_section->get_link(); }
211 
212  //------------------------------------------------------------------------------
213  template <class T>
214  void generic_get_entry_rel(Elf_Xword index, Elf64_Addr& offset, Elf_Word& symbol,
215  Elf_Word& type, Elf_Sxword& addend) const {
216  const endianess_convertor& convertor = elf_file.get_convertor();
217 
218  const T* pEntry = reinterpret_cast<const T*>(relocation_section->get_data() +
219  index * relocation_section->get_entry_size());
220  offset = convertor(pEntry->r_offset);
221  Elf_Xword tmp = convertor(pEntry->r_info);
222  symbol = get_sym_and_type<T>::get_r_sym(tmp);
224  addend = 0;
225  }
226 
227  //------------------------------------------------------------------------------
228  template <class T>
229  void generic_get_entry_rela(Elf_Xword index, Elf64_Addr& offset, Elf_Word& symbol,
230  Elf_Word& type, Elf_Sxword& addend) const {
231  const endianess_convertor& convertor = elf_file.get_convertor();
232 
233  const T* pEntry = reinterpret_cast<const T*>(relocation_section->get_data() +
234  index * relocation_section->get_entry_size());
235  offset = convertor(pEntry->r_offset);
236  Elf_Xword tmp = convertor(pEntry->r_info);
237  symbol = get_sym_and_type<T>::get_r_sym(tmp);
239  addend = convertor(pEntry->r_addend);
240  }
241 
242  //------------------------------------------------------------------------------
243  template <class T>
244  void generic_add_entry(Elf64_Addr offset, Elf_Xword info) {
245  const endianess_convertor& convertor = elf_file.get_convertor();
246 
247  T entry;
248  entry.r_offset = offset;
249  entry.r_info = info;
250  entry.r_offset = convertor(entry.r_offset);
251  entry.r_info = convertor(entry.r_info);
252 
253  relocation_section->append_data(reinterpret_cast<char*>(&entry), sizeof(entry));
254  }
255 
256  //------------------------------------------------------------------------------
257  template <class T>
258  void generic_add_entry(Elf64_Addr offset, Elf_Xword info, Elf_Sxword addend) {
259  const endianess_convertor& convertor = elf_file.get_convertor();
260 
261  T entry;
262  entry.r_offset = offset;
263  entry.r_info = info;
264  entry.r_addend = addend;
265  entry.r_offset = convertor(entry.r_offset);
266  entry.r_info = convertor(entry.r_info);
267  entry.r_addend = convertor(entry.r_addend);
268 
269  relocation_section->append_data(reinterpret_cast<char*>(&entry), sizeof(entry));
270  }
271 
272  //------------------------------------------------------------------------------
273  private:
274  const elfio& elf_file;
275  section* relocation_section;
276 };
277 
278 } // namespace ELFIO
279 
280 #endif // ELFIO_RELOCATION_HPP
ELFIO::string_section_accessor
Definition: elfio_strings.hpp:33
ELFIO::endianess_convertor
Definition: elfio_utils.hpp:51
ELFIO::Elf64_Rel
Definition: elf_types.hpp:709
ELFIO::relocation_section_accessor
Definition: elfio_relocation.hpp:53
ELFIO::get_sym_and_type
Definition: elfio_relocation.hpp:29
ELFIO::elfio
Definition: elfio.hpp:59
ELFIO::symbol_section_accessor
Definition: elfio_symbols.hpp:29
ELFIO::Elf64_Rela
Definition: elf_types.hpp:714
ELFIO::Elf32_Rela
Definition: elf_types.hpp:703
ELFIO::section
Definition: elfio_section.hpp:31
ELFIO::Elf32_Rel
Definition: elf_types.hpp:698