• 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_DYNAMIC_HPP
24 #define ELFIO_DYNAMIC_HPP
25 
26 #include <algorithm>
27 
28 namespace ELFIO {
29 
30 //------------------------------------------------------------------------------
31 template <class S> class dynamic_section_accessor_template
32 {
33   public:
34     //------------------------------------------------------------------------------
dynamic_section_accessor_template(const elfio & elf_file,S * section)35     dynamic_section_accessor_template( const elfio& elf_file, S* section )
36         : elf_file( elf_file ), dynamic_section( section ), entries_num( 0 )
37     {
38     }
39 
40     //------------------------------------------------------------------------------
get_entries_num() const41     Elf_Xword get_entries_num() const
42     {
43         if ( ( 0 == entries_num ) &&
44              ( 0 != dynamic_section->get_entry_size() ) ) {
45             entries_num =
46                 dynamic_section->get_size() / dynamic_section->get_entry_size();
47             Elf_Xword   i;
48             Elf_Xword   tag;
49             Elf_Xword   value;
50             std::string str;
51             for ( i = 0; i < entries_num; i++ ) {
52                 get_entry( i, tag, value, str );
53                 if ( tag == DT_NULL )
54                     break;
55             }
56             entries_num = std::min<Elf_Xword>( entries_num, i + 1 );
57         }
58 
59         return entries_num;
60     }
61 
62     //------------------------------------------------------------------------------
get_entry(Elf_Xword index,Elf_Xword & tag,Elf_Xword & value,std::string & str) const63     bool get_entry( Elf_Xword    index,
64                     Elf_Xword&   tag,
65                     Elf_Xword&   value,
66                     std::string& str ) const
67     {
68         if ( index >= get_entries_num() ) { // Is index valid
69             return false;
70         }
71 
72         if ( elf_file.get_class() == ELFCLASS32 ) {
73             generic_get_entry_dyn<Elf32_Dyn>( index, tag, value );
74         }
75         else {
76             generic_get_entry_dyn<Elf64_Dyn>( index, tag, value );
77         }
78 
79         // If the tag may have a string table reference, prepare the string
80         if ( tag == DT_NEEDED || tag == DT_SONAME || tag == DT_RPATH ||
81              tag == DT_RUNPATH ) {
82             string_section_accessor strsec =
83                 elf_file.sections[get_string_table_index()];
84             const char* result = strsec.get_string( value );
85             if ( 0 == result ) {
86                 str.clear();
87                 return false;
88             }
89             str = result;
90         }
91         else {
92             str.clear();
93         }
94 
95         return true;
96     }
97 
98     //------------------------------------------------------------------------------
add_entry(Elf_Xword tag,Elf_Xword value)99     void add_entry( Elf_Xword tag, Elf_Xword value )
100     {
101         if ( elf_file.get_class() == ELFCLASS32 ) {
102             generic_add_entry_dyn<Elf32_Dyn>( tag, value );
103         }
104         else {
105             generic_add_entry_dyn<Elf64_Dyn>( tag, value );
106         }
107     }
108 
109     //------------------------------------------------------------------------------
add_entry(Elf_Xword tag,const std::string & str)110     void add_entry( Elf_Xword tag, const std::string& str )
111     {
112         string_section_accessor strsec =
113             elf_file.sections[get_string_table_index()];
114         Elf_Xword value = strsec.add_string( str );
115         add_entry( tag, value );
116     }
117 
118     //------------------------------------------------------------------------------
119   private:
120     //------------------------------------------------------------------------------
get_string_table_index() const121     Elf_Half get_string_table_index() const
122     {
123         return (Elf_Half)dynamic_section->get_link();
124     }
125 
126     //------------------------------------------------------------------------------
127     template <class T>
generic_get_entry_dyn(Elf_Xword index,Elf_Xword & tag,Elf_Xword & value) const128     void generic_get_entry_dyn( Elf_Xword  index,
129                                 Elf_Xword& tag,
130                                 Elf_Xword& value ) const
131     {
132         const endianess_convertor& convertor = elf_file.get_convertor();
133 
134         // Check unusual case when dynamic section has no data
135         if ( dynamic_section->get_data() == 0 ||
136              ( index + 1 ) * dynamic_section->get_entry_size() >
137                  dynamic_section->get_size() ) {
138             tag   = DT_NULL;
139             value = 0;
140             return;
141         }
142 
143         const T* pEntry = reinterpret_cast<const T*>(
144             dynamic_section->get_data() +
145             index * dynamic_section->get_entry_size() );
146         tag = convertor( pEntry->d_tag );
147         switch ( tag ) {
148         case DT_NULL:
149         case DT_SYMBOLIC:
150         case DT_TEXTREL:
151         case DT_BIND_NOW:
152             value = 0;
153             break;
154         case DT_NEEDED:
155         case DT_PLTRELSZ:
156         case DT_RELASZ:
157         case DT_RELAENT:
158         case DT_STRSZ:
159         case DT_SYMENT:
160         case DT_SONAME:
161         case DT_RPATH:
162         case DT_RELSZ:
163         case DT_RELENT:
164         case DT_PLTREL:
165         case DT_INIT_ARRAYSZ:
166         case DT_FINI_ARRAYSZ:
167         case DT_RUNPATH:
168         case DT_FLAGS:
169         case DT_PREINIT_ARRAYSZ:
170             value = convertor( pEntry->d_un.d_val );
171             break;
172         case DT_PLTGOT:
173         case DT_HASH:
174         case DT_STRTAB:
175         case DT_SYMTAB:
176         case DT_RELA:
177         case DT_INIT:
178         case DT_FINI:
179         case DT_REL:
180         case DT_DEBUG:
181         case DT_JMPREL:
182         case DT_INIT_ARRAY:
183         case DT_FINI_ARRAY:
184         case DT_PREINIT_ARRAY:
185         default:
186             value = convertor( pEntry->d_un.d_ptr );
187             break;
188         }
189     }
190 
191     //------------------------------------------------------------------------------
generic_add_entry_dyn(Elf_Xword tag,Elf_Xword value)192     template <class T> void generic_add_entry_dyn( Elf_Xword tag, Elf_Xword value )
193     {
194         const endianess_convertor& convertor = elf_file.get_convertor();
195 
196         T entry;
197 
198         switch ( tag ) {
199         case DT_NULL:
200         case DT_SYMBOLIC:
201         case DT_TEXTREL:
202         case DT_BIND_NOW:
203             value = 0;
204         case DT_NEEDED:
205         case DT_PLTRELSZ:
206         case DT_RELASZ:
207         case DT_RELAENT:
208         case DT_STRSZ:
209         case DT_SYMENT:
210         case DT_SONAME:
211         case DT_RPATH:
212         case DT_RELSZ:
213         case DT_RELENT:
214         case DT_PLTREL:
215         case DT_INIT_ARRAYSZ:
216         case DT_FINI_ARRAYSZ:
217         case DT_RUNPATH:
218         case DT_FLAGS:
219         case DT_PREINIT_ARRAYSZ:
220             entry.d_un.d_val = convertor( value );
221             break;
222         case DT_PLTGOT:
223         case DT_HASH:
224         case DT_STRTAB:
225         case DT_SYMTAB:
226         case DT_RELA:
227         case DT_INIT:
228         case DT_FINI:
229         case DT_REL:
230         case DT_DEBUG:
231         case DT_JMPREL:
232         case DT_INIT_ARRAY:
233         case DT_FINI_ARRAY:
234         case DT_PREINIT_ARRAY:
235         default:
236             entry.d_un.d_ptr = convertor( value );
237             break;
238         }
239 
240         entry.d_tag = convertor( tag );
241 
242         dynamic_section->append_data( reinterpret_cast<char*>( &entry ),
243                                       sizeof( entry ) );
244     }
245 
246     //------------------------------------------------------------------------------
247   private:
248     const elfio&      elf_file;
249     S*                dynamic_section;
250     mutable Elf_Xword entries_num;
251 };
252 
253 using dynamic_section_accessor = dynamic_section_accessor_template<section>;
254 using const_dynamic_section_accessor =
255     dynamic_section_accessor_template<const section>;
256 
257 } // namespace ELFIO
258 
259 #endif // ELFIO_DYNAMIC_HPP
260