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