• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 Copyright (C) 2001-present 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> struct get_sym_and_type;
29 template <> struct get_sym_and_type<Elf32_Rel>
30 {
get_r_symELFIO::get_sym_and_type31     static int get_r_sym( Elf_Xword info )
32     {
33         return ELF32_R_SYM( (Elf_Word)info );
34     }
get_r_typeELFIO::get_sym_and_type35     static int get_r_type( Elf_Xword info )
36     {
37         return ELF32_R_TYPE( (Elf_Word)info );
38     }
39 };
40 template <> struct get_sym_and_type<Elf32_Rela>
41 {
get_r_symELFIO::get_sym_and_type42     static int get_r_sym( Elf_Xword info )
43     {
44         return ELF32_R_SYM( (Elf_Word)info );
45     }
get_r_typeELFIO::get_sym_and_type46     static int get_r_type( Elf_Xword info )
47     {
48         return ELF32_R_TYPE( (Elf_Word)info );
49     }
50 };
51 template <> struct get_sym_and_type<Elf64_Rel>
52 {
get_r_symELFIO::get_sym_and_type53     static int get_r_sym( Elf_Xword info ) { return ELF64_R_SYM( info ); }
get_r_typeELFIO::get_sym_and_type54     static int get_r_type( Elf_Xword info ) { return ELF64_R_TYPE( info ); }
55 };
56 template <> struct get_sym_and_type<Elf64_Rela>
57 {
get_r_symELFIO::get_sym_and_type58     static int get_r_sym( Elf_Xword info ) { return ELF64_R_SYM( info ); }
get_r_typeELFIO::get_sym_and_type59     static int get_r_type( Elf_Xword info ) { return ELF64_R_TYPE( info ); }
60 };
61 
62 //------------------------------------------------------------------------------
63 template <class S> class relocation_section_accessor_template
64 {
65   public:
66     //------------------------------------------------------------------------------
relocation_section_accessor_template(const elfio & elf_file,S * section)67     explicit relocation_section_accessor_template( const elfio& elf_file,
68                                                    S*           section )
69         : elf_file( elf_file ), relocation_section( section )
70     {
71     }
72 
73     //------------------------------------------------------------------------------
get_entries_num() const74     Elf_Xword get_entries_num() const
75     {
76         Elf_Xword nRet = 0;
77 
78         if ( 0 != relocation_section->get_entry_size() ) {
79             nRet = relocation_section->get_size() /
80                    relocation_section->get_entry_size();
81         }
82 
83         return nRet;
84     }
85 
86     //------------------------------------------------------------------------------
get_entry(Elf_Xword index,Elf64_Addr & offset,Elf_Word & symbol,unsigned & type,Elf_Sxword & addend) const87     bool get_entry( Elf_Xword   index,
88                     Elf64_Addr& offset,
89                     Elf_Word&   symbol,
90                     unsigned&   type,
91                     Elf_Sxword& addend ) const
92     {
93         if ( index >= get_entries_num() ) { // Is index valid
94             return false;
95         }
96 
97         if ( elf_file.get_class() == ELFCLASS32 ) {
98             if ( SHT_REL == relocation_section->get_type() ) {
99                 generic_get_entry_rel<Elf32_Rel>( index, offset, symbol, type,
100                                                   addend );
101             }
102             else if ( SHT_RELA == relocation_section->get_type() ) {
103                 generic_get_entry_rela<Elf32_Rela>( index, offset, symbol, type,
104                                                     addend );
105             }
106         }
107         else {
108             if ( SHT_REL == relocation_section->get_type() ) {
109                 generic_get_entry_rel<Elf64_Rel>( index, offset, symbol, type,
110                                                   addend );
111             }
112             else if ( SHT_RELA == relocation_section->get_type() ) {
113                 generic_get_entry_rela<Elf64_Rela>( index, offset, symbol, type,
114                                                     addend );
115             }
116         }
117 
118         return true;
119     }
120 
121     //------------------------------------------------------------------------------
get_entry(Elf_Xword index,Elf64_Addr & offset,Elf64_Addr & symbolValue,std::string & symbolName,unsigned & type,Elf_Sxword & addend,Elf_Sxword & calcValue) const122     bool get_entry( Elf_Xword    index,
123                     Elf64_Addr&  offset,
124                     Elf64_Addr&  symbolValue,
125                     std::string& symbolName,
126                     unsigned&    type,
127                     Elf_Sxword&  addend,
128                     Elf_Sxword&  calcValue ) const
129     {
130         // Do regular job
131         Elf_Word symbol = 0;
132         bool     ret    = get_entry( index, offset, symbol, type, addend );
133 
134         // Find the symbol
135         Elf_Xword     size;
136         unsigned char bind;
137         unsigned char symbolType;
138         Elf_Half      section;
139         unsigned char other;
140 
141         symbol_section_accessor symbols(
142             elf_file, elf_file.sections[get_symbol_table_index()] );
143         ret = ret && symbols.get_symbol( symbol, symbolName, symbolValue, size,
144                                          bind, symbolType, section, other );
145 
146         if ( ret ) { // Was it successful?
147             switch ( type ) {
148             case R_386_NONE: // none
149                 calcValue = 0;
150                 break;
151             case R_386_32: // S + A
152                 calcValue = symbolValue + addend;
153                 break;
154             case R_386_PC32: // S + A - P
155                 calcValue = symbolValue + addend - offset;
156                 break;
157             case R_386_GOT32: // G + A - P
158                 calcValue = 0;
159                 break;
160             case R_386_PLT32: // L + A - P
161                 calcValue = 0;
162                 break;
163             case R_386_COPY: // none
164                 calcValue = 0;
165                 break;
166             case R_386_GLOB_DAT: // S
167             case R_386_JMP_SLOT: // S
168                 calcValue = symbolValue;
169                 break;
170             case R_386_RELATIVE: // B + A
171                 calcValue = addend;
172                 break;
173             case R_386_GOTOFF: // S + A - GOT
174                 calcValue = 0;
175                 break;
176             case R_386_GOTPC: // GOT + A - P
177                 calcValue = 0;
178                 break;
179             default: // Not recognized symbol!
180                 calcValue = 0;
181                 break;
182             }
183         }
184 
185         return ret;
186     }
187 
188     //------------------------------------------------------------------------------
set_entry(Elf_Xword index,Elf64_Addr offset,Elf_Word symbol,unsigned type,Elf_Sxword addend)189     bool set_entry( Elf_Xword  index,
190                     Elf64_Addr offset,
191                     Elf_Word   symbol,
192                     unsigned   type,
193                     Elf_Sxword addend )
194     {
195         if ( index >= get_entries_num() ) { // Is index valid
196             return false;
197         }
198 
199         if ( elf_file.get_class() == ELFCLASS32 ) {
200             if ( SHT_REL == relocation_section->get_type() ) {
201                 generic_set_entry_rel<Elf32_Rel>( index, offset, symbol, type,
202                                                   addend );
203             }
204             else if ( SHT_RELA == relocation_section->get_type() ) {
205                 generic_set_entry_rela<Elf32_Rela>( index, offset, symbol, type,
206                                                     addend );
207             }
208         }
209         else {
210             if ( SHT_REL == relocation_section->get_type() ) {
211                 generic_set_entry_rel<Elf64_Rel>( index, offset, symbol, type,
212                                                   addend );
213             }
214             else if ( SHT_RELA == relocation_section->get_type() ) {
215                 generic_set_entry_rela<Elf64_Rela>( index, offset, symbol, type,
216                                                     addend );
217             }
218         }
219 
220         return true;
221     }
222 
223     //------------------------------------------------------------------------------
add_entry(Elf64_Addr offset,Elf_Xword info)224     void add_entry( Elf64_Addr offset, Elf_Xword info )
225     {
226         if ( elf_file.get_class() == ELFCLASS32 ) {
227             generic_add_entry<Elf32_Rel>( offset, info );
228         }
229         else {
230             generic_add_entry<Elf64_Rel>( offset, info );
231         }
232     }
233 
234     //------------------------------------------------------------------------------
add_entry(Elf64_Addr offset,Elf_Word symbol,unsigned type)235     void add_entry( Elf64_Addr offset, Elf_Word symbol, unsigned type )
236     {
237         Elf_Xword info;
238         if ( elf_file.get_class() == ELFCLASS32 ) {
239             info = ELF32_R_INFO( (Elf_Xword)symbol, type );
240         }
241         else {
242             info = ELF64_R_INFO( (Elf_Xword)symbol, type );
243         }
244 
245         add_entry( offset, info );
246     }
247 
248     //------------------------------------------------------------------------------
add_entry(Elf64_Addr offset,Elf_Xword info,Elf_Sxword addend)249     void add_entry( Elf64_Addr offset, Elf_Xword info, Elf_Sxword addend )
250     {
251         if ( elf_file.get_class() == ELFCLASS32 ) {
252             generic_add_entry<Elf32_Rela>( offset, info, addend );
253         }
254         else {
255             generic_add_entry<Elf64_Rela>( offset, info, addend );
256         }
257     }
258 
259     //------------------------------------------------------------------------------
add_entry(Elf64_Addr offset,Elf_Word symbol,unsigned type,Elf_Sxword addend)260     void add_entry( Elf64_Addr offset,
261                     Elf_Word   symbol,
262                     unsigned   type,
263                     Elf_Sxword addend )
264     {
265         Elf_Xword info;
266         if ( elf_file.get_class() == ELFCLASS32 ) {
267             info = ELF32_R_INFO( (Elf_Xword)symbol, type );
268         }
269         else {
270             info = ELF64_R_INFO( (Elf_Xword)symbol, type );
271         }
272 
273         add_entry( offset, info, addend );
274     }
275 
276     //------------------------------------------------------------------------------
add_entry(string_section_accessor str_writer,const char * str,symbol_section_accessor sym_writer,Elf64_Addr value,Elf_Word size,unsigned char sym_info,unsigned char other,Elf_Half shndx,Elf64_Addr offset,unsigned type)277     void add_entry( string_section_accessor str_writer,
278                     const char*             str,
279                     symbol_section_accessor sym_writer,
280                     Elf64_Addr              value,
281                     Elf_Word                size,
282                     unsigned char           sym_info,
283                     unsigned char           other,
284                     Elf_Half                shndx,
285                     Elf64_Addr              offset,
286                     unsigned                type )
287     {
288         Elf_Word str_index = str_writer.add_string( str );
289         Elf_Word sym_index = sym_writer.add_symbol( str_index, value, size,
290                                                     sym_info, other, shndx );
291         add_entry( offset, sym_index, type );
292     }
293 
294     //------------------------------------------------------------------------------
swap_symbols(Elf_Xword first,Elf_Xword second)295     void swap_symbols( Elf_Xword first, Elf_Xword second )
296     {
297         Elf64_Addr offset = 0;
298         Elf_Word   symbol = 0;
299         unsigned   rtype  = 0;
300         Elf_Sxword addend = 0;
301         for ( Elf_Word i = 0; i < get_entries_num(); i++ ) {
302             get_entry( i, offset, symbol, rtype, addend );
303             if ( symbol == first ) {
304                 set_entry( i, offset, (Elf_Word)second, rtype, addend );
305             }
306             if ( symbol == second ) {
307                 set_entry( i, offset, (Elf_Word)first, rtype, addend );
308             }
309         }
310     }
311 
312     //------------------------------------------------------------------------------
313   private:
314     //------------------------------------------------------------------------------
get_symbol_table_index() const315     Elf_Half get_symbol_table_index() const
316     {
317         return (Elf_Half)relocation_section->get_link();
318     }
319 
320     //------------------------------------------------------------------------------
321     template <class T>
generic_get_entry_rel(Elf_Xword index,Elf64_Addr & offset,Elf_Word & symbol,unsigned & type,Elf_Sxword & addend) const322     void generic_get_entry_rel( Elf_Xword   index,
323                                 Elf64_Addr& offset,
324                                 Elf_Word&   symbol,
325                                 unsigned&   type,
326                                 Elf_Sxword& addend ) const
327     {
328         const endianess_convertor& convertor = elf_file.get_convertor();
329 
330         const T* pEntry = reinterpret_cast<const T*>(
331             relocation_section->get_data() +
332             index * relocation_section->get_entry_size() );
333         offset        = convertor( pEntry->r_offset );
334         Elf_Xword tmp = convertor( pEntry->r_info );
335         symbol        = get_sym_and_type<T>::get_r_sym( tmp );
336         type          = get_sym_and_type<T>::get_r_type( tmp );
337         addend        = 0;
338     }
339 
340     //------------------------------------------------------------------------------
341     template <class T>
generic_get_entry_rela(Elf_Xword index,Elf64_Addr & offset,Elf_Word & symbol,unsigned & type,Elf_Sxword & addend) const342     void generic_get_entry_rela( Elf_Xword   index,
343                                  Elf64_Addr& offset,
344                                  Elf_Word&   symbol,
345                                  unsigned&   type,
346                                  Elf_Sxword& addend ) const
347     {
348         const endianess_convertor& convertor = elf_file.get_convertor();
349 
350         const T* pEntry = reinterpret_cast<const T*>(
351             relocation_section->get_data() +
352             index * relocation_section->get_entry_size() );
353         offset        = convertor( pEntry->r_offset );
354         Elf_Xword tmp = convertor( pEntry->r_info );
355         symbol        = get_sym_and_type<T>::get_r_sym( tmp );
356         type          = get_sym_and_type<T>::get_r_type( tmp );
357         addend        = convertor( pEntry->r_addend );
358     }
359 
360     //------------------------------------------------------------------------------
361     template <class T>
generic_set_entry_rel(Elf_Xword index,Elf64_Addr offset,Elf_Word symbol,unsigned type,Elf_Sxword)362     void generic_set_entry_rel( Elf_Xword  index,
363                                 Elf64_Addr offset,
364                                 Elf_Word   symbol,
365                                 unsigned   type,
366                                 Elf_Sxword )
367     {
368         const endianess_convertor& convertor = elf_file.get_convertor();
369 
370         T* pEntry = const_cast<T*>( reinterpret_cast<const T*>(
371             relocation_section->get_data() +
372             index * relocation_section->get_entry_size() ) );
373 
374         if ( elf_file.get_class() == ELFCLASS32 ) {
375             pEntry->r_info = ELF32_R_INFO( (Elf_Xword)symbol, type );
376         }
377         else {
378             pEntry->r_info = ELF64_R_INFO( (Elf_Xword)symbol, type );
379         }
380         pEntry->r_offset = decltype( pEntry->r_offset )( offset );
381         pEntry->r_offset = convertor( pEntry->r_offset );
382         pEntry->r_info   = convertor( pEntry->r_info );
383     }
384 
385     //------------------------------------------------------------------------------
386     template <class T>
generic_set_entry_rela(Elf_Xword index,Elf64_Addr offset,Elf_Word symbol,unsigned type,Elf_Sxword addend)387     void generic_set_entry_rela( Elf_Xword  index,
388                                  Elf64_Addr offset,
389                                  Elf_Word   symbol,
390                                  unsigned   type,
391                                  Elf_Sxword addend )
392     {
393         const endianess_convertor& convertor = elf_file.get_convertor();
394 
395         T* pEntry = const_cast<T*>( reinterpret_cast<const T*>(
396             relocation_section->get_data() +
397             index * relocation_section->get_entry_size() ) );
398 
399         if ( elf_file.get_class() == ELFCLASS32 ) {
400             pEntry->r_info = ELF32_R_INFO( (Elf_Xword)symbol, type );
401         }
402         else {
403             pEntry->r_info = ELF64_R_INFO( (Elf_Xword)symbol, type );
404         }
405         pEntry->r_offset = decltype( pEntry->r_offset )( offset );
406         pEntry->r_addend = decltype( pEntry->r_addend )( addend );
407         pEntry->r_offset = convertor( pEntry->r_offset );
408         pEntry->r_info   = convertor( pEntry->r_info );
409         pEntry->r_addend = convertor( pEntry->r_addend );
410     }
411 
412     //------------------------------------------------------------------------------
413     template <class T>
generic_add_entry(Elf64_Addr offset,Elf_Xword info)414     void generic_add_entry( Elf64_Addr offset, Elf_Xword info )
415     {
416         const endianess_convertor& convertor = elf_file.get_convertor();
417 
418         T entry;
419         entry.r_offset = decltype( entry.r_offset )( offset );
420         entry.r_info   = decltype( entry.r_info )( info );
421         entry.r_offset = convertor( entry.r_offset );
422         entry.r_info   = convertor( entry.r_info );
423 
424         relocation_section->append_data( reinterpret_cast<char*>( &entry ),
425                                          sizeof( entry ) );
426     }
427 
428     //------------------------------------------------------------------------------
429     template <class T>
430     void
generic_add_entry(Elf64_Addr offset,Elf_Xword info,Elf_Sxword addend)431     generic_add_entry( Elf64_Addr offset, Elf_Xword info, Elf_Sxword addend )
432     {
433         const endianess_convertor& convertor = elf_file.get_convertor();
434 
435         T entry;
436         entry.r_offset = offset;
437         entry.r_info   = info;
438         entry.r_addend = addend;
439         entry.r_offset = convertor( entry.r_offset );
440         entry.r_info   = convertor( entry.r_info );
441         entry.r_addend = convertor( entry.r_addend );
442 
443         relocation_section->append_data( reinterpret_cast<char*>( &entry ),
444                                          sizeof( entry ) );
445     }
446 
447     //------------------------------------------------------------------------------
448   private:
449     const elfio& elf_file;
450     S*           relocation_section = nullptr;
451 };
452 
453 using relocation_section_accessor =
454     relocation_section_accessor_template<section>;
455 using const_relocation_section_accessor =
456     relocation_section_accessor_template<const section>;
457 
458 } // namespace ELFIO
459 
460 #endif // ELFIO_RELOCATION_HPP
461