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