| skipped 92 lines |
93 | 93 | | binary_->sizing_info_->dynamic = size; |
94 | 94 | | } |
95 | 95 | | |
| 96 | + | process_dynamic_table<ELF_T>(); |
| 97 | + | |
| 98 | + | if (const Section* sec_symbtab = binary_->get(Section::TYPE::SYMTAB)) { |
| 99 | + | auto nb_entries = static_cast<uint32_t>((sec_symbtab->size() / sizeof(typename ELF_T::Elf_Sym))); |
| 100 | + | nb_entries = std::min(nb_entries, Parser::NB_MAX_SYMBOLS); |
| 101 | + | |
| 102 | + | if (sec_symbtab->link() == 0 || sec_symbtab->link() >= binary_->sections_.size()) { |
| 103 | + | LIEF_WARN("section->link() is not valid !"); |
| 104 | + | } else { |
| 105 | + | if (config_.parse_symtab_symbols) { |
| 106 | + | // We should have: |
| 107 | + | // nb_entries == section->information()) |
| 108 | + | // but lots of compiler not respect this rule |
| 109 | + | parse_symtab_symbols<ELF_T>(sec_symbtab->file_offset(), nb_entries, |
| 110 | + | *binary_->sections_[sec_symbtab->link()]); |
| 111 | + | } |
| 112 | + | } |
| 113 | + | } |
| 114 | + | |
| 115 | + | |
| 116 | + | // Parse Symbols's hash |
| 117 | + | // ==================== |
| 118 | + | if (DynamicEntry* dt_hash = binary_->get(DynamicEntry::TAG::HASH)) { |
| 119 | + | if (auto res = binary_->virtual_address_to_offset(dt_hash->value())) { |
| 120 | + | parse_symbol_sysv_hash(*res); |
| 121 | + | } else { |
| 122 | + | LIEF_WARN("Can't convert DT_HASH.virtual_address into an offset (0x{:x})", dt_hash->value()); |
| 123 | + | } |
| 124 | + | } |
| 125 | + | |
| 126 | + | |
| 127 | + | if (DynamicEntry* dt_gnu_hash = binary_->get(DynamicEntry::TAG::GNU_HASH)) { |
| 128 | + | if (auto res = binary_->virtual_address_to_offset(dt_gnu_hash->value())) { |
| 129 | + | parse_symbol_gnu_hash<ELF_T>(*res); |
| 130 | + | } else { |
| 131 | + | LIEF_WARN("Can't convert DT_GNU_HASH.virtual_address into an offset (0x{:x})", dt_gnu_hash->value()); |
| 132 | + | } |
| 133 | + | } |
| 134 | + | |
| 135 | + | if (config_.parse_notes) { |
| 136 | + | // Parse Note segment |
| 137 | + | // ================== |
| 138 | + | for (const Segment& segment : binary_->segments()) { |
| 139 | + | if (segment.type() != Segment::TYPE::NOTE) { |
| 140 | + | continue; |
| 141 | + | } |
| 142 | + | parse_notes(segment.file_offset(), segment.physical_size()); |
| 143 | + | } |
| 144 | + | |
| 145 | + | // Parse Note Sections |
| 146 | + | // =================== |
| 147 | + | for (const Section& section : binary_->sections()) { |
| 148 | + | if (section.type() != Section::TYPE::NOTE) { |
| 149 | + | continue; |
| 150 | + | } |
| 151 | + | LIEF_DEBUG("Notes from section: {}", section.name()); |
| 152 | + | parse_notes(section.offset(), section.size()); |
| 153 | + | } |
| 154 | + | } |
96 | 155 | | |
97 | | - | // Parse dynamic symbols |
98 | | - | // ===================== |
| 156 | + | // Try to parse using sections |
| 157 | + | // If we don't have any relocations, we parse all relocation sections |
| 158 | + | // otherwise, only the non-allocated sections to avoid parsing dynamic |
| 159 | + | // relocations (or plt relocations) twice. |
| 160 | + | if (config_.parse_relocations) { |
| 161 | + | bool skip_allocated_sections = !binary_->relocations_.empty(); |
| 162 | + | for (const Section& section : binary_->sections()) { |
| 163 | + | if (skip_allocated_sections && section.has(Section::FLAGS::ALLOC)){ |
| 164 | + | continue; |
| 165 | + | } |
| 166 | + | if (section.type() == Section::TYPE::REL) { |
| 167 | + | parse_section_relocations<ELF_T, typename ELF_T::Elf_Rel>(section); |
| 168 | + | } |
| 169 | + | else if (section.type() == Section::TYPE::RELA) { |
| 170 | + | parse_section_relocations<ELF_T, typename ELF_T::Elf_Rela>(section); |
| 171 | + | } |
| 172 | + | } |
| 173 | + | } |
| 174 | + | if (config_.parse_symbol_versions) { |
| 175 | + | link_symbol_version(); |
| 176 | + | } |
| 177 | + | |
| 178 | + | if (config_.parse_overlay) { |
| 179 | + | parse_overlay(); |
| 180 | + | } |
| 181 | + | return ok(); |
| 182 | + | } |
| 183 | + | |
| 184 | + | |
| 185 | + | template<typename ELF_T> |
| 186 | + | ok_error_t Parser::process_dynamic_table() { |
99 | 187 | | { |
100 | 188 | | DynamicEntry* dt_symtab = binary_->get(DynamicEntry::TAG::SYMTAB); |
101 | 189 | | DynamicEntry* dt_syment = binary_->get(DynamicEntry::TAG::SYMENT); |
| skipped 7 lines |
109 | 197 | | } |
110 | 198 | | } |
111 | 199 | | } |
112 | | - | |
113 | | - | // Parse dynamic relocations |
114 | | - | // ========================= |
115 | | - | |
116 | | - | // RELA |
117 | | - | // ---- |
118 | 200 | | { |
119 | 201 | | DynamicEntry* dt_rela = binary_->get(DynamicEntry::TAG::RELA); |
120 | 202 | | DynamicEntry* dt_relasz = binary_->get(DynamicEntry::TAG::RELASZ); |
| skipped 9 lines |
130 | 212 | | } |
131 | 213 | | } |
132 | 214 | | } |
133 | | - | |
134 | | - | |
135 | | - | // REL |
136 | | - | // --- |
137 | 215 | | { |
138 | 216 | | DynamicEntry* dt_rel = binary_->get(DynamicEntry::TAG::REL); |
139 | 217 | | DynamicEntry* dt_relsz = binary_->get(DynamicEntry::TAG::RELSZ); |
| skipped 9 lines |
149 | 227 | | } |
150 | 228 | | } |
151 | 229 | | } |
| 230 | + | { |
| 231 | + | DynamicEntry* dt_relr = binary_->get(DynamicEntry::TAG::RELR); |
| 232 | + | DynamicEntry* dt_relrsz = binary_->get(DynamicEntry::TAG::RELRSZ); |
152 | 233 | | |
153 | | - | // Parse PLT/GOT Relocations |
154 | | - | // ========================== |
| 234 | + | if (dt_relr != nullptr && dt_relrsz != nullptr && config_.parse_relocations) { |
| 235 | + | const uint64_t virtual_address = dt_relr->value(); |
| 236 | + | const uint64_t size = dt_relrsz->value(); |
| 237 | + | if (auto res = binary_->virtual_address_to_offset(virtual_address)) { |
| 238 | + | parse_relative_relocations<ELF_T>(*res, size); |
| 239 | + | binary_->sizing_info_->relr = size; |
| 240 | + | } else { |
| 241 | + | LIEF_WARN("Can't convert DT_RELR.virtual_address into an offset (0x{:x})", virtual_address); |
| 242 | + | } |
| 243 | + | } |
| 244 | + | } |
| 245 | + | { |
| 246 | + | DynamicEntry* dt_relr = binary_->get(DynamicEntry::TAG::ANDROID_RELR); |
| 247 | + | DynamicEntry* dt_relrsz = binary_->get(DynamicEntry::TAG::ANDROID_RELRSZ); |
| 248 | + | |
| 249 | + | if (dt_relr != nullptr && dt_relrsz != nullptr && config_.parse_relocations) { |
| 250 | + | const uint64_t virtual_address = dt_relr->value(); |
| 251 | + | const uint64_t size = dt_relrsz->value(); |
| 252 | + | if (auto res = binary_->virtual_address_to_offset(virtual_address)) { |
| 253 | + | parse_relative_relocations<ELF_T>(*res, size); |
| 254 | + | binary_->sizing_info_->relr = size; |
| 255 | + | } else { |
| 256 | + | LIEF_WARN("Can't convert (Android)DT_RELR.virtual_address into an offset (0x{:x})", virtual_address); |
| 257 | + | } |
| 258 | + | } |
| 259 | + | } |
| 260 | + | { |
| 261 | + | DynamicEntry* dt_rela = binary_->get(DynamicEntry::TAG::ANDROID_RELA); |
| 262 | + | DynamicEntry* dt_relasz = binary_->get(DynamicEntry::TAG::ANDROID_RELASZ); |
| 263 | + | if (dt_rela == nullptr) { |
| 264 | + | dt_rela = binary_->get(DynamicEntry::TAG::ANDROID_REL); |
| 265 | + | dt_relasz = binary_->get(DynamicEntry::TAG::ANDROID_RELSZ); |
| 266 | + | } |
| 267 | + | |
| 268 | + | if (dt_rela != nullptr && dt_relasz != nullptr && config_.parse_relocations) { |
| 269 | + | const uint64_t virtual_address = dt_rela->value(); |
| 270 | + | const uint64_t size = dt_relasz->value(); |
| 271 | + | if (auto res = binary_->virtual_address_to_offset(virtual_address)) { |
| 272 | + | parse_packed_relocations<ELF_T>(*res, size); |
| 273 | + | binary_->sizing_info_->android_rela = size; |
| 274 | + | } else { |
| 275 | + | LIEF_WARN("Can't convert DT_ANDROID_REL[A].virtual_address into an offset (0x{:x})", virtual_address); |
| 276 | + | } |
| 277 | + | } |
| 278 | + | } |
155 | 279 | | { |
156 | 280 | | DynamicEntry* dt_jmprel = binary_->get(DynamicEntry::TAG::JMPREL); |
157 | 281 | | DynamicEntry* dt_pltrelsz = binary_->get(DynamicEntry::TAG::PLTRELSZ); |
| skipped 24 lines |
182 | 306 | | } |
183 | 307 | | } |
184 | 308 | | } |
185 | | - | |
186 | | - | // Parse Symbol Version |
187 | | - | // ==================== |
188 | 309 | | if (config_.parse_symbol_versions && config_.parse_dyn_symbols) { |
189 | 310 | | if (DynamicEntry* dt_versym = binary_->get(DynamicEntry::TAG::VERSYM)) { |
190 | 311 | | const uint64_t virtual_address = dt_versym->value(); |
| skipped 6 lines |
197 | 318 | | } |
198 | 319 | | } |
199 | 320 | | |
200 | | - | |
201 | | - | // Parse Symbol Version Requirement |
202 | | - | // ================================ |
203 | 321 | | if (config_.parse_symbol_versions) { |
204 | 322 | | DynamicEntry* dt_verneed = binary_->get(DynamicEntry::TAG::VERNEED); |
205 | 323 | | DynamicEntry* dt_verneed_num = binary_->get(DynamicEntry::TAG::VERNEEDNUM); |
| skipped 11 lines |
217 | 335 | | } |
218 | 336 | | } |
219 | 337 | | |
220 | | - | // Parse Symbol Version Definition |
221 | | - | // =============================== |
222 | 338 | | if (config_.parse_symbol_versions) { |
223 | 339 | | DynamicEntry* dt_verdef = binary_->get(DynamicEntry::TAG::VERDEF); |
224 | 340 | | DynamicEntry* dt_verdef_num = binary_->get(DynamicEntry::TAG::VERDEFNUM); |
| skipped 9 lines |
234 | 350 | | } |
235 | 351 | | } |
236 | 352 | | |
237 | | - | if (const Section* sec_symbtab = binary_->get(Section::TYPE::SYMTAB)) { |
238 | | - | auto nb_entries = static_cast<uint32_t>((sec_symbtab->size() / sizeof(typename ELF_T::Elf_Sym))); |
239 | | - | nb_entries = std::min(nb_entries, Parser::NB_MAX_SYMBOLS); |
240 | | - | |
241 | | - | if (sec_symbtab->link() == 0 || sec_symbtab->link() >= binary_->sections_.size()) { |
242 | | - | LIEF_WARN("section->link() is not valid !"); |
243 | | - | } else { |
244 | | - | if (config_.parse_symtab_symbols) { |
245 | | - | // We should have: |
246 | | - | // nb_entries == section->information()) |
247 | | - | // but lots of compiler not respect this rule |
248 | | - | parse_symtab_symbols<ELF_T>(sec_symbtab->file_offset(), nb_entries, |
249 | | - | *binary_->sections_[sec_symbtab->link()]); |
250 | | - | } |
251 | | - | } |
252 | | - | } |
253 | | - | |
254 | | - | |
255 | | - | // Parse Symbols's hash |
256 | | - | // ==================== |
257 | | - | if (DynamicEntry* dt_hash = binary_->get(DynamicEntry::TAG::HASH)) { |
258 | | - | if (auto res = binary_->virtual_address_to_offset(dt_hash->value())) { |
259 | | - | parse_symbol_sysv_hash(*res); |
260 | | - | } else { |
261 | | - | LIEF_WARN("Can't convert DT_HASH.virtual_address into an offset (0x{:x})", dt_hash->value()); |
262 | | - | } |
263 | | - | } |
264 | | - | |
265 | | - | |
266 | | - | if (DynamicEntry* dt_gnu_hash = binary_->get(DynamicEntry::TAG::GNU_HASH)) { |
267 | | - | if (auto res = binary_->virtual_address_to_offset(dt_gnu_hash->value())) { |
268 | | - | parse_symbol_gnu_hash<ELF_T>(*res); |
269 | | - | } else { |
270 | | - | LIEF_WARN("Can't convert DT_GNU_HASH.virtual_address into an offset (0x{:x})", dt_gnu_hash->value()); |
271 | | - | } |
272 | | - | } |
273 | | - | |
274 | | - | if (config_.parse_notes) { |
275 | | - | // Parse Note segment |
276 | | - | // ================== |
277 | | - | for (const Segment& segment : binary_->segments()) { |
278 | | - | if (segment.type() != Segment::TYPE::NOTE) { |
279 | | - | continue; |
280 | | - | } |
281 | | - | parse_notes(segment.file_offset(), segment.physical_size()); |
282 | | - | } |
283 | | - | |
284 | | - | // Parse Note Sections |
285 | | - | // =================== |
286 | | - | for (const Section& section : binary_->sections()) { |
287 | | - | if (section.type() != Section::TYPE::NOTE) { |
288 | | - | continue; |
289 | | - | } |
290 | | - | LIEF_DEBUG("Notes from section: {}", section.name()); |
291 | | - | parse_notes(section.offset(), section.size()); |
292 | | - | } |
293 | | - | } |
294 | | - | |
295 | | - | // Try to parse using sections |
296 | | - | // If we don't have any relocations, we parse all relocation sections |
297 | | - | // otherwise, only the non-allocated sections to avoid parsing dynamic |
298 | | - | // relocations (or plt relocations) twice. |
299 | | - | if (config_.parse_relocations) { |
300 | | - | bool skip_allocated_sections = !binary_->relocations_.empty(); |
301 | | - | for (const Section& section : binary_->sections()) { |
302 | | - | if (skip_allocated_sections && section.has(Section::FLAGS::ALLOC)){ |
303 | | - | continue; |
304 | | - | } |
305 | | - | if (section.type() == Section::TYPE::REL) { |
306 | | - | parse_section_relocations<ELF_T, typename ELF_T::Elf_Rel>(section); |
307 | | - | } |
308 | | - | else if (section.type() == Section::TYPE::RELA) { |
309 | | - | parse_section_relocations<ELF_T, typename ELF_T::Elf_Rela>(section); |
310 | | - | } |
311 | | - | } |
312 | | - | } |
313 | | - | if (config_.parse_symbol_versions) { |
314 | | - | link_symbol_version(); |
315 | | - | } |
316 | | - | |
317 | | - | if (config_.parse_overlay) { |
318 | | - | parse_overlay(); |
319 | | - | } |
320 | 353 | | return ok(); |
321 | 354 | | } |
322 | | - | |
323 | 355 | | |
324 | 356 | | template<typename ELF_T> |
325 | 357 | | ok_error_t Parser::parse_header() { |
| skipped 605 lines |
931 | 963 | | } |
932 | 964 | | |
933 | 965 | | |
| 966 | + | template<typename ELF_T> |
| 967 | + | ok_error_t Parser::parse_packed_relocations(uint64_t offset, uint64_t size) { |
| 968 | + | using Elf_Rela = typename ELF_T::Elf_Rela; |
| 969 | + | static constexpr uint64_t GROUPED_BY_INFO_FLAG = 1 << 0; |
| 970 | + | static constexpr uint64_t GROUPED_BY_OFFSET_DELTA_FLAG = 1 << 1; |
| 971 | + | static constexpr uint64_t GROUPED_BY_ADDEND_FLAG = 1 << 2; |
| 972 | + | static constexpr uint64_t GROUP_HAS_ADDEND_FLAG = 1 << 3; |
| 973 | + | |
| 974 | + | LIEF_DEBUG("Parsing Android packed relocations"); |
| 975 | + | if (size < 4) { |
| 976 | + | LIEF_ERR("Invalid Android packed relocation header"); |
| 977 | + | return make_error_code(lief_errors::read_error); |
| 978 | + | } |
| 979 | + | ScopedStream rel_stream(*stream_, offset); |
| 980 | + | |
| 981 | + | const auto H0 = stream_->read<char>().value_or(0); |
| 982 | + | const auto H1 = stream_->read<char>().value_or(0); |
| 983 | + | const auto H2 = stream_->read<char>().value_or(0); |
| 984 | + | const auto H3 = stream_->read<char>().value_or(0); |
| 985 | + | |
| 986 | + | LIEF_DEBUG("Header: {} {} {} {}", H0, H1, H2, H3); |
| 987 | + | |
| 988 | + | // Check for the Magic: APS2 |
| 989 | + | if (H0 != 'A' || H1 != 'P' || H2 != 'S' || H3 != '2') { |
| 990 | + | LIEF_ERR("Invalid Android packed relocation magic header: " |
| 991 | + | "{} {} {} {}", H0, H1, H2, H3); |
| 992 | + | return make_error_code(lief_errors::read_error); |
| 993 | + | } |
| 994 | + | |
| 995 | + | auto res_nb_relocs = rel_stream->read_sleb128(); |
| 996 | + | if (!res_nb_relocs) { |
| 997 | + | LIEF_ERR("Can't read number of relocations"); |
| 998 | + | return make_error_code(lief_errors::read_error); |
| 999 | + | } |
| 1000 | + | auto res_rels_offset = rel_stream->read_sleb128(); |
| 1001 | + | if (!res_rels_offset) { |
| 1002 | + | LIEF_ERR("Can't read offset"); |
| 1003 | + | return make_error_code(lief_errors::read_error); |
| 1004 | + | } |
| 1005 | + | |
| 1006 | + | uint64_t nb_relocs = *res_nb_relocs; |
| 1007 | + | uint64_t r_offset = *res_rels_offset; |
| 1008 | + | uint64_t addend = 0; |
| 1009 | + | const ARCH arch = binary_->header().machine_type(); |
| 1010 | + | |
| 1011 | + | LIEF_DEBUG("Nb relocs: {}", nb_relocs); |
| 1012 | + | |
| 1013 | + | while (nb_relocs > 0) { |
| 1014 | + | auto nb_reloc_group_r = rel_stream->read_sleb128(); |
| 1015 | + | if (!nb_reloc_group_r) { |
| 1016 | + | break; |
| 1017 | + | } |
| 1018 | + | |
| 1019 | + | uint64_t nb_reloc_group = *nb_reloc_group_r; |
| 1020 | + | LIEF_DEBUG(" Nb relocs in group: {}", nb_reloc_group); |
| 1021 | + | |
| 1022 | + | if (nb_reloc_group > nb_relocs) { |
| 1023 | + | break; |
| 1024 | + | } |
| 1025 | + | |
| 1026 | + | nb_relocs -= nb_reloc_group; |
| 1027 | + | |
| 1028 | + | auto group_flag_r = rel_stream->read_sleb128(); |
| 1029 | + | if (!group_flag_r) { |
| 1030 | + | LIEF_ERR("Can't read group flag"); |
| 1031 | + | break; |
| 1032 | + | } |
| 1033 | + | uint64_t group_flag = *group_flag_r; |
| 1034 | + | |
| 1035 | + | const bool g_by_info = group_flag & GROUPED_BY_INFO_FLAG; |
| 1036 | + | const bool g_by_offset_delta = group_flag & GROUPED_BY_OFFSET_DELTA_FLAG; |
| 1037 | + | const bool g_by_addend = group_flag & GROUPED_BY_ADDEND_FLAG; |
| 1038 | + | const bool g_has_addend = group_flag & GROUP_HAS_ADDEND_FLAG; |
| 1039 | + | |
| 1040 | + | uint64_t group_off_delta = |
| 1041 | + | g_by_offset_delta ? rel_stream->read_sleb128().value_or(0) : 0; |
| 1042 | + | |
| 1043 | + | uint64_t groupr_info = |
| 1044 | + | g_by_info ? rel_stream->read_sleb128().value_or(0) : 0; |
| 1045 | + | |
| 1046 | + | if (g_by_addend && g_has_addend) { |
| 1047 | + | addend += rel_stream->read_sleb128().value_or(0); |
| 1048 | + | } |
| 1049 | + | |
| 1050 | + | if (!g_has_addend) { |
| 1051 | + | addend = 0; |
| 1052 | + | } |
| 1053 | + | |
| 1054 | + | for (size_t i = 0; i < nb_reloc_group; ++i) { |
| 1055 | + | if (!*rel_stream) { |
| 1056 | + | break; |
| 1057 | + | } |
| 1058 | + | r_offset += g_by_offset_delta ? group_off_delta : rel_stream->read_sleb128().value_or(0); |
| 1059 | + | uint64_t info = g_by_info ? groupr_info : rel_stream->read_sleb128().value_or(0); |
| 1060 | + | if (g_has_addend && !g_by_addend) { |
| 1061 | + | addend += rel_stream->read_sleb128().value_or(0); |
| 1062 | + | } |
| 1063 | + | |
| 1064 | + | Elf_Rela R; |
| 1065 | + | R.r_info = info; |
| 1066 | + | R.r_addend = addend; |
| 1067 | + | R.r_offset = r_offset; |
| 1068 | + | auto reloc = std::unique_ptr<Relocation>(new Relocation(R, Relocation::PURPOSE::DYNAMIC, |
| 1069 | + | Relocation::ENCODING::ANDROID_SLEB, arch)); |
| 1070 | + | bind_symbol(*reloc); |
| 1071 | + | binary_->relocations_.push_back(std::move(reloc)); |
| 1072 | + | } |
| 1073 | + | } |
| 1074 | + | return ok(); |
| 1075 | + | } |
| 1076 | + | |
| 1077 | + | template<typename ELF_T> |
| 1078 | + | ok_error_t Parser::parse_relative_relocations(uint64_t offset, uint64_t size) { |
| 1079 | + | LIEF_DEBUG("Parsing relative relocations"); |
| 1080 | + | using Elf_Relr = typename ELF_T::uint; |
| 1081 | + | using Elf_Addr = typename ELF_T::uint; |
| 1082 | + | ScopedStream rel_stream(*stream_, offset); |
| 1083 | + | |
| 1084 | + | Elf_Addr base = 0; |
| 1085 | + | const ARCH arch = binary_->header().machine_type(); |
| 1086 | + | Relocation::TYPE type = Relocation::TYPE::UNKNOWN; |
| 1087 | + | switch (arch) { |
| 1088 | + | case ARCH::AARCH64: |
| 1089 | + | type = Relocation::TYPE::AARCH64_RELATIVE; break; |
| 1090 | + | case ARCH::X86_64: |
| 1091 | + | type = Relocation::TYPE::X86_64_RELATIVE; break; |
| 1092 | + | case ARCH::ARM: |
| 1093 | + | type = Relocation::TYPE::ARM_RELATIVE; break; |
| 1094 | + | case ARCH::HEXAGON: |
| 1095 | + | type = Relocation::TYPE::HEX_RELATIVE; break; |
| 1096 | + | case ARCH::PPC64: |
| 1097 | + | type = Relocation::TYPE::PPC64_RELATIVE; break; |
| 1098 | + | case ARCH::PPC: |
| 1099 | + | type = Relocation::TYPE::PPC_RELATIVE; break; |
| 1100 | + | case ARCH::I386: |
| 1101 | + | case ARCH::IAMCU: |
| 1102 | + | type = Relocation::TYPE::X86_RELATIVE; break; |
| 1103 | + | default: |
| 1104 | + | break; |
| 1105 | + | } |
| 1106 | + | |
| 1107 | + | while (rel_stream->pos() < (offset + size)) { |
| 1108 | + | auto opt_relr = rel_stream->read<Elf_Relr>(); |
| 1109 | + | if (!opt_relr) { |
| 1110 | + | break; |
| 1111 | + | } |
| 1112 | + | Elf_Relr rel = *opt_relr; |
| 1113 | + | if ((rel & 1) == 0) { |
| 1114 | + | Elf_Addr r_offset = rel; |
| 1115 | + | auto reloc = std::make_unique<Relocation>(r_offset, type, |
| 1116 | + | Relocation::ENCODING::RELR); |
| 1117 | + | reloc->purpose(Relocation::PURPOSE::DYNAMIC); |
| 1118 | + | binary_->relocations_.push_back(std::move(reloc)); |
| 1119 | + | base = rel + sizeof(Elf_Addr); |
| 1120 | + | } else { |
| 1121 | + | for (Elf_Addr offset = base; (rel >>= 1) != 0; offset += sizeof(Elf_Addr)) { |
| 1122 | + | if ((rel & 1) != 0) { |
| 1123 | + | Elf_Addr r_offset = offset; |
| 1124 | + | auto reloc = std::make_unique<Relocation>(r_offset, type, |
| 1125 | + | Relocation::ENCODING::RELR); |
| 1126 | + | reloc->purpose(Relocation::PURPOSE::DYNAMIC); |
| 1127 | + | binary_->relocations_.push_back(std::move(reloc)); |
| 1128 | + | } |
| 1129 | + | } |
| 1130 | + | base += (8 * sizeof(Elf_Relr) - 1) * sizeof(Elf_Addr); |
| 1131 | + | } |
| 1132 | + | } |
| 1133 | + | return ok(); |
| 1134 | + | } |
| 1135 | + | |
934 | 1136 | | |
935 | 1137 | | template<typename ELF_T, typename REL_T> |
936 | 1138 | | ok_error_t Parser::parse_dynamic_relocations(uint64_t relocations_offset, uint64_t size) { |
937 | | - | static_assert(std::is_same<REL_T, typename ELF_T::Elf_Rel>::value || |
938 | | - | std::is_same<REL_T, typename ELF_T::Elf_Rela>::value, "REL_T must be Elf_Rel || Elf_Rela"); |
| 1139 | + | static_assert(std::is_same_v<REL_T, typename ELF_T::Elf_Rel> || |
| 1140 | + | std::is_same_v<REL_T, typename ELF_T::Elf_Rela>, "REL_T must be Elf_Rel || Elf_Rela"); |
939 | 1141 | | LIEF_DEBUG("== Parsing dynamic relocations =="); |
940 | 1142 | | |
941 | 1143 | | // Already parsed |
| skipped 1 lines |
943 | 1145 | | return ok(); |
944 | 1146 | | } |
945 | 1147 | | |
946 | | - | const uint8_t shift = std::is_same<ELF_T, details::ELF32>::value ? 8 : 32; |
947 | | - | |
948 | 1148 | | auto nb_entries = static_cast<uint32_t>(size / sizeof(REL_T)); |
949 | 1149 | | |
950 | 1150 | | nb_entries = std::min<uint32_t>(nb_entries, Parser::NB_MAX_RELOCATIONS); |
| skipped 1 lines |
952 | 1152 | | |
953 | 1153 | | stream_->setpos(relocations_offset); |
954 | 1154 | | const ARCH arch = binary_->header().machine_type(); |
| 1155 | + | const Relocation::ENCODING enc = |
| 1156 | + | std::is_same_v<REL_T, typename ELF_T::Elf_Rel> ? Relocation::ENCODING::REL : |
| 1157 | + | Relocation::ENCODING::RELA; |
| 1158 | + | |
955 | 1159 | | for (uint32_t i = 0; i < nb_entries; ++i) { |
956 | 1160 | | const auto raw_reloc = stream_->read_conv<REL_T>(); |
957 | 1161 | | if (!raw_reloc) { |
958 | 1162 | | break; |
959 | 1163 | | } |
960 | | - | auto reloc = std::make_unique<Relocation>( |
961 | | - | std::move(*raw_reloc), Relocation::PURPOSE::DYNAMIC, arch); |
962 | 1164 | | |
963 | | - | const auto idx = static_cast<uint32_t>(raw_reloc->r_info >> shift); |
964 | | - | if (config_.parse_dyn_symbols) { |
965 | | - | if (idx < binary_->dynamic_symbols_.size()) { |
966 | | - | reloc->symbol_ = binary_->dynamic_symbols_[idx].get(); |
967 | | - | } else { |
968 | | - | LIEF_WARN("Unable to find the symbol associated with the relocation " |
969 | | - | "(idx: {}) {}", idx, to_string(*reloc)); |
970 | | - | } |
971 | | - | } |
| 1165 | + | auto reloc = std::unique_ptr<Relocation>(new Relocation( |
| 1166 | + | std::move(*raw_reloc), Relocation::PURPOSE::DYNAMIC, enc, arch)); |
| 1167 | + | bind_symbol(*reloc); |
972 | 1168 | | |
973 | 1169 | | binary_->relocations_.push_back(std::move(reloc)); |
974 | 1170 | | } |
| skipped 317 lines |
1292 | 1488 | | } |
1293 | 1489 | | |
1294 | 1490 | | const Elf_Off offset_relocations = offset; |
1295 | | - | const uint8_t shift = std::is_same<ELF_T, details::ELF32>::value ? 8 : 32; |
1296 | 1491 | | |
1297 | 1492 | | auto nb_entries = static_cast<uint32_t>(size / sizeof(REL_T)); |
1298 | 1493 | | |
1299 | 1494 | | nb_entries = std::min<uint32_t>(nb_entries, Parser::NB_MAX_RELOCATIONS); |
1300 | 1495 | | |
1301 | 1496 | | const ARCH arch = binary_->header_.machine_type(); |
| 1497 | + | const Relocation::ENCODING enc = |
| 1498 | + | std::is_same_v<REL_T, typename ELF_T::Elf_Rel> ? Relocation::ENCODING::REL : |
| 1499 | + | Relocation::ENCODING::RELA; |
1302 | 1500 | | stream_->setpos(offset_relocations); |
1303 | 1501 | | for (uint32_t i = 0; i < nb_entries; ++i) { |
1304 | 1502 | | const auto rel_hdr = stream_->read_conv<REL_T>(); |
| skipped 1 lines |
1306 | 1504 | | break; |
1307 | 1505 | | } |
1308 | 1506 | | |
1309 | | - | auto reloc = std::make_unique<Relocation>( |
1310 | | - | std::move(*rel_hdr), Relocation::PURPOSE::PLTGOT, arch); |
1311 | | - | |
1312 | | - | const auto idx = static_cast<uint32_t>(rel_hdr->r_info >> shift); |
1313 | | - | if (config_.parse_dyn_symbols && |
1314 | | - | 0 < idx && idx < binary_->dynamic_symbols_.size()) |
1315 | | - | { |
1316 | | - | reloc->symbol_ = binary_->dynamic_symbols_[idx].get(); |
1317 | | - | } |
1318 | | - | |
| 1507 | + | auto reloc = std::unique_ptr<Relocation>(new Relocation( |
| 1508 | + | std::move(*rel_hdr), Relocation::PURPOSE::PLTGOT, enc, arch)); |
| 1509 | + | bind_symbol(*reloc); |
1319 | 1510 | | binary_->relocations_.push_back(std::move(reloc)); |
1320 | 1511 | | } |
1321 | 1512 | | return ok(); |
| skipped 61 lines |
1383 | 1574 | | const uint64_t offset_relocations = section.file_offset(); |
1384 | 1575 | | const uint8_t shift = std::is_same<ELF_T, details::ELF32>::value ? 8 : 32; |
1385 | 1576 | | |
| 1577 | + | const ARCH arch = binary_->header_.machine_type(); |
| 1578 | + | |
| 1579 | + | const Relocation::ENCODING enc = |
| 1580 | + | std::is_same_v<REL_T, typename ELF_T::Elf_Rel> ? Relocation::ENCODING::REL : |
| 1581 | + | Relocation::ENCODING::RELA; |
| 1582 | + | |
1386 | 1583 | | auto nb_entries = static_cast<uint32_t>(section.size() / sizeof(REL_T)); |
1387 | 1584 | | nb_entries = std::min<uint32_t>(nb_entries, Parser::NB_MAX_RELOCATIONS); |
1388 | 1585 | | |
| skipped 5 lines |
1394 | 1591 | | break; |
1395 | 1592 | | } |
1396 | 1593 | | |
1397 | | - | auto reloc = std::make_unique<Relocation>( |
1398 | | - | *rel_hdr, Relocation::PURPOSE::NONE, binary_->header_.machine_type()); |
| 1594 | + | auto reloc = std::unique_ptr<Relocation>(new Relocation( |
| 1595 | + | *rel_hdr, Relocation::PURPOSE::NONE, enc, arch)); |
| 1596 | + | |
1399 | 1597 | | reloc->section_ = applies_to; |
1400 | 1598 | | reloc->symbol_table_ = symbol_table; |
1401 | 1599 | | if (binary_->header().file_type() == Header::FILE_TYPE::REL && |
| skipped 295 lines |