| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "crazy_linker_elf_relocations.h" | 5 #include "crazy_linker_elf_relocations.h" |
| 6 | 6 |
| 7 #include <assert.h> |
| 7 #include <errno.h> | 8 #include <errno.h> |
| 8 | 9 |
| 9 #include "crazy_linker_debug.h" | 10 #include "crazy_linker_debug.h" |
| 10 #include "crazy_linker_elf_symbols.h" | 11 #include "crazy_linker_elf_symbols.h" |
| 11 #include "crazy_linker_elf_view.h" | 12 #include "crazy_linker_elf_view.h" |
| 12 #include "crazy_linker_error.h" | 13 #include "crazy_linker_error.h" |
| 13 #include "crazy_linker_leb128.h" | 14 #include "crazy_linker_leb128.h" |
| 14 #include "crazy_linker_system.h" | 15 #include "crazy_linker_system.h" |
| 15 #include "crazy_linker_util.h" | 16 #include "crazy_linker_util.h" |
| 16 #include "linker_phdr.h" | 17 #include "linker_phdr.h" |
| 17 | 18 |
| 18 #define DEBUG_RELOCATIONS 0 | 19 #define DEBUG_RELOCATIONS 0 |
| 19 | 20 |
| 20 #define RLOG(...) LOG_IF(DEBUG_RELOCATIONS, __VA_ARGS__) | 21 #define RLOG(...) LOG_IF(DEBUG_RELOCATIONS, __VA_ARGS__) |
| 21 #define RLOG_ERRNO(...) LOG_ERRNO_IF(DEBUG_RELOCATIONS, __VA_ARGS__) | 22 #define RLOG_ERRNO(...) LOG_ERRNO_IF(DEBUG_RELOCATIONS, __VA_ARGS__) |
| 22 | 23 |
| 23 #ifndef DF_SYMBOLIC | 24 #ifndef DF_SYMBOLIC |
| 24 #define DF_SYMBOLIC 2 | 25 #define DF_SYMBOLIC 2 |
| 25 #endif | 26 #endif |
| 26 | 27 |
| 27 #ifndef DF_TEXTREL | 28 #ifndef DF_TEXTREL |
| 28 #define DF_TEXTREL 4 | 29 #define DF_TEXTREL 4 |
| 29 #endif | 30 #endif |
| 30 | 31 |
| 31 #ifndef DT_FLAGS | 32 #ifndef DT_FLAGS |
| 32 #define DT_FLAGS 30 | 33 #define DT_FLAGS 30 |
| 33 #endif | 34 #endif |
| 34 | 35 |
| 36 // Extension dynamic tags for Android packed relocations. |
| 37 #ifndef DT_LOOS |
| 38 #define DT_LOOS 0x6000000d |
| 39 #endif |
| 40 #ifndef DT_ANDROID_REL |
| 41 #define DT_ANDROID_REL (DT_LOOS + 2) |
| 42 #endif |
| 43 #ifndef DT_ANDROID_RELSZ |
| 44 #define DT_ANDROID_RELSZ (DT_LOOS + 3) |
| 45 #endif |
| 46 #ifndef DT_ANDROID_RELA |
| 47 #define DT_ANDROID_RELA (DT_LOOS + 4) |
| 48 #endif |
| 49 #ifndef DT_ANDROID_RELASZ |
| 50 #define DT_ANDROID_RELASZ (DT_LOOS + 5) |
| 51 #endif |
| 52 |
| 35 // Processor-specific relocation types supported by the linker. | 53 // Processor-specific relocation types supported by the linker. |
| 36 #ifdef __arm__ | 54 #ifdef __arm__ |
| 37 | 55 |
| 38 /* arm32 relocations */ | 56 /* arm32 relocations */ |
| 39 #define R_ARM_ABS32 2 | 57 #define R_ARM_ABS32 2 |
| 40 #define R_ARM_REL32 3 | 58 #define R_ARM_REL32 3 |
| 41 #define R_ARM_GLOB_DAT 21 | 59 #define R_ARM_GLOB_DAT 21 |
| 42 #define R_ARM_JUMP_SLOT 22 | 60 #define R_ARM_JUMP_SLOT 22 |
| 43 #define R_ARM_COPY 20 | 61 #define R_ARM_COPY 20 |
| 44 #define R_ARM_RELATIVE 23 | 62 #define R_ARM_RELATIVE 23 |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 161 } | 179 } |
| 162 } | 180 } |
| 163 | 181 |
| 164 } // namespace | 182 } // namespace |
| 165 | 183 |
| 166 bool ElfRelocations::Init(const ElfView* view, Error* error) { | 184 bool ElfRelocations::Init(const ElfView* view, Error* error) { |
| 167 // Save these for later. | 185 // Save these for later. |
| 168 phdr_ = view->phdr(); | 186 phdr_ = view->phdr(); |
| 169 phdr_count_ = view->phdr_count(); | 187 phdr_count_ = view->phdr_count(); |
| 170 load_bias_ = view->load_bias(); | 188 load_bias_ = view->load_bias(); |
| 171 #if defined(__arm__) || defined(__aarch64__) | |
| 172 packed_relocations_ = view->packed_relocations(); | |
| 173 #endif | |
| 174 | 189 |
| 175 // We handle only Rel or Rela, but not both. If DT_RELA or DT_RELASZ | 190 // We handle only Rel or Rela, but not both. If DT_RELA or DT_RELASZ |
| 176 // then we require DT_PLTREL to agree. | 191 // then we require DT_PLTREL to agree. |
| 177 bool has_rela_relocations = false; | 192 bool has_rela_relocations = false; |
| 178 bool has_rel_relocations = false; | 193 bool has_rel_relocations = false; |
| 179 | 194 |
| 180 // Parse the dynamic table. | 195 // Parse the dynamic table. |
| 181 ElfView::DynamicIterator dyn(view); | 196 ElfView::DynamicIterator dyn(view); |
| 182 for (; dyn.HasNext(); dyn.GetNext()) { | 197 for (; dyn.HasNext(); dyn.GetNext()) { |
| 183 ELF::Addr dyn_value = dyn.GetValue(); | 198 ELF::Addr dyn_value = dyn.GetValue(); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 224 if (relocations_size_) { | 239 if (relocations_size_) { |
| 225 *error = "Unsupported DT_RELASZ/DT_RELSZ combination in dyn section"; | 240 *error = "Unsupported DT_RELASZ/DT_RELSZ combination in dyn section"; |
| 226 return false; | 241 return false; |
| 227 } | 242 } |
| 228 relocations_size_ = dyn_value; | 243 relocations_size_ = dyn_value; |
| 229 if (tag == DT_RELASZ) | 244 if (tag == DT_RELASZ) |
| 230 has_rela_relocations = true; | 245 has_rela_relocations = true; |
| 231 else | 246 else |
| 232 has_rel_relocations = true; | 247 has_rel_relocations = true; |
| 233 break; | 248 break; |
| 249 case DT_ANDROID_RELA: |
| 250 case DT_ANDROID_REL: |
| 251 RLOG(" %s addr=%p\n", |
| 252 (tag == DT_ANDROID_RELA) ? "DT_ANDROID_RELA" : "DT_ANDROID_REL", |
| 253 dyn_addr); |
| 254 if (android_relocations_) { |
| 255 *error = "Unsupported DT_ANDROID_RELA/DT_ANDROID_REL " |
| 256 "combination in dynamic section"; |
| 257 return false; |
| 258 } |
| 259 android_relocations_ = reinterpret_cast<uint8_t*>(dyn_addr); |
| 260 if (tag == DT_ANDROID_RELA) |
| 261 has_rela_relocations = true; |
| 262 else |
| 263 has_rel_relocations = true; |
| 264 break; |
| 265 case DT_ANDROID_RELASZ: |
| 266 case DT_ANDROID_RELSZ: |
| 267 RLOG(" %s size=%d\n", |
| 268 (tag == DT_ANDROID_RELASZ) |
| 269 ? "DT_ANDROID_RELASZ" : "DT_ANDROID_RELSZ", dyn_addr); |
| 270 if (android_relocations_size_) { |
| 271 *error = "Unsupported DT_ANDROID_RELASZ/DT_ANDROID_RELSZ " |
| 272 "combination in dyn section"; |
| 273 return false; |
| 274 } |
| 275 android_relocations_size_ = dyn_value; |
| 276 if (tag == DT_ANDROID_RELASZ) |
| 277 has_rela_relocations = true; |
| 278 else |
| 279 has_rel_relocations = true; |
| 280 break; |
| 234 case DT_PLTGOT: | 281 case DT_PLTGOT: |
| 235 // Only used on MIPS currently. Could also be used on other platforms | 282 // Only used on MIPS currently. Could also be used on other platforms |
| 236 // when lazy binding (i.e. RTLD_LAZY) is implemented. | 283 // when lazy binding (i.e. RTLD_LAZY) is implemented. |
| 237 RLOG(" DT_PLTGOT addr=%p\n", dyn_addr); | 284 RLOG(" DT_PLTGOT addr=%p\n", dyn_addr); |
| 238 plt_got_ = reinterpret_cast<ELF::Addr*>(dyn_addr); | 285 plt_got_ = reinterpret_cast<ELF::Addr*>(dyn_addr); |
| 239 break; | 286 break; |
| 240 case DT_TEXTREL: | 287 case DT_TEXTREL: |
| 241 RLOG(" DT_TEXTREL\n"); | 288 RLOG(" DT_TEXTREL\n"); |
| 242 has_text_relocations_ = true; | 289 has_text_relocations_ = true; |
| 243 break; | 290 break; |
| 244 case DT_SYMBOLIC: | 291 case DT_SYMBOLIC: |
| 245 RLOG(" DT_SYMBOLIC\n"); | 292 RLOG(" DT_SYMBOLIC\n"); |
| 246 has_symbolic_ = true; | 293 has_symbolic_ = true; |
| 247 break; | 294 break; |
| 248 case DT_FLAGS: | 295 case DT_FLAGS: |
| 249 if (dyn_value & DF_TEXTREL) | 296 if (dyn_value & DF_TEXTREL) |
| 250 has_text_relocations_ = true; | 297 has_text_relocations_ = true; |
| 251 if (dyn_value & DF_SYMBOLIC) | 298 if (dyn_value & DF_SYMBOLIC) |
| 252 has_symbolic_ = true; | 299 has_symbolic_ = true; |
| 253 RLOG(" DT_FLAGS has_text_relocations=%s has_symbolic=%s\n", | 300 RLOG(" DT_FLAGS has_text_relocations=%s has_symbolic=%s\n", |
| 254 has_text_relocations_ ? "true" : "false", | 301 has_text_relocations_ ? "true" : "false", |
| 255 has_symbolic_ ? "true" : "false"); | 302 has_symbolic_ ? "true" : "false"); |
| 256 break; | 303 break; |
| 257 #if defined(__mips__) | 304 #if defined(__mips__) |
| 258 case DT_MIPS_SYMTABNO: | 305 case DT_MIPS_SYMTABNO: |
| 259 RLOG(" DT_MIPS_SYMTABNO value=%d\n", dyn_value); | 306 RLOG(" DT_MIPS_SYMTABNO value=%d\n", dyn_value); |
| 260 mips_symtab_count_ = dyn_value; | 307 mips_symtab_count_ = dyn_value; |
| 261 break; | 308 break; |
| 262 | 309 |
| 263 case DT_MIPS_LOCAL_GOTNO: | 310 case DT_MIPS_LOCAL_GOTNO: |
| 264 RLOG(" DT_MIPS_LOCAL_GOTNO value=%d\n", dyn_value); | 311 RLOG(" DT_MIPS_LOCAL_GOTNO value=%d\n", dyn_value); |
| 265 mips_local_got_count_ = dyn_value; | 312 mips_local_got_count_ = dyn_value; |
| 266 break; | 313 break; |
| 267 | 314 |
| 268 case DT_MIPS_GOTSYM: | 315 case DT_MIPS_GOTSYM: |
| 269 RLOG(" DT_MIPS_GOTSYM value=%d\n", dyn_value); | 316 RLOG(" DT_MIPS_GOTSYM value=%d\n", dyn_value); |
| 270 mips_gotsym_ = dyn_value; | 317 mips_gotsym_ = dyn_value; |
| 271 break; | 318 break; |
| 272 #endif | 319 #endif |
| 273 default: | 320 default: |
| 274 ; | 321 ; |
| 275 } | 322 } |
| 276 } | 323 } |
| 277 | 324 |
| 278 if (has_rel_relocations && has_rela_relocations) { | 325 if (has_rel_relocations && has_rela_relocations) { |
| 279 *error = "Combining DT_REL and DT_RELA is not currently supported"; | 326 *error = "Combining relocations with and without addends is not " |
| 327 "currently supported"; |
| 280 return false; | 328 return false; |
| 281 } | 329 } |
| 282 | 330 |
| 283 // If DT_PLTREL did not explicitly assign relocations_type_, set it | 331 // If DT_PLTREL did not explicitly assign relocations_type_, set it |
| 284 // here based on the type of relocations found. | 332 // here based on the type of relocations found. |
| 285 if (relocations_type_ != DT_REL && relocations_type_ != DT_RELA) { | 333 if (relocations_type_ != DT_REL && relocations_type_ != DT_RELA) { |
| 286 if (has_rel_relocations) | 334 if (has_rel_relocations) |
| 287 relocations_type_ = DT_REL; | 335 relocations_type_ = DT_REL; |
| 288 else if (has_rela_relocations) | 336 else if (has_rela_relocations) |
| 289 relocations_type_ = DT_RELA; | 337 relocations_type_ = DT_RELA; |
| 290 } | 338 } |
| 291 | 339 |
| 292 if (relocations_type_ == DT_REL && has_rela_relocations) { | 340 if (relocations_type_ == DT_REL && has_rela_relocations) { |
| 293 *error = "Found DT_RELA in dyn section, but DT_PLTREL is DT_REL"; | 341 *error = "Found relocations with addends in dyn section, " |
| 342 "but DT_PLTREL is DT_REL"; |
| 294 return false; | 343 return false; |
| 295 } | 344 } |
| 296 if (relocations_type_ == DT_RELA && has_rel_relocations) { | 345 if (relocations_type_ == DT_RELA && has_rel_relocations) { |
| 297 *error = "Found DT_REL in dyn section, but DT_PLTREL is DT_RELA"; | 346 *error = "Found relocations without addends in dyn section, " |
| 347 "but DT_PLTREL is DT_RELA"; |
| 298 return false; | 348 return false; |
| 299 } | 349 } |
| 300 | 350 |
| 301 return true; | 351 return true; |
| 302 } | 352 } |
| 303 | 353 |
| 304 bool ElfRelocations::ApplyAll(const ElfSymbols* symbols, | 354 bool ElfRelocations::ApplyAll(const ElfSymbols* symbols, |
| 305 SymbolResolver* resolver, | 355 SymbolResolver* resolver, |
| 306 Error* error) { | 356 Error* error) { |
| 307 LOG("%s: Enter\n", __FUNCTION__); | 357 LOG("%s: Enter\n", __FUNCTION__); |
| 308 | 358 |
| 309 if (has_text_relocations_) { | 359 if (has_text_relocations_) { |
| 310 if (phdr_table_unprotect_segments(phdr_, phdr_count_, load_bias_) < 0) { | 360 if (phdr_table_unprotect_segments(phdr_, phdr_count_, load_bias_) < 0) { |
| 311 error->Format("Can't unprotect loadable segments: %s", strerror(errno)); | 361 error->Format("Can't unprotect loadable segments: %s", strerror(errno)); |
| 312 return false; | 362 return false; |
| 313 } | 363 } |
| 314 } | 364 } |
| 315 | 365 |
| 316 #if defined(__arm__) || defined(__aarch64__) | 366 if (!ApplyAndroidRelocations(symbols, resolver, error)) |
| 317 if (!ApplyPackedRelocations(error)) | |
| 318 return false; | 367 return false; |
| 319 #endif | |
| 320 | 368 |
| 321 if (relocations_type_ == DT_REL) { | 369 if (relocations_type_ == DT_REL) { |
| 322 if (!ApplyRelRelocs(reinterpret_cast<ELF::Rel*>(relocations_), | 370 if (!ApplyRelRelocs(reinterpret_cast<ELF::Rel*>(relocations_), |
| 323 relocations_size_ / sizeof(ELF::Rel), | 371 relocations_size_ / sizeof(ELF::Rel), |
| 324 symbols, | 372 symbols, |
| 325 resolver, | 373 resolver, |
| 326 error)) | 374 error)) |
| 327 return false; | 375 return false; |
| 328 if (!ApplyRelRelocs(reinterpret_cast<ELF::Rel*>(plt_relocations_), | 376 if (!ApplyRelRelocs(reinterpret_cast<ELF::Rel*>(plt_relocations_), |
| 329 plt_relocations_size_ / sizeof(ELF::Rel), | 377 plt_relocations_size_ / sizeof(ELF::Rel), |
| (...skipping 27 matching lines...) Expand all Loading... |
| 357 if (phdr_table_protect_segments(phdr_, phdr_count_, load_bias_) < 0) { | 405 if (phdr_table_protect_segments(phdr_, phdr_count_, load_bias_) < 0) { |
| 358 error->Format("Can't reprotect loadable segments: %s", strerror(errno)); | 406 error->Format("Can't reprotect loadable segments: %s", strerror(errno)); |
| 359 return false; | 407 return false; |
| 360 } | 408 } |
| 361 } | 409 } |
| 362 | 410 |
| 363 LOG("%s: Done\n", __FUNCTION__); | 411 LOG("%s: Done\n", __FUNCTION__); |
| 364 return true; | 412 return true; |
| 365 } | 413 } |
| 366 | 414 |
| 367 #if defined(__arm__) || defined(__aarch64__) | 415 // Helper class for Android packed relocations. Encapsulates the packing |
| 416 // flags used by Android for packed relocation groups. |
| 417 class AndroidPackedRelocationGroupFlags { |
| 418 public: |
| 419 explicit AndroidPackedRelocationGroupFlags(size_t flags) : flags_(flags) { } |
| 368 | 420 |
| 369 bool ElfRelocations::ForEachPackedRel(const uint8_t* packed_relocations, | 421 bool is_relocation_grouped_by_info() const { |
| 370 RelRelocationHandler handler, | 422 return hasFlag(RELOCATION_GROUPED_BY_INFO_FLAG); |
| 371 void* opaque) { | 423 } |
| 372 Leb128Decoder decoder(packed_relocations); | 424 bool is_relocation_grouped_by_offset_delta() const { |
| 373 | 425 return hasFlag(RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG); |
| 374 // Find the count of pairs and the start address. | 426 } |
| 375 size_t pairs = decoder.Dequeue(); | 427 bool is_relocation_grouped_by_addend() const { |
| 376 const ELF::Addr start_address = decoder.Dequeue(); | 428 return hasFlag(RELOCATION_GROUPED_BY_ADDEND_FLAG); |
| 377 | 429 } |
| 378 // Emit initial relative relocation. | 430 bool is_relocation_group_has_addend() const { |
| 379 ELF::Rel relocation; | 431 return hasFlag(RELOCATION_GROUP_HAS_ADDEND_FLAG); |
| 380 relocation.r_offset = start_address; | |
| 381 relocation.r_info = ELF_R_INFO(0, RELATIVE_RELOCATION_CODE); | |
| 382 const ELF::Addr sym_addr = 0; | |
| 383 const bool resolved = false; | |
| 384 if (!handler(this, &relocation, opaque)) | |
| 385 return false; | |
| 386 | |
| 387 size_t unpacked_count = 1; | |
| 388 | |
| 389 // Emit relocations for each count-delta pair. | |
| 390 while (pairs) { | |
| 391 size_t count = decoder.Dequeue(); | |
| 392 const size_t delta = decoder.Dequeue(); | |
| 393 | |
| 394 // Emit count relative relocations with delta offset. | |
| 395 while (count) { | |
| 396 relocation.r_offset += delta; | |
| 397 if (!handler(this, &relocation, opaque)) | |
| 398 return false; | |
| 399 unpacked_count++; | |
| 400 count--; | |
| 401 } | |
| 402 pairs--; | |
| 403 } | 432 } |
| 404 | 433 |
| 405 RLOG("%s: unpacked_count=%d\n", __FUNCTION__, unpacked_count); | 434 private: |
| 435 bool hasFlag(size_t flag) const { return (flags_ & flag) != 0; } |
| 436 |
| 437 static const size_t RELOCATION_GROUPED_BY_INFO_FLAG = 1 << 0; |
| 438 static const size_t RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG = 1 << 1; |
| 439 static const size_t RELOCATION_GROUPED_BY_ADDEND_FLAG = 1 << 2; |
| 440 static const size_t RELOCATION_GROUP_HAS_ADDEND_FLAG = 1 << 3; |
| 441 |
| 442 const size_t flags_; |
| 443 }; |
| 444 |
| 445 bool ElfRelocations::ForEachAndroidRelocation(RelocationHandler handler, |
| 446 void* opaque) { |
| 447 // Skip over the "APS2" signature. |
| 448 Sleb128Decoder decoder(android_relocations_ + 4, |
| 449 android_relocations_size_ - 4); |
| 450 |
| 451 // Unpacking into a relocation with addend, both for REL and RELA, is |
| 452 // convenient at this point. If REL, the handler needs to take care of |
| 453 // any conversion before use. |
| 454 ELF::Rela relocation; |
| 455 memset(&relocation, 0, sizeof(relocation)); |
| 456 |
| 457 // Read the relocation count and initial offset. |
| 458 const size_t relocation_count = decoder.pop_front(); |
| 459 relocation.r_offset = decoder.pop_front(); |
| 460 |
| 461 LOG("%s: relocation_count=%d, initial r_offset=%p\n", |
| 462 __FUNCTION__, |
| 463 relocation_count, |
| 464 relocation.r_offset); |
| 465 |
| 466 size_t relocations_handled = 0; |
| 467 while (relocations_handled < relocation_count) { |
| 468 // Read the start of the group header to obtain its size and flags. |
| 469 const size_t group_size = decoder.pop_front(); |
| 470 AndroidPackedRelocationGroupFlags group_flags(decoder.pop_front()); |
| 471 |
| 472 // Read other group header fields, depending on the flags read above. |
| 473 size_t group_r_offset_delta = 0; |
| 474 if (group_flags.is_relocation_grouped_by_offset_delta()) |
| 475 group_r_offset_delta = decoder.pop_front(); |
| 476 |
| 477 if (group_flags.is_relocation_grouped_by_info()) |
| 478 relocation.r_info = decoder.pop_front(); |
| 479 |
| 480 if (group_flags.is_relocation_group_has_addend() && |
| 481 group_flags.is_relocation_grouped_by_addend()) |
| 482 relocation.r_addend += decoder.pop_front(); |
| 483 else if (!group_flags.is_relocation_group_has_addend()) |
| 484 relocation.r_addend = 0; |
| 485 |
| 486 // Expand the group into individual relocations. |
| 487 for (size_t group_index = 0; group_index < group_size; group_index++) { |
| 488 if (group_flags.is_relocation_grouped_by_offset_delta()) |
| 489 relocation.r_offset += group_r_offset_delta; |
| 490 else |
| 491 relocation.r_offset += decoder.pop_front(); |
| 492 |
| 493 if (!group_flags.is_relocation_grouped_by_info()) |
| 494 relocation.r_info = decoder.pop_front(); |
| 495 |
| 496 if (group_flags.is_relocation_group_has_addend() && |
| 497 !group_flags.is_relocation_grouped_by_addend()) |
| 498 relocation.r_addend += decoder.pop_front(); |
| 499 |
| 500 // Pass the relocation to the supplied handler function. If the handler |
| 501 // returns false we view this as failure and return false to our caller. |
| 502 if (!handler(this, &relocation, opaque)) { |
| 503 LOG("%s: failed handling relocation %d\n", |
| 504 __FUNCTION__, |
| 505 relocations_handled); |
| 506 return false; |
| 507 } |
| 508 |
| 509 relocations_handled++; |
| 510 } |
| 511 } |
| 512 |
| 513 LOG("%s: relocations_handled=%d\n", __FUNCTION__, relocations_handled); |
| 406 return true; | 514 return true; |
| 407 } | 515 } |
| 408 | 516 |
| 409 bool ElfRelocations::ForEachPackedRela(const uint8_t* packed_relocations, | 517 namespace { |
| 410 RelaRelocationHandler handler, | |
| 411 void* opaque) { | |
| 412 Sleb128Decoder decoder(packed_relocations); | |
| 413 | 518 |
| 414 // Find the count of pairs. | 519 // Validate the Android packed relocations signature. |
| 415 size_t pairs = decoder.Dequeue(); | 520 bool IsValidAndroidPackedRelocations(const uint8_t* android_relocations, |
| 521 size_t android_relocations_size) { |
| 522 if (android_relocations_size < 4) |
| 523 return false; |
| 416 | 524 |
| 417 ELF::Addr offset = 0; | 525 // Check for an initial APS2 Android packed relocations header. |
| 418 ELF::Sxword addend = 0; | 526 return (android_relocations[0] == 'A' && |
| 527 android_relocations[1] == 'P' && |
| 528 android_relocations[2] == 'S' && |
| 529 android_relocations[3] == '2'); |
| 530 } |
| 419 | 531 |
| 420 const ELF::Addr sym_addr = 0; | 532 // Narrow a Rela to its equivalent Rel. The r_addend field in the input |
| 421 const bool resolved = false; | 533 // Rela must be zero. |
| 534 void ConvertRelaToRel(const ELF::Rela* rela, ELF::Rel* rel) { |
| 535 assert(rela->r_addend == 0); |
| 536 rel->r_offset = rela->r_offset; |
| 537 rel->r_info = rela->r_info; |
| 538 } |
| 422 | 539 |
| 423 size_t unpacked_count = 0; | 540 } // namespace |
| 424 | 541 |
| 425 // Emit relocations for each deltas pair. | 542 // Args for ApplyAndroidRelocation handler function. |
| 426 while (pairs) { | 543 struct ApplyAndroidRelocationArgs { |
| 427 offset += decoder.Dequeue(); | 544 ELF::Addr relocations_type; |
| 428 addend += decoder.Dequeue(); | 545 const ElfSymbols* symbols; |
| 546 ElfRelocations::SymbolResolver* resolver; |
| 547 Error* error; |
| 548 }; |
| 429 | 549 |
| 430 ELF::Rela relocation; | 550 // Static ForEachAndroidRelocation() handler. |
| 431 relocation.r_offset = offset; | 551 bool ElfRelocations::ApplyAndroidRelocation(ElfRelocations* relocations, |
| 432 relocation.r_info = ELF_R_INFO(0, RELATIVE_RELOCATION_CODE); | 552 const ELF::Rela* relocation, |
| 433 relocation.r_addend = addend; | 553 void* opaque) { |
| 434 if (!handler(this, &relocation, opaque)) | 554 // Unpack args from opaque. |
| 435 return false; | 555 ApplyAndroidRelocationArgs* args = |
| 436 unpacked_count++; | 556 reinterpret_cast<ApplyAndroidRelocationArgs*>(opaque); |
| 437 pairs--; | 557 const ELF::Addr relocations_type = args->relocations_type; |
| 558 const ElfSymbols* symbols = args->symbols; |
| 559 ElfRelocations::SymbolResolver* resolver = args->resolver; |
| 560 Error* error = args->error; |
| 561 |
| 562 // For REL relocations, convert from RELA to REL and apply the conversion. |
| 563 // For RELA relocations, apply RELA directly. |
| 564 if (relocations_type == DT_REL) { |
| 565 ELF::Rel converted; |
| 566 ConvertRelaToRel(relocation, &converted); |
| 567 return relocations->ApplyRelReloc(&converted, symbols, resolver, error); |
| 438 } | 568 } |
| 439 | 569 |
| 440 RLOG("%s: unpacked_count=%d\n", __FUNCTION__, unpacked_count); | 570 if (relocations_type == DT_RELA) |
| 571 return relocations->ApplyRelaReloc(relocation, symbols, resolver, error); |
| 572 |
| 441 return true; | 573 return true; |
| 442 } | 574 } |
| 443 | 575 |
| 444 bool ElfRelocations::ApplyPackedRel(ElfRelocations* relocations, | 576 bool ElfRelocations::ApplyAndroidRelocations(const ElfSymbols* symbols, |
| 445 const ELF::Rel* relocation, | 577 SymbolResolver* resolver, |
| 446 void* opaque) { | 578 Error* error) { |
| 447 Error* error = reinterpret_cast<Error*>(opaque); | 579 if (!android_relocations_) |
| 448 const ELF::Addr sym_addr = 0; | 580 return true; |
| 449 const bool resolved = false; | 581 |
| 450 return relocations->ApplyRelReloc(relocation, sym_addr, resolved, error); | 582 if (!IsValidAndroidPackedRelocations(android_relocations_, |
| 583 android_relocations_size_)) |
| 584 return false; |
| 585 |
| 586 ApplyAndroidRelocationArgs args; |
| 587 args.relocations_type = relocations_type_; |
| 588 args.symbols = symbols; |
| 589 args.resolver = resolver; |
| 590 args.error = error; |
| 591 return ForEachAndroidRelocation(&ApplyAndroidRelocation, &args); |
| 451 } | 592 } |
| 452 | 593 |
| 453 bool ElfRelocations::ApplyPackedRels(const uint8_t* packed_relocations, | 594 bool ElfRelocations::ApplyResolvedRelaReloc(const ELF::Rela* rela, |
| 454 Error* error) { | 595 ELF::Addr sym_addr, |
| 455 void* opaque = error; | 596 bool resolved CRAZY_UNUSED, |
| 456 return ForEachPackedRel(packed_relocations, &ApplyPackedRel, opaque); | 597 Error* error) { |
| 457 } | |
| 458 | |
| 459 bool ElfRelocations::ApplyPackedRela(ElfRelocations* relocations, | |
| 460 const ELF::Rela* relocation, | |
| 461 void* opaque) { | |
| 462 Error* error = reinterpret_cast<Error*>(opaque); | |
| 463 const ELF::Addr sym_addr = 0; | |
| 464 const bool resolved = false; | |
| 465 return relocations->ApplyRelaReloc(relocation, sym_addr, resolved, error); | |
| 466 } | |
| 467 | |
| 468 bool ElfRelocations::ApplyPackedRelas(const uint8_t* packed_relocations, | |
| 469 Error* error) { | |
| 470 void* opaque = error; | |
| 471 return ForEachPackedRela(packed_relocations, &ApplyPackedRela, opaque); | |
| 472 } | |
| 473 | |
| 474 bool ElfRelocations::ApplyPackedRelocations(Error* error) { | |
| 475 if (!packed_relocations_) | |
| 476 return true; | |
| 477 | |
| 478 // Check for an initial APR1 header, packed relocations. | |
| 479 if (packed_relocations_[0] == 'A' && | |
| 480 packed_relocations_[1] == 'P' && | |
| 481 packed_relocations_[2] == 'R' && | |
| 482 packed_relocations_[3] == '1') { | |
| 483 return ApplyPackedRels(packed_relocations_ + 4, error); | |
| 484 } | |
| 485 | |
| 486 // Check for an initial APA1 header, packed relocations with addend. | |
| 487 if (packed_relocations_[0] == 'A' && | |
| 488 packed_relocations_[1] == 'P' && | |
| 489 packed_relocations_[2] == 'A' && | |
| 490 packed_relocations_[3] == '1') { | |
| 491 return ApplyPackedRelas(packed_relocations_ + 4, error); | |
| 492 } | |
| 493 | |
| 494 error->Format("Bad packed relocations ident, expected APR1 or APA1"); | |
| 495 return false; | |
| 496 } | |
| 497 #endif // __arm__ || __aarch64__ | |
| 498 | |
| 499 bool ElfRelocations::ApplyRelaReloc(const ELF::Rela* rela, | |
| 500 ELF::Addr sym_addr, | |
| 501 bool resolved CRAZY_UNUSED, | |
| 502 Error* error) { | |
| 503 const ELF::Word rela_type = ELF_R_TYPE(rela->r_info); | 598 const ELF::Word rela_type = ELF_R_TYPE(rela->r_info); |
| 504 const ELF::Word CRAZY_UNUSED rela_symbol = ELF_R_SYM(rela->r_info); | 599 const ELF::Word CRAZY_UNUSED rela_symbol = ELF_R_SYM(rela->r_info); |
| 505 const ELF::Sword CRAZY_UNUSED addend = rela->r_addend; | 600 const ELF::Sword CRAZY_UNUSED addend = rela->r_addend; |
| 506 | 601 |
| 507 const ELF::Addr reloc = static_cast<ELF::Addr>(rela->r_offset + load_bias_); | 602 const ELF::Addr reloc = static_cast<ELF::Addr>(rela->r_offset + load_bias_); |
| 508 | 603 |
| 509 RLOG(" rela reloc=%p offset=%p type=%d addend=%p\n", | 604 RLOG(" rela reloc=%p offset=%p type=%d addend=%p\n", |
| 510 reloc, | 605 reloc, |
| 511 rela->r_offset, | 606 rela->r_offset, |
| 512 rela_type, | 607 rela_type, |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 584 #endif // __x86_64__ | 679 #endif // __x86_64__ |
| 585 | 680 |
| 586 default: | 681 default: |
| 587 error->Format("Invalid relocation type (%d)", rela_type); | 682 error->Format("Invalid relocation type (%d)", rela_type); |
| 588 return false; | 683 return false; |
| 589 } | 684 } |
| 590 | 685 |
| 591 return true; | 686 return true; |
| 592 } | 687 } |
| 593 | 688 |
| 594 bool ElfRelocations::ApplyRelReloc(const ELF::Rel* rel, | 689 bool ElfRelocations::ApplyResolvedRelReloc(const ELF::Rel* rel, |
| 595 ELF::Addr sym_addr, | 690 ELF::Addr sym_addr, |
| 596 bool resolved CRAZY_UNUSED, | 691 bool resolved CRAZY_UNUSED, |
| 597 Error* error) { | 692 Error* error) { |
| 598 const ELF::Word rel_type = ELF_R_TYPE(rel->r_info); | 693 const ELF::Word rel_type = ELF_R_TYPE(rel->r_info); |
| 599 const ELF::Word CRAZY_UNUSED rel_symbol = ELF_R_SYM(rel->r_info); | 694 const ELF::Word CRAZY_UNUSED rel_symbol = ELF_R_SYM(rel->r_info); |
| 600 | 695 |
| 601 const ELF::Addr reloc = static_cast<ELF::Addr>(rel->r_offset + load_bias_); | 696 const ELF::Addr reloc = static_cast<ELF::Addr>(rel->r_offset + load_bias_); |
| 602 | 697 |
| 603 RLOG(" rel reloc=%p offset=%p type=%d\n", reloc, rel->r_offset, rel_type); | 698 RLOG(" rel reloc=%p offset=%p type=%d\n", reloc, rel->r_offset, rel_type); |
| 604 | 699 |
| 605 // Apply the relocation. | 700 // Apply the relocation. |
| 606 ELF::Addr* CRAZY_UNUSED target = reinterpret_cast<ELF::Addr*>(reloc); | 701 ELF::Addr* CRAZY_UNUSED target = reinterpret_cast<ELF::Addr*>(reloc); |
| 607 switch (rel_type) { | 702 switch (rel_type) { |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 745 return true; | 840 return true; |
| 746 } | 841 } |
| 747 | 842 |
| 748 error->Format( | 843 error->Format( |
| 749 "Invalid weak relocation type (%d) for unknown symbol '%s'", | 844 "Invalid weak relocation type (%d) for unknown symbol '%s'", |
| 750 r, | 845 r, |
| 751 sym_name); | 846 sym_name); |
| 752 return false; | 847 return false; |
| 753 } | 848 } |
| 754 | 849 |
| 850 bool ElfRelocations::ApplyRelReloc(const ELF::Rel* rel, |
| 851 const ElfSymbols* symbols, |
| 852 SymbolResolver* resolver, |
| 853 Error* error) { |
| 854 const ELF::Word rel_type = ELF_R_TYPE(rel->r_info); |
| 855 const ELF::Word rel_symbol = ELF_R_SYM(rel->r_info); |
| 856 |
| 857 ELF::Addr sym_addr = 0; |
| 858 ELF::Addr reloc = static_cast<ELF::Addr>(rel->r_offset + load_bias_); |
| 859 RLOG(" reloc=%p offset=%p type=%d symbol=%d\n", |
| 860 reloc, |
| 861 rel->r_offset, |
| 862 rel_type, |
| 863 rel_symbol); |
| 864 |
| 865 if (rel_type == 0) |
| 866 return true; |
| 867 |
| 868 bool resolved = false; |
| 869 |
| 870 // If this is a symbolic relocation, compute the symbol's address. |
| 871 if (__builtin_expect(rel_symbol != 0, 0)) { |
| 872 if (!ResolveSymbol(rel_type, |
| 873 rel_symbol, |
| 874 symbols, |
| 875 resolver, |
| 876 reloc, |
| 877 &sym_addr, |
| 878 error)) { |
| 879 return false; |
| 880 } |
| 881 resolved = true; |
| 882 } |
| 883 |
| 884 return ApplyResolvedRelReloc(rel, sym_addr, resolved, error); |
| 885 } |
| 886 |
| 755 bool ElfRelocations::ApplyRelRelocs(const ELF::Rel* rel, | 887 bool ElfRelocations::ApplyRelRelocs(const ELF::Rel* rel, |
| 756 size_t rel_count, | 888 size_t rel_count, |
| 757 const ElfSymbols* symbols, | 889 const ElfSymbols* symbols, |
| 758 SymbolResolver* resolver, | 890 SymbolResolver* resolver, |
| 759 Error* error) { | 891 Error* error) { |
| 760 RLOG("%s: rel=%p rel_count=%d\n", __FUNCTION__, rel, rel_count); | 892 RLOG("%s: rel=%p rel_count=%d\n", __FUNCTION__, rel, rel_count); |
| 761 | 893 |
| 762 if (!rel) | 894 if (!rel) |
| 763 return true; | 895 return true; |
| 764 | 896 |
| 765 for (size_t rel_n = 0; rel_n < rel_count; rel++, rel_n++) { | 897 for (size_t rel_n = 0; rel_n < rel_count; rel++, rel_n++) { |
| 766 const ELF::Word rel_type = ELF_R_TYPE(rel->r_info); | 898 RLOG(" Relocation %d of %d:\n", rel_n + 1, rel_count); |
| 767 const ELF::Word rel_symbol = ELF_R_SYM(rel->r_info); | |
| 768 | 899 |
| 769 ELF::Addr sym_addr = 0; | 900 if (!ApplyRelReloc(rel, symbols, resolver, error)) |
| 770 ELF::Addr reloc = static_cast<ELF::Addr>(rel->r_offset + load_bias_); | |
| 771 RLOG(" %d/%d reloc=%p offset=%p type=%d symbol=%d\n", | |
| 772 rel_n + 1, | |
| 773 rel_count, | |
| 774 reloc, | |
| 775 rel->r_offset, | |
| 776 rel_type, | |
| 777 rel_symbol); | |
| 778 | |
| 779 if (rel_type == 0) | |
| 780 continue; | |
| 781 | |
| 782 bool resolved = false; | |
| 783 | |
| 784 // If this is a symbolic relocation, compute the symbol's address. | |
| 785 if (__builtin_expect(rel_symbol != 0, 0)) { | |
| 786 if (!ResolveSymbol(rel_type, | |
| 787 rel_symbol, | |
| 788 symbols, | |
| 789 resolver, | |
| 790 reloc, | |
| 791 &sym_addr, | |
| 792 error)) { | |
| 793 return false; | |
| 794 } | |
| 795 resolved = true; | |
| 796 } | |
| 797 | |
| 798 if (!ApplyRelReloc(rel, sym_addr, resolved, error)) | |
| 799 return false; | 901 return false; |
| 800 } | 902 } |
| 801 | 903 |
| 802 return true; | 904 return true; |
| 803 } | 905 } |
| 804 | 906 |
| 907 bool ElfRelocations::ApplyRelaReloc(const ELF::Rela* rela, |
| 908 const ElfSymbols* symbols, |
| 909 SymbolResolver* resolver, |
| 910 Error* error) { |
| 911 const ELF::Word rel_type = ELF_R_TYPE(rela->r_info); |
| 912 const ELF::Word rel_symbol = ELF_R_SYM(rela->r_info); |
| 913 |
| 914 ELF::Addr sym_addr = 0; |
| 915 ELF::Addr reloc = static_cast<ELF::Addr>(rela->r_offset + load_bias_); |
| 916 RLOG(" reloc=%p offset=%p type=%d symbol=%d\n", |
| 917 reloc, |
| 918 rela->r_offset, |
| 919 rel_type, |
| 920 rel_symbol); |
| 921 |
| 922 if (rel_type == 0) |
| 923 return true; |
| 924 |
| 925 bool resolved = false; |
| 926 |
| 927 // If this is a symbolic relocation, compute the symbol's address. |
| 928 if (__builtin_expect(rel_symbol != 0, 0)) { |
| 929 if (!ResolveSymbol(rel_type, |
| 930 rel_symbol, |
| 931 symbols, |
| 932 resolver, |
| 933 reloc, |
| 934 &sym_addr, |
| 935 error)) { |
| 936 return false; |
| 937 } |
| 938 resolved = true; |
| 939 } |
| 940 |
| 941 return ApplyResolvedRelaReloc(rela, sym_addr, resolved, error); |
| 942 } |
| 943 |
| 805 bool ElfRelocations::ApplyRelaRelocs(const ELF::Rela* rela, | 944 bool ElfRelocations::ApplyRelaRelocs(const ELF::Rela* rela, |
| 806 size_t rela_count, | 945 size_t rela_count, |
| 807 const ElfSymbols* symbols, | 946 const ElfSymbols* symbols, |
| 808 SymbolResolver* resolver, | 947 SymbolResolver* resolver, |
| 809 Error* error) { | 948 Error* error) { |
| 810 RLOG("%s: rela=%p rela_count=%d\n", __FUNCTION__, rela, rela_count); | 949 RLOG("%s: rela=%p rela_count=%d\n", __FUNCTION__, rela, rela_count); |
| 811 | 950 |
| 812 if (!rela) | 951 if (!rela) |
| 813 return true; | 952 return true; |
| 814 | 953 |
| 815 for (size_t rel_n = 0; rel_n < rela_count; rela++, rel_n++) { | 954 for (size_t rel_n = 0; rel_n < rela_count; rela++, rel_n++) { |
| 816 const ELF::Word rel_type = ELF_R_TYPE(rela->r_info); | 955 RLOG(" Relocation %d of %d:\n", rel_n + 1, rela_count); |
| 817 const ELF::Word rel_symbol = ELF_R_SYM(rela->r_info); | |
| 818 | 956 |
| 819 ELF::Addr sym_addr = 0; | 957 if (!ApplyRelaReloc(rela, symbols, resolver, error)) |
| 820 ELF::Addr reloc = static_cast<ELF::Addr>(rela->r_offset + load_bias_); | |
| 821 RLOG(" %d/%d reloc=%p offset=%p type=%d symbol=%d\n", | |
| 822 rel_n + 1, | |
| 823 rela_count, | |
| 824 reloc, | |
| 825 rela->r_offset, | |
| 826 rel_type, | |
| 827 rel_symbol); | |
| 828 | |
| 829 if (rel_type == 0) | |
| 830 continue; | |
| 831 | |
| 832 bool resolved = false; | |
| 833 | |
| 834 // If this is a symbolic relocation, compute the symbol's address. | |
| 835 if (__builtin_expect(rel_symbol != 0, 0)) { | |
| 836 if (!ResolveSymbol(rel_type, | |
| 837 rel_symbol, | |
| 838 symbols, | |
| 839 resolver, | |
| 840 reloc, | |
| 841 &sym_addr, | |
| 842 error)) { | |
| 843 return false; | |
| 844 } | |
| 845 resolved = true; | |
| 846 } | |
| 847 | |
| 848 if (!ApplyRelaReloc(rela, sym_addr, resolved, error)) | |
| 849 return false; | 958 return false; |
| 850 } | 959 } |
| 851 | 960 |
| 852 return true; | 961 return true; |
| 853 } | 962 } |
| 854 | 963 |
| 855 #ifdef __mips__ | 964 #ifdef __mips__ |
| 856 bool ElfRelocations::RelocateMipsGot(const ElfSymbols* symbols, | 965 bool ElfRelocations::RelocateMipsGot(const ElfSymbols* symbols, |
| 857 SymbolResolver* resolver, | 966 SymbolResolver* resolver, |
| 858 Error* error) { | 967 Error* error) { |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 934 #ifdef __mips__ | 1043 #ifdef __mips__ |
| 935 case R_MIPS_REL32: | 1044 case R_MIPS_REL32: |
| 936 *dst_ptr += map_delta; | 1045 *dst_ptr += map_delta; |
| 937 break; | 1046 break; |
| 938 #endif | 1047 #endif |
| 939 default: | 1048 default: |
| 940 ; | 1049 ; |
| 941 } | 1050 } |
| 942 } | 1051 } |
| 943 | 1052 |
| 944 #if defined(__arm__) || defined(__aarch64__) | 1053 void ElfRelocations::AdjustAndroidRelocation(const ELF::Rela* relocation, |
| 1054 size_t src_addr, |
| 1055 size_t dst_addr, |
| 1056 size_t map_addr, |
| 1057 size_t size) { |
| 1058 // Add this value to each source address to get the corresponding |
| 1059 // destination address. |
| 1060 const size_t dst_delta = dst_addr - src_addr; |
| 1061 const size_t map_delta = map_addr - src_addr; |
| 945 | 1062 |
| 946 struct AdjustRelocationArgs { | 1063 const ELF::Word rel_type = ELF_R_TYPE(relocation->r_info); |
| 1064 const ELF::Word rel_symbol = ELF_R_SYM(relocation->r_info); |
| 1065 ELF::Addr src_reloc = |
| 1066 static_cast<ELF::Addr>(relocation->r_offset + load_bias_); |
| 1067 |
| 1068 if (rel_type == 0 || rel_symbol != 0) { |
| 1069 // Ignore empty and symbolic relocations |
| 1070 return; |
| 1071 } |
| 1072 |
| 1073 if (src_reloc < src_addr || src_reloc >= src_addr + size) { |
| 1074 // Ignore entries that don't relocate addresses inside the source section. |
| 1075 return; |
| 1076 } |
| 1077 |
| 1078 AdjustRelocation(rel_type, src_reloc, dst_delta, map_delta); |
| 1079 } |
| 1080 |
| 1081 // Args for ApplyAndroidRelocation handler function. |
| 1082 struct RelocateAndroidRelocationArgs { |
| 947 size_t src_addr; | 1083 size_t src_addr; |
| 948 size_t dst_addr; | 1084 size_t dst_addr; |
| 949 size_t map_addr; | 1085 size_t map_addr; |
| 950 size_t size; | 1086 size_t size; |
| 951 }; | 1087 }; |
| 952 | 1088 |
| 953 template<typename Rel> | 1089 // Static ForEachAndroidRelocation() handler. |
| 954 bool ElfRelocations::RelocatePackedRelocation(ElfRelocations* relocations, | 1090 bool ElfRelocations::RelocateAndroidRelocation(ElfRelocations* relocations, |
| 955 const Rel* rel, | 1091 const ELF::Rela* relocation, |
| 956 void* opaque) { | 1092 void* opaque) { |
| 957 AdjustRelocationArgs* args = reinterpret_cast<AdjustRelocationArgs*>(opaque); | 1093 // Unpack args from opaque, to obtain addrs and size; |
| 1094 RelocateAndroidRelocationArgs* args = |
| 1095 reinterpret_cast<RelocateAndroidRelocationArgs*>(opaque); |
| 958 const size_t src_addr = args->src_addr; | 1096 const size_t src_addr = args->src_addr; |
| 959 const size_t dst_addr = args->dst_addr; | 1097 const size_t dst_addr = args->dst_addr; |
| 960 const size_t map_addr = args->map_addr; | 1098 const size_t map_addr = args->map_addr; |
| 961 const size_t size = args->size; | 1099 const size_t size = args->size; |
| 962 | 1100 |
| 963 const size_t load_bias = relocations->load_bias_; | 1101 // Relocate the given relocation. Because the r_addend field is ignored |
| 964 | 1102 // in relocating RELA relocations we do not need to convert from REL to |
| 965 const size_t dst_delta = dst_addr - src_addr; | 1103 // RELA and supply alternative relocator functions; instead we can work |
| 966 const size_t map_delta = map_addr - src_addr; | 1104 // here directly on the RELA supplied by ForEachAndroidRelocation(), even |
| 967 | 1105 // on REL architectures. |
| 968 const ELF::Word rel_type = ELF_R_TYPE(rel->r_info); | 1106 relocations->AdjustAndroidRelocation(relocation, |
| 969 const ELF::Word rel_symbol = ELF_R_SYM(rel->r_info); | 1107 src_addr, |
| 970 ELF::Addr src_reloc = static_cast<ELF::Addr>(rel->r_offset + load_bias); | 1108 dst_addr, |
| 971 | 1109 map_addr, |
| 972 if (rel_type == 0 || rel_symbol != 0) { | 1110 size); |
| 973 // Ignore empty and symbolic relocations | |
| 974 return true; | |
| 975 } | |
| 976 | |
| 977 if (src_reloc < src_addr || src_reloc >= src_addr + size) { | |
| 978 // Ignore entries that don't relocate addresses inside the source section. | |
| 979 return true; | |
| 980 } | |
| 981 | |
| 982 relocations->AdjustRelocation(rel_type, src_reloc, dst_delta, map_delta); | |
| 983 return true; | 1111 return true; |
| 984 } | 1112 } |
| 985 | 1113 |
| 986 template bool ElfRelocations::RelocatePackedRelocation<ELF::Rel>( | 1114 void ElfRelocations::RelocateAndroidRelocations(size_t src_addr, |
| 987 ElfRelocations* relocations, const ELF::Rel* rel, void* opaque); | 1115 size_t dst_addr, |
| 1116 size_t map_addr, |
| 1117 size_t size) { |
| 1118 if (!android_relocations_) |
| 1119 return; |
| 988 | 1120 |
| 989 template bool ElfRelocations::RelocatePackedRelocation<ELF::Rela>( | 1121 assert(IsValidAndroidPackedRelocations(android_relocations_, |
| 990 ElfRelocations* relocations, const ELF::Rela* rel, void* opaque); | 1122 android_relocations_size_)); |
| 991 | 1123 |
| 992 void ElfRelocations::RelocatePackedRels(const uint8_t* packed_relocations, | 1124 RelocateAndroidRelocationArgs args; |
| 993 size_t src_addr, | |
| 994 size_t dst_addr, | |
| 995 size_t map_addr, | |
| 996 size_t size) { | |
| 997 AdjustRelocationArgs args; | |
| 998 args.src_addr = src_addr; | 1125 args.src_addr = src_addr; |
| 999 args.dst_addr = dst_addr; | 1126 args.dst_addr = dst_addr; |
| 1000 args.map_addr = map_addr; | 1127 args.map_addr = map_addr; |
| 1001 args.size = size; | 1128 args.size = size; |
| 1002 ForEachPackedRel(packed_relocations, | 1129 ForEachAndroidRelocation(&RelocateAndroidRelocation, &args); |
| 1003 &RelocatePackedRelocation<ELF::Rel>, &args); | |
| 1004 } | 1130 } |
| 1005 | 1131 |
| 1006 void ElfRelocations::RelocatePackedRelas(const uint8_t* packed_relocations, | 1132 template<typename Rel> |
| 1007 size_t src_addr, | 1133 void ElfRelocations::RelocateRelocations(size_t src_addr, |
| 1008 size_t dst_addr, | 1134 size_t dst_addr, |
| 1009 size_t map_addr, | 1135 size_t map_addr, |
| 1010 size_t size) { | 1136 size_t size) { |
| 1011 AdjustRelocationArgs args; | |
| 1012 args.src_addr = src_addr; | |
| 1013 args.dst_addr = dst_addr; | |
| 1014 args.map_addr = map_addr; | |
| 1015 args.size = size; | |
| 1016 ForEachPackedRela(packed_relocations, | |
| 1017 &RelocatePackedRelocation<ELF::Rela>, &args); | |
| 1018 } | |
| 1019 | |
| 1020 void ElfRelocations::RelocatePackedRelocations(size_t src_addr, | |
| 1021 size_t dst_addr, | |
| 1022 size_t map_addr, | |
| 1023 size_t size) { | |
| 1024 if (!packed_relocations_) | |
| 1025 return; | |
| 1026 | |
| 1027 // Check for an initial APR1 header, packed relocations. | |
| 1028 if (packed_relocations_[0] == 'A' && | |
| 1029 packed_relocations_[1] == 'P' && | |
| 1030 packed_relocations_[2] == 'R' && | |
| 1031 packed_relocations_[3] == '1') { | |
| 1032 RelocatePackedRels(packed_relocations_ + 4, | |
| 1033 src_addr, dst_addr, map_addr, size); | |
| 1034 } | |
| 1035 | |
| 1036 // Check for an initial APA1 header, packed relocations with addend. | |
| 1037 if (packed_relocations_[0] == 'A' && | |
| 1038 packed_relocations_[1] == 'P' && | |
| 1039 packed_relocations_[2] == 'A' && | |
| 1040 packed_relocations_[3] == '1') { | |
| 1041 RelocatePackedRelas(packed_relocations_ + 4, | |
| 1042 src_addr, dst_addr, map_addr, size); | |
| 1043 } | |
| 1044 } | |
| 1045 | |
| 1046 #endif // __arm__ || __aarch64__ | |
| 1047 | |
| 1048 template<typename Rel> | |
| 1049 void ElfRelocations::RelocateRelocation(size_t src_addr, | |
| 1050 size_t dst_addr, | |
| 1051 size_t map_addr, | |
| 1052 size_t size) { | |
| 1053 // Add this value to each source address to get the corresponding | 1137 // Add this value to each source address to get the corresponding |
| 1054 // destination address. | 1138 // destination address. |
| 1055 const size_t dst_delta = dst_addr - src_addr; | 1139 const size_t dst_delta = dst_addr - src_addr; |
| 1056 const size_t map_delta = map_addr - src_addr; | 1140 const size_t map_delta = map_addr - src_addr; |
| 1057 | 1141 |
| 1058 // Ignore PLT relocations, which all target symbols (ignored here). | 1142 // Ignore PLT relocations, which all target symbols (ignored here). |
| 1059 const Rel* rel = reinterpret_cast<Rel*>(relocations_); | 1143 const Rel* rel = reinterpret_cast<Rel*>(relocations_); |
| 1060 const size_t relocations_count = relocations_size_ / sizeof(Rel); | 1144 const size_t relocations_count = relocations_size_ / sizeof(Rel); |
| 1061 const Rel* rel_limit = rel + relocations_count; | 1145 const Rel* rel_limit = rel + relocations_count; |
| 1062 | 1146 |
| 1063 for (; rel < rel_limit; ++rel) { | 1147 for (; rel < rel_limit; ++rel) { |
| 1064 const ELF::Word rel_type = ELF_R_TYPE(rel->r_info); | 1148 const ELF::Word rel_type = ELF_R_TYPE(rel->r_info); |
| 1065 const ELF::Word rel_symbol = ELF_R_SYM(rel->r_info); | 1149 const ELF::Word rel_symbol = ELF_R_SYM(rel->r_info); |
| 1066 ELF::Addr src_reloc = static_cast<ELF::Addr>(rel->r_offset + load_bias_); | 1150 ELF::Addr src_reloc = static_cast<ELF::Addr>(rel->r_offset + load_bias_); |
| 1067 | 1151 |
| 1068 if (rel_type == 0 || rel_symbol != 0) { | 1152 if (rel_type == 0 || rel_symbol != 0) { |
| 1069 // Ignore empty and symbolic relocations | 1153 // Ignore empty and symbolic relocations |
| 1070 continue; | 1154 continue; |
| 1071 } | 1155 } |
| 1072 | 1156 |
| 1073 if (src_reloc < src_addr || src_reloc >= src_addr + size) { | 1157 if (src_reloc < src_addr || src_reloc >= src_addr + size) { |
| 1074 // Ignore entries that don't relocate addresses inside the source section. | 1158 // Ignore entries that don't relocate addresses inside the source section. |
| 1075 continue; | 1159 continue; |
| 1076 } | 1160 } |
| 1077 | 1161 |
| 1078 AdjustRelocation(rel_type, src_reloc, dst_delta, map_delta); | 1162 AdjustRelocation(rel_type, src_reloc, dst_delta, map_delta); |
| 1079 } | 1163 } |
| 1080 } | 1164 } |
| 1081 | 1165 |
| 1082 template void ElfRelocations::RelocateRelocation<ELF::Rel>( | 1166 template void ElfRelocations::RelocateRelocations<ELF::Rel>( |
| 1083 size_t src_addr, size_t dst_addr, size_t map_addr, size_t size); | 1167 size_t src_addr, size_t dst_addr, size_t map_addr, size_t size); |
| 1084 | 1168 |
| 1085 template void ElfRelocations::RelocateRelocation<ELF::Rela>( | 1169 template void ElfRelocations::RelocateRelocations<ELF::Rela>( |
| 1086 size_t src_addr, size_t dst_addr, size_t map_addr, size_t size); | 1170 size_t src_addr, size_t dst_addr, size_t map_addr, size_t size); |
| 1087 | 1171 |
| 1088 void ElfRelocations::CopyAndRelocate(size_t src_addr, | 1172 void ElfRelocations::CopyAndRelocate(size_t src_addr, |
| 1089 size_t dst_addr, | 1173 size_t dst_addr, |
| 1090 size_t map_addr, | 1174 size_t map_addr, |
| 1091 size_t size) { | 1175 size_t size) { |
| 1092 // First, a straight copy. | 1176 // First, a straight copy. |
| 1093 ::memcpy(reinterpret_cast<void*>(dst_addr), | 1177 ::memcpy(reinterpret_cast<void*>(dst_addr), |
| 1094 reinterpret_cast<void*>(src_addr), | 1178 reinterpret_cast<void*>(src_addr), |
| 1095 size); | 1179 size); |
| 1096 | 1180 |
| 1097 #if defined(__arm__) || defined(__aarch64__) | 1181 // Relocate android relocations. |
| 1098 // Relocate packed relative relocations. | 1182 RelocateAndroidRelocations(src_addr, dst_addr, map_addr, size); |
| 1099 RelocatePackedRelocations(src_addr, dst_addr, map_addr, size); | |
| 1100 #endif | |
| 1101 | 1183 |
| 1102 // Relocate relocations. | 1184 // Relocate relocations. |
| 1103 if (relocations_type_ == DT_REL) | 1185 if (relocations_type_ == DT_REL) |
| 1104 RelocateRelocation<ELF::Rel>(src_addr, dst_addr, map_addr, size); | 1186 RelocateRelocations<ELF::Rel>(src_addr, dst_addr, map_addr, size); |
| 1105 | 1187 |
| 1106 if (relocations_type_ == DT_RELA) | 1188 if (relocations_type_ == DT_RELA) |
| 1107 RelocateRelocation<ELF::Rela>(src_addr, dst_addr, map_addr, size); | 1189 RelocateRelocations<ELF::Rela>(src_addr, dst_addr, map_addr, size); |
| 1108 | 1190 |
| 1109 #ifdef __mips__ | 1191 #ifdef __mips__ |
| 1110 // Add this value to each source address to get the corresponding | 1192 // Add this value to each source address to get the corresponding |
| 1111 // destination address. | 1193 // destination address. |
| 1112 const size_t dst_delta = dst_addr - src_addr; | 1194 const size_t dst_delta = dst_addr - src_addr; |
| 1113 const size_t map_delta = map_addr - src_addr; | 1195 const size_t map_delta = map_addr - src_addr; |
| 1114 | 1196 |
| 1115 // Only relocate local GOT entries. | 1197 // Only relocate local GOT entries. |
| 1116 ELF::Addr* got = plt_got_; | 1198 ELF::Addr* got = plt_got_; |
| 1117 if (got) { | 1199 if (got) { |
| 1118 for (ELF::Addr n = 2; n < mips_local_got_count_; ++n) { | 1200 for (ELF::Addr n = 2; n < mips_local_got_count_; ++n) { |
| 1119 size_t got_addr = reinterpret_cast<size_t>(&got[n]); | 1201 size_t got_addr = reinterpret_cast<size_t>(&got[n]); |
| 1120 if (got_addr < src_addr || got_addr >= src_addr + size) | 1202 if (got_addr < src_addr || got_addr >= src_addr + size) |
| 1121 continue; | 1203 continue; |
| 1122 ELF::Addr* dst_ptr = reinterpret_cast<ELF::Addr*>(got_addr + dst_delta); | 1204 ELF::Addr* dst_ptr = reinterpret_cast<ELF::Addr*>(got_addr + dst_delta); |
| 1123 *dst_ptr += map_delta; | 1205 *dst_ptr += map_delta; |
| 1124 } | 1206 } |
| 1125 } | 1207 } |
| 1126 #endif | 1208 #endif |
| 1127 } | 1209 } |
| 1128 | 1210 |
| 1129 } // namespace crazy | 1211 } // namespace crazy |
| OLD | NEW |