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