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