Chromium Code Reviews| 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 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 221 if (relocations_size_) { | 239 if (relocations_size_) { |
| 222 *error = "Unsupported DT_RELASZ/DT_RELSZ combination in dyn section"; | 240 *error = "Unsupported DT_RELASZ/DT_RELSZ combination in dyn section"; |
| 223 return false; | 241 return false; |
| 224 } | 242 } |
| 225 relocations_size_ = dyn_value; | 243 relocations_size_ = dyn_value; |
| 226 if (tag == DT_RELASZ) | 244 if (tag == DT_RELASZ) |
| 227 has_rela_relocations = true; | 245 has_rela_relocations = true; |
| 228 else | 246 else |
| 229 has_rel_relocations = true; | 247 has_rel_relocations = true; |
| 230 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; | |
| 231 case DT_PLTGOT: | 281 case DT_PLTGOT: |
| 232 // 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 |
| 233 // when lazy binding (i.e. RTLD_LAZY) is implemented. | 283 // when lazy binding (i.e. RTLD_LAZY) is implemented. |
| 234 RLOG(" DT_PLTGOT addr=%p\n", dyn_addr); | 284 RLOG(" DT_PLTGOT addr=%p\n", dyn_addr); |
| 235 plt_got_ = reinterpret_cast<ELF::Addr*>(dyn_addr); | 285 plt_got_ = reinterpret_cast<ELF::Addr*>(dyn_addr); |
| 236 break; | 286 break; |
| 237 case DT_TEXTREL: | 287 case DT_TEXTREL: |
| 238 RLOG(" DT_TEXTREL\n"); | 288 RLOG(" DT_TEXTREL\n"); |
| 239 has_text_relocations_ = true; | 289 has_text_relocations_ = true; |
| 240 break; | 290 break; |
| 241 case DT_SYMBOLIC: | 291 case DT_SYMBOLIC: |
| 242 RLOG(" DT_SYMBOLIC\n"); | 292 RLOG(" DT_SYMBOLIC\n"); |
| 243 has_symbolic_ = true; | 293 has_symbolic_ = true; |
| 244 break; | 294 break; |
| 245 case DT_FLAGS: | 295 case DT_FLAGS: |
| 246 if (dyn_value & DF_TEXTREL) | 296 if (dyn_value & DF_TEXTREL) |
| 247 has_text_relocations_ = true; | 297 has_text_relocations_ = true; |
| 248 if (dyn_value & DF_SYMBOLIC) | 298 if (dyn_value & DF_SYMBOLIC) |
| 249 has_symbolic_ = true; | 299 has_symbolic_ = true; |
| 250 RLOG(" DT_FLAGS has_text_relocations=%s has_symbolic=%s\n", | 300 RLOG(" DT_FLAGS has_text_relocations=%s has_symbolic=%s\n", |
| 251 has_text_relocations_ ? "true" : "false", | 301 has_text_relocations_ ? "true" : "false", |
| 252 has_symbolic_ ? "true" : "false"); | 302 has_symbolic_ ? "true" : "false"); |
| 253 break; | 303 break; |
| 254 #if defined(__mips__) | 304 #if defined(__mips__) |
| 255 case DT_MIPS_SYMTABNO: | 305 case DT_MIPS_SYMTABNO: |
| 256 RLOG(" DT_MIPS_SYMTABNO value=%d\n", dyn_value); | 306 RLOG(" DT_MIPS_SYMTABNO value=%d\n", dyn_value); |
| 257 mips_symtab_count_ = dyn_value; | 307 mips_symtab_count_ = dyn_value; |
| 258 break; | 308 break; |
| 259 | 309 |
| 260 case DT_MIPS_LOCAL_GOTNO: | 310 case DT_MIPS_LOCAL_GOTNO: |
| 261 RLOG(" DT_MIPS_LOCAL_GOTNO value=%d\n", dyn_value); | 311 RLOG(" DT_MIPS_LOCAL_GOTNO value=%d\n", dyn_value); |
| 262 mips_local_got_count_ = dyn_value; | 312 mips_local_got_count_ = dyn_value; |
| 263 break; | 313 break; |
| 264 | 314 |
| 265 case DT_MIPS_GOTSYM: | 315 case DT_MIPS_GOTSYM: |
| 266 RLOG(" DT_MIPS_GOTSYM value=%d\n", dyn_value); | 316 RLOG(" DT_MIPS_GOTSYM value=%d\n", dyn_value); |
| 267 mips_gotsym_ = dyn_value; | 317 mips_gotsym_ = dyn_value; |
| 268 break; | 318 break; |
| 269 #endif | 319 #endif |
| 270 default: | 320 default: |
| 271 ; | 321 ; |
| 272 } | 322 } |
| 273 } | 323 } |
| 274 | 324 |
| 275 if (has_rel_relocations && has_rela_relocations) { | 325 if (has_rel_relocations && has_rela_relocations) { |
| 276 *error = "Combining DT_REL and DT_RELA is not currently supported"; | 326 *error = "Combining relocations with and without addends is not " |
| 327 "currently supported"; | |
| 277 return false; | 328 return false; |
| 278 } | 329 } |
| 279 | 330 |
| 280 // If DT_PLTREL did not explicitly assign relocations_type_, set it | 331 // If DT_PLTREL did not explicitly assign relocations_type_, set it |
| 281 // here based on the type of relocations found. | 332 // here based on the type of relocations found. |
| 282 if (relocations_type_ != DT_REL && relocations_type_ != DT_RELA) { | 333 if (relocations_type_ != DT_REL && relocations_type_ != DT_RELA) { |
| 283 if (has_rel_relocations) | 334 if (has_rel_relocations) |
| 284 relocations_type_ = DT_REL; | 335 relocations_type_ = DT_REL; |
| 285 else if (has_rela_relocations) | 336 else if (has_rela_relocations) |
| 286 relocations_type_ = DT_RELA; | 337 relocations_type_ = DT_RELA; |
| 287 } | 338 } |
| 288 | 339 |
| 289 if (relocations_type_ == DT_REL && has_rela_relocations) { | 340 if (relocations_type_ == DT_REL && has_rela_relocations) { |
| 290 *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"; | |
| 291 return false; | 343 return false; |
| 292 } | 344 } |
| 293 if (relocations_type_ == DT_RELA && has_rel_relocations) { | 345 if (relocations_type_ == DT_RELA && has_rel_relocations) { |
| 294 *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"; | |
| 295 return false; | 348 return false; |
| 296 } | 349 } |
| 297 | 350 |
| 298 return true; | 351 return true; |
| 299 } | 352 } |
| 300 | 353 |
| 301 bool ElfRelocations::ApplyAll(const ElfSymbols* symbols, | 354 bool ElfRelocations::ApplyAll(const ElfSymbols* symbols, |
| 302 SymbolResolver* resolver, | 355 SymbolResolver* resolver, |
| 303 Error* error) { | 356 Error* error) { |
| 304 LOG("%s: Enter\n", __FUNCTION__); | 357 LOG("%s: Enter\n", __FUNCTION__); |
| 305 | 358 |
| 306 if (has_text_relocations_) { | 359 if (has_text_relocations_) { |
| 307 if (phdr_table_unprotect_segments(phdr_, phdr_count_, load_bias_) < 0) { | 360 if (phdr_table_unprotect_segments(phdr_, phdr_count_, load_bias_) < 0) { |
| 308 error->Format("Can't unprotect loadable segments: %s", strerror(errno)); | 361 error->Format("Can't unprotect loadable segments: %s", strerror(errno)); |
| 309 return false; | 362 return false; |
| 310 } | 363 } |
| 311 } | 364 } |
| 312 | 365 |
| 313 #if defined(__arm__) || defined(__aarch64__) | 366 if (!ApplyAndroidRelocations(symbols, resolver, error)) |
| 314 if (!ApplyPackedRelocations(error)) | |
| 315 return false; | 367 return false; |
| 316 #endif | |
| 317 | 368 |
| 318 if (relocations_type_ == DT_REL) { | 369 if (relocations_type_ == DT_REL) { |
| 319 if (!ApplyRelRelocs(reinterpret_cast<ELF::Rel*>(relocations_), | 370 if (!ApplyRelRelocs(reinterpret_cast<ELF::Rel*>(relocations_), |
| 320 relocations_size_ / sizeof(ELF::Rel), | 371 relocations_size_ / sizeof(ELF::Rel), |
| 321 symbols, | 372 symbols, |
| 322 resolver, | 373 resolver, |
| 323 error)) | 374 error)) |
| 324 return false; | 375 return false; |
| 325 if (!ApplyRelRelocs(reinterpret_cast<ELF::Rel*>(plt_relocations_), | 376 if (!ApplyRelRelocs(reinterpret_cast<ELF::Rel*>(plt_relocations_), |
| 326 plt_relocations_size_ / sizeof(ELF::Rel), | 377 plt_relocations_size_ / sizeof(ELF::Rel), |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 354 if (phdr_table_protect_segments(phdr_, phdr_count_, load_bias_) < 0) { | 405 if (phdr_table_protect_segments(phdr_, phdr_count_, load_bias_) < 0) { |
| 355 error->Format("Can't reprotect loadable segments: %s", strerror(errno)); | 406 error->Format("Can't reprotect loadable segments: %s", strerror(errno)); |
| 356 return false; | 407 return false; |
| 357 } | 408 } |
| 358 } | 409 } |
| 359 | 410 |
| 360 LOG("%s: Done\n", __FUNCTION__); | 411 LOG("%s: Done\n", __FUNCTION__); |
| 361 return true; | 412 return true; |
| 362 } | 413 } |
| 363 | 414 |
| 364 #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) { } | |
| 365 | 420 |
| 366 void ElfRelocations::RegisterPackedRelocations(uint8_t* packed_relocations) { | 421 bool is_relocation_grouped_by_info() const { |
| 367 packed_relocations_ = packed_relocations; | 422 return hasFlag(RELOCATION_GROUPED_BY_INFO_FLAG); |
| 368 } | 423 } |
| 369 | 424 bool is_relocation_grouped_by_offset_delta() const { |
| 370 bool ElfRelocations::ApplyPackedRel(const uint8_t* packed_relocations, | 425 return hasFlag(RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG); |
| 371 Error* error) { | 426 } |
| 372 Leb128Decoder decoder(packed_relocations); | 427 bool is_relocation_grouped_by_addend() const { |
| 373 | 428 return hasFlag(RELOCATION_GROUPED_BY_ADDEND_FLAG); |
| 374 // Find the count of pairs and the start address. | 429 } |
| 375 size_t pairs = decoder.Dequeue(); | 430 bool is_relocation_group_has_addend() const { |
| 376 const ELF::Addr start_address = decoder.Dequeue(); | 431 return hasFlag(RELOCATION_GROUP_HAS_ADDEND_FLAG); |
| 377 | |
| 378 // Emit initial relative relocation. | |
| 379 ELF::Rel relocation; | |
| 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 (!ApplyRelReloc(&relocation, sym_addr, resolved, error)) | |
| 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 (!ApplyRelReloc(&relocation, sym_addr, resolved, error)) | |
| 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 "APU2" or "APS2" signature. | |
| 448 const uint8_t* data_start = android_relocations_ + 4; | |
| 449 const size_t data_size = android_relocations_size_ - 4; | |
| 450 | |
| 451 // Create the appropriate type of LEB128 decoder, and wrap it inside a | |
| 452 // ScopedPtr for convenience. | |
| 453 Leb128Decoder* decoder; | |
| 454 if (android_relocations_[2] == 'U') | |
| 455 decoder = new Uleb128Decoder(data_start, data_size); | |
| 456 else | |
| 457 decoder = new Sleb128Decoder(data_start, data_size); | |
|
rmcilroy
2015/04/13 10:36:10
nit - add a DCHECK that android_relocations_[2] ==
simonb (inactive)
2015/04/28 14:39:41
Gone -- the android packer no longer generates uns
| |
| 458 ScopedPtr<Leb128Decoder> scoped_decoder(decoder); | |
| 459 | |
| 460 // Unpacking into a relocation with addend, both for REL and RELA, is | |
| 461 // convenient at this point. If REL, the handler needs to take care of | |
| 462 // any conversion before use. | |
| 463 ELF::Rela relocation; | |
| 464 memset(&relocation, 0, sizeof(relocation)); | |
| 465 | |
| 466 // Read the relocation count and initial offset. | |
| 467 const size_t relocation_count = decoder->pop_front(); | |
| 468 relocation.r_offset = decoder->pop_front(); | |
| 469 | |
| 470 LOG("%s: relocation_count=%d, initial r_offset=%p\n", | |
| 471 __FUNCTION__, | |
| 472 relocation_count, | |
| 473 relocation.r_offset); | |
| 474 | |
| 475 size_t relocations_handled = 0; | |
| 476 while (relocations_handled < relocation_count) { | |
| 477 // Read the start of the group header to obtain its size and flags. | |
| 478 const size_t group_size = decoder->pop_front(); | |
| 479 AndroidPackedRelocationGroupFlags group_flags(decoder->pop_front()); | |
|
rmcilroy
2015/04/13 10:36:10
Maybe we could just package up the different group
simonb (inactive)
2015/04/28 14:39:41
I'd like to keep this code close to that of the an
rmcilroy
2015/05/01 14:15:22
Ok, SGTM.
| |
| 480 | |
| 481 // Read other group header fields, depending on the flags read above. | |
| 482 size_t group_r_offset_delta = 0; | |
| 483 if (group_flags.is_relocation_grouped_by_offset_delta()) | |
| 484 group_r_offset_delta = decoder->pop_front(); | |
| 485 | |
| 486 if (group_flags.is_relocation_grouped_by_info()) | |
| 487 relocation.r_info = decoder->pop_front(); | |
| 488 | |
| 489 if (group_flags.is_relocation_group_has_addend() && | |
| 490 group_flags.is_relocation_grouped_by_addend()) | |
| 491 relocation.r_addend += decoder->pop_front(); | |
| 492 else if (!group_flags.is_relocation_group_has_addend()) | |
| 493 relocation.r_addend = 0; | |
| 494 | |
| 495 // Expand the group into individual relocations. | |
| 496 for (size_t group_index = 0; group_index < group_size; group_index++) { | |
| 497 if (group_flags.is_relocation_grouped_by_offset_delta()) | |
| 498 relocation.r_offset += group_r_offset_delta; | |
| 499 else | |
| 500 relocation.r_offset += decoder->pop_front(); | |
| 501 | |
| 502 if (!group_flags.is_relocation_grouped_by_info()) | |
| 503 relocation.r_info = decoder->pop_front(); | |
| 504 | |
| 505 if (group_flags.is_relocation_group_has_addend() && | |
| 506 !group_flags.is_relocation_grouped_by_addend()) | |
| 507 relocation.r_addend += decoder->pop_front(); | |
|
rmcilroy
2015/04/13 10:36:10
If you do the suggestion above then the AndroidRel
simonb (inactive)
2015/04/28 14:39:41
Acknowledged.
| |
| 508 | |
| 509 // Pass the relocation to the supplied handler function. If the handler | |
| 510 // returns false we view this as failure and return false to our caller. | |
| 511 if (!handler(this, &relocation, opaque)) { | |
| 512 LOG("%s: failed handling relocation %d\n", | |
| 513 __FUNCTION__, | |
| 514 relocations_handled); | |
| 515 return false; | |
| 516 } | |
| 517 | |
| 518 relocations_handled++; | |
| 519 } | |
| 520 } | |
| 521 | |
| 522 LOG("%s: relocations_handled=%d\n", __FUNCTION__, relocations_handled); | |
| 406 return true; | 523 return true; |
| 407 } | 524 } |
| 408 | 525 |
| 409 bool ElfRelocations::ApplyPackedRela(const uint8_t* packed_relocations, | 526 namespace { |
|
rmcilroy
2015/04/13 10:36:10
Could we just make these private static functions
simonb (inactive)
2015/04/28 14:39:41
We could. Not sure what it would buy us though.
rmcilroy
2015/05/01 14:15:21
It just seems strange to have a mix of private fun
| |
| 410 Error* error) { | |
| 411 Sleb128Decoder decoder(packed_relocations); | |
| 412 | 527 |
| 413 // Find the count of pairs. | 528 // Validate the Android packed relocations signature. |
| 414 size_t pairs = decoder.Dequeue(); | 529 bool IsValidAndroidPackedRelocations(const uint8_t* android_relocations, |
| 530 size_t android_relocations_size) { | |
| 531 if (android_relocations_size < 4) | |
| 532 return false; | |
| 415 | 533 |
| 416 ELF::Addr offset = 0; | 534 // Check for an initial APU2 or APS2 Android packed relocations header. |
| 417 ELF::Sxword addend = 0; | 535 return (android_relocations[0] == 'A' && |
| 536 android_relocations[1] == 'P' && | |
| 537 (android_relocations[2] == 'U' || android_relocations[2] == 'S') && | |
| 538 android_relocations[3] == '2'); | |
| 539 } | |
| 418 | 540 |
| 419 const ELF::Addr sym_addr = 0; | 541 // Narrow a Rela to its equivalent Rel. The r_addend field in the input |
| 420 const bool resolved = false; | 542 // Rela must be zero. |
| 543 void ConvertRelaToRel(const ELF::Rela* rela, ELF::Rel* rel) { | |
| 544 assert(rela->r_addend == 0); | |
| 545 rel->r_offset = rela->r_offset; | |
| 546 rel->r_info = rela->r_info; | |
| 547 } | |
| 421 | 548 |
| 422 size_t unpacked_count = 0; | 549 } // namespace |
| 423 | 550 |
| 424 // Emit relocations for each deltas pair. | 551 // Args for ApplyAndroidRelocation handler function. |
| 425 while (pairs) { | 552 struct ApplyAndroidRelocationArgs { |
| 426 offset += decoder.Dequeue(); | 553 ELF::Addr relocations_type; |
| 427 addend += decoder.Dequeue(); | 554 const ElfSymbols* symbols; |
| 555 ElfRelocations::SymbolResolver* resolver; | |
| 556 Error* error; | |
| 557 }; | |
| 428 | 558 |
| 429 ELF::Rela relocation; | 559 // Static ForEachAndroidRelocation() handler. |
| 430 relocation.r_offset = offset; | 560 bool ElfRelocations::ApplyAndroidRelocation(ElfRelocations* relocations, |
| 431 relocation.r_info = ELF_R_INFO(0, RELATIVE_RELOCATION_CODE); | 561 const ELF::Rela* relocation, |
| 432 relocation.r_addend = addend; | 562 void* opaque) { |
| 433 if (!ApplyRelaReloc(&relocation, sym_addr, resolved, error)) | 563 // Unpack args from opaque. |
| 434 return false; | 564 ApplyAndroidRelocationArgs* args = |
| 435 unpacked_count++; | 565 reinterpret_cast<ApplyAndroidRelocationArgs*>(opaque); |
| 436 pairs--; | 566 const ELF::Addr relocations_type = args->relocations_type; |
| 567 const ElfSymbols* symbols = args->symbols; | |
| 568 ElfRelocations::SymbolResolver* resolver = args->resolver; | |
| 569 Error* error = args->error; | |
| 570 | |
| 571 // For REL relocations, convert from RELA to REL and apply the conversion. | |
| 572 // For RELA relocations, apply RELA directly. | |
| 573 if (relocations_type == DT_REL) { | |
| 574 ELF::Rel converted; | |
| 575 ConvertRelaToRel(relocation, &converted); | |
| 576 return relocations->ApplyRelReloc(&converted, symbols, resolver, error); | |
| 437 } | 577 } |
| 438 | 578 |
| 439 RLOG("%s: unpacked_count=%d\n", __FUNCTION__, unpacked_count); | 579 if (relocations_type == DT_RELA) |
| 580 return relocations->ApplyRelaReloc(relocation, symbols, resolver, error); | |
| 581 | |
| 440 return true; | 582 return true; |
|
rmcilroy
2015/04/13 10:36:10
Are non DT_REL / DT_RELA relocations allowed to go
simonb (inactive)
2015/04/28 14:39:41
Relocations are either DT_REL or DT_RELA, but cann
rmcilroy
2015/05/01 14:15:22
I see, that's fine.
| |
| 441 } | 583 } |
| 442 | 584 |
| 443 bool ElfRelocations::ApplyPackedRelocations(Error* error) { | 585 bool ElfRelocations::ApplyAndroidRelocations(const ElfSymbols* symbols, |
| 444 if (!packed_relocations_) | 586 SymbolResolver* resolver, |
| 587 Error* error) { | |
| 588 if (!android_relocations_) | |
| 445 return true; | 589 return true; |
| 446 | 590 |
| 447 // Check for an initial APR1 header, packed relocations. | 591 if (!IsValidAndroidPackedRelocations(android_relocations_, |
| 448 if (packed_relocations_[0] == 'A' && | 592 android_relocations_size_)) |
| 449 packed_relocations_[1] == 'P' && | 593 return false; |
| 450 packed_relocations_[2] == 'R' && | |
| 451 packed_relocations_[3] == '1') { | |
| 452 return ApplyPackedRel(packed_relocations_ + 4, error); | |
| 453 } | |
| 454 | 594 |
| 455 // Check for an initial APA1 header, packed relocations with addend. | 595 ApplyAndroidRelocationArgs args; |
| 456 if (packed_relocations_[0] == 'A' && | 596 args.relocations_type = relocations_type_; |
| 457 packed_relocations_[1] == 'P' && | 597 args.symbols = symbols; |
| 458 packed_relocations_[2] == 'A' && | 598 args.resolver = resolver; |
| 459 packed_relocations_[3] == '1') { | 599 args.error = error; |
| 460 return ApplyPackedRela(packed_relocations_ + 4, error); | 600 return ForEachAndroidRelocation(&ApplyAndroidRelocation, &args); |
| 461 } | 601 } |
| 462 | 602 |
| 463 error->Format("Bad packed relocations ident, expected APR1 or APA1"); | 603 bool ElfRelocations::ApplyResolvedRelaReloc(const ELF::Rela* rela, |
| 464 return false; | 604 ELF::Addr sym_addr, |
| 465 } | 605 bool resolved CRAZY_UNUSED, |
| 466 #endif // __arm__ || __aarch64__ | 606 Error* error) { |
| 467 | |
| 468 bool ElfRelocations::ApplyRelaReloc(const ELF::Rela* rela, | |
| 469 ELF::Addr sym_addr, | |
| 470 bool resolved CRAZY_UNUSED, | |
| 471 Error* error) { | |
| 472 const ELF::Word rela_type = ELF_R_TYPE(rela->r_info); | 607 const ELF::Word rela_type = ELF_R_TYPE(rela->r_info); |
| 473 const ELF::Word CRAZY_UNUSED rela_symbol = ELF_R_SYM(rela->r_info); | 608 const ELF::Word CRAZY_UNUSED rela_symbol = ELF_R_SYM(rela->r_info); |
| 474 const ELF::Sword CRAZY_UNUSED addend = rela->r_addend; | 609 const ELF::Sword CRAZY_UNUSED addend = rela->r_addend; |
| 475 | 610 |
| 476 const ELF::Addr reloc = static_cast<ELF::Addr>(rela->r_offset + load_bias_); | 611 const ELF::Addr reloc = static_cast<ELF::Addr>(rela->r_offset + load_bias_); |
| 477 | 612 |
| 478 RLOG(" rela reloc=%p offset=%p type=%d addend=%p\n", | 613 RLOG(" rela reloc=%p offset=%p type=%d addend=%p\n", |
| 479 reloc, | 614 reloc, |
| 480 rela->r_offset, | 615 rela->r_offset, |
| 481 rela_type, | 616 rela_type, |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 553 #endif // __x86_64__ | 688 #endif // __x86_64__ |
| 554 | 689 |
| 555 default: | 690 default: |
| 556 error->Format("Invalid relocation type (%d)", rela_type); | 691 error->Format("Invalid relocation type (%d)", rela_type); |
| 557 return false; | 692 return false; |
| 558 } | 693 } |
| 559 | 694 |
| 560 return true; | 695 return true; |
| 561 } | 696 } |
| 562 | 697 |
| 563 bool ElfRelocations::ApplyRelReloc(const ELF::Rel* rel, | 698 bool ElfRelocations::ApplyResolvedRelReloc(const ELF::Rel* rel, |
| 564 ELF::Addr sym_addr, | 699 ELF::Addr sym_addr, |
| 565 bool resolved CRAZY_UNUSED, | 700 bool resolved CRAZY_UNUSED, |
| 566 Error* error) { | 701 Error* error) { |
| 567 const ELF::Word rel_type = ELF_R_TYPE(rel->r_info); | 702 const ELF::Word rel_type = ELF_R_TYPE(rel->r_info); |
| 568 const ELF::Word CRAZY_UNUSED rel_symbol = ELF_R_SYM(rel->r_info); | 703 const ELF::Word CRAZY_UNUSED rel_symbol = ELF_R_SYM(rel->r_info); |
| 569 | 704 |
| 570 const ELF::Addr reloc = static_cast<ELF::Addr>(rel->r_offset + load_bias_); | 705 const ELF::Addr reloc = static_cast<ELF::Addr>(rel->r_offset + load_bias_); |
| 571 | 706 |
| 572 RLOG(" rel reloc=%p offset=%p type=%d\n", reloc, rel->r_offset, rel_type); | 707 RLOG(" rel reloc=%p offset=%p type=%d\n", reloc, rel->r_offset, rel_type); |
| 573 | 708 |
| 574 // Apply the relocation. | 709 // Apply the relocation. |
| 575 ELF::Addr* CRAZY_UNUSED target = reinterpret_cast<ELF::Addr*>(reloc); | 710 ELF::Addr* CRAZY_UNUSED target = reinterpret_cast<ELF::Addr*>(reloc); |
| 576 switch (rel_type) { | 711 switch (rel_type) { |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 714 return true; | 849 return true; |
| 715 } | 850 } |
| 716 | 851 |
| 717 error->Format( | 852 error->Format( |
| 718 "Invalid weak relocation type (%d) for unknown symbol '%s'", | 853 "Invalid weak relocation type (%d) for unknown symbol '%s'", |
| 719 r, | 854 r, |
| 720 sym_name); | 855 sym_name); |
| 721 return false; | 856 return false; |
| 722 } | 857 } |
| 723 | 858 |
| 859 bool ElfRelocations::ApplyRelReloc(const ELF::Rel* rel, | |
| 860 const ElfSymbols* symbols, | |
| 861 SymbolResolver* resolver, | |
| 862 Error* error) { | |
| 863 const ELF::Word rel_type = ELF_R_TYPE(rel->r_info); | |
| 864 const ELF::Word rel_symbol = ELF_R_SYM(rel->r_info); | |
| 865 | |
| 866 ELF::Addr sym_addr = 0; | |
| 867 ELF::Addr reloc = static_cast<ELF::Addr>(rel->r_offset + load_bias_); | |
| 868 RLOG(" reloc=%p offset=%p type=%d symbol=%d\n", | |
| 869 reloc, | |
| 870 rel->r_offset, | |
| 871 rel_type, | |
| 872 rel_symbol); | |
| 873 | |
| 874 if (rel_type == 0) | |
| 875 return true; | |
| 876 | |
| 877 bool resolved = false; | |
| 878 | |
| 879 // If this is a symbolic relocation, compute the symbol's address. | |
| 880 if (__builtin_expect(rel_symbol != 0, 0)) { | |
| 881 if (!ResolveSymbol(rel_type, | |
| 882 rel_symbol, | |
| 883 symbols, | |
| 884 resolver, | |
| 885 reloc, | |
| 886 &sym_addr, | |
| 887 error)) { | |
| 888 return false; | |
| 889 } | |
| 890 resolved = true; | |
| 891 } | |
| 892 | |
| 893 return ApplyResolvedRelReloc(rel, sym_addr, resolved, error); | |
| 894 } | |
| 895 | |
| 724 bool ElfRelocations::ApplyRelRelocs(const ELF::Rel* rel, | 896 bool ElfRelocations::ApplyRelRelocs(const ELF::Rel* rel, |
| 725 size_t rel_count, | 897 size_t rel_count, |
| 726 const ElfSymbols* symbols, | 898 const ElfSymbols* symbols, |
| 727 SymbolResolver* resolver, | 899 SymbolResolver* resolver, |
| 728 Error* error) { | 900 Error* error) { |
| 729 RLOG("%s: rel=%p rel_count=%d\n", __FUNCTION__, rel, rel_count); | 901 RLOG("%s: rel=%p rel_count=%d\n", __FUNCTION__, rel, rel_count); |
| 730 | 902 |
| 731 if (!rel) | 903 if (!rel) |
| 732 return true; | 904 return true; |
| 733 | 905 |
| 734 for (size_t rel_n = 0; rel_n < rel_count; rel++, rel_n++) { | 906 for (size_t rel_n = 0; rel_n < rel_count; rel++, rel_n++) { |
| 735 const ELF::Word rel_type = ELF_R_TYPE(rel->r_info); | 907 RLOG(" Relocation %d of %d:\n", rel_n + 1, rel_count); |
| 736 const ELF::Word rel_symbol = ELF_R_SYM(rel->r_info); | |
| 737 | 908 |
| 738 ELF::Addr sym_addr = 0; | 909 if (!ApplyRelReloc(rel, symbols, resolver, error)) |
| 739 ELF::Addr reloc = static_cast<ELF::Addr>(rel->r_offset + load_bias_); | |
| 740 RLOG(" %d/%d reloc=%p offset=%p type=%d symbol=%d\n", | |
| 741 rel_n + 1, | |
| 742 rel_count, | |
| 743 reloc, | |
| 744 rel->r_offset, | |
| 745 rel_type, | |
| 746 rel_symbol); | |
| 747 | |
| 748 if (rel_type == 0) | |
| 749 continue; | |
| 750 | |
| 751 bool resolved = false; | |
| 752 | |
| 753 // If this is a symbolic relocation, compute the symbol's address. | |
| 754 if (__builtin_expect(rel_symbol != 0, 0)) { | |
| 755 if (!ResolveSymbol(rel_type, | |
| 756 rel_symbol, | |
| 757 symbols, | |
| 758 resolver, | |
| 759 reloc, | |
| 760 &sym_addr, | |
| 761 error)) { | |
| 762 return false; | |
| 763 } | |
| 764 resolved = true; | |
| 765 } | |
| 766 | |
| 767 if (!ApplyRelReloc(rel, sym_addr, resolved, error)) | |
| 768 return false; | 910 return false; |
| 769 } | 911 } |
| 770 | 912 |
| 771 return true; | 913 return true; |
| 772 } | 914 } |
| 773 | 915 |
| 916 bool ElfRelocations::ApplyRelaReloc(const ELF::Rela* rela, | |
|
rmcilroy
2015/04/13 10:36:10
Could you template this with ApplyRelReloc? Not su
simonb (inactive)
2015/04/28 14:39:41
Possible, but the result doesn't aid readability m
rmcilroy
2015/05/01 14:15:22
Acknowledged.
| |
| 917 const ElfSymbols* symbols, | |
| 918 SymbolResolver* resolver, | |
| 919 Error* error) { | |
| 920 const ELF::Word rel_type = ELF_R_TYPE(rela->r_info); | |
| 921 const ELF::Word rel_symbol = ELF_R_SYM(rela->r_info); | |
| 922 | |
| 923 ELF::Addr sym_addr = 0; | |
| 924 ELF::Addr reloc = static_cast<ELF::Addr>(rela->r_offset + load_bias_); | |
| 925 RLOG(" reloc=%p offset=%p type=%d symbol=%d\n", | |
| 926 reloc, | |
| 927 rela->r_offset, | |
| 928 rel_type, | |
| 929 rel_symbol); | |
| 930 | |
| 931 if (rel_type == 0) | |
| 932 return true; | |
| 933 | |
| 934 bool resolved = false; | |
| 935 | |
| 936 // If this is a symbolic relocation, compute the symbol's address. | |
| 937 if (__builtin_expect(rel_symbol != 0, 0)) { | |
| 938 if (!ResolveSymbol(rel_type, | |
| 939 rel_symbol, | |
| 940 symbols, | |
| 941 resolver, | |
| 942 reloc, | |
| 943 &sym_addr, | |
| 944 error)) { | |
| 945 return false; | |
| 946 } | |
| 947 resolved = true; | |
| 948 } | |
| 949 | |
| 950 return ApplyResolvedRelaReloc(rela, sym_addr, resolved, error); | |
| 951 } | |
| 952 | |
| 774 bool ElfRelocations::ApplyRelaRelocs(const ELF::Rela* rela, | 953 bool ElfRelocations::ApplyRelaRelocs(const ELF::Rela* rela, |
| 775 size_t rela_count, | 954 size_t rela_count, |
| 776 const ElfSymbols* symbols, | 955 const ElfSymbols* symbols, |
| 777 SymbolResolver* resolver, | 956 SymbolResolver* resolver, |
| 778 Error* error) { | 957 Error* error) { |
| 779 RLOG("%s: rela=%p rela_count=%d\n", __FUNCTION__, rela, rela_count); | 958 RLOG("%s: rela=%p rela_count=%d\n", __FUNCTION__, rela, rela_count); |
| 780 | 959 |
| 781 if (!rela) | 960 if (!rela) |
| 782 return true; | 961 return true; |
| 783 | 962 |
| 784 for (size_t rel_n = 0; rel_n < rela_count; rela++, rel_n++) { | 963 for (size_t rel_n = 0; rel_n < rela_count; rela++, rel_n++) { |
| 785 const ELF::Word rel_type = ELF_R_TYPE(rela->r_info); | 964 RLOG(" Relocation %d of %d:\n", rel_n + 1, rela_count); |
| 786 const ELF::Word rel_symbol = ELF_R_SYM(rela->r_info); | |
| 787 | 965 |
| 788 ELF::Addr sym_addr = 0; | 966 if (!ApplyRelaReloc(rela, symbols, resolver, error)) |
| 789 ELF::Addr reloc = static_cast<ELF::Addr>(rela->r_offset + load_bias_); | |
| 790 RLOG(" %d/%d reloc=%p offset=%p type=%d symbol=%d\n", | |
| 791 rel_n + 1, | |
| 792 rela_count, | |
| 793 reloc, | |
| 794 rela->r_offset, | |
| 795 rel_type, | |
| 796 rel_symbol); | |
| 797 | |
| 798 if (rel_type == 0) | |
| 799 continue; | |
| 800 | |
| 801 bool resolved = false; | |
| 802 | |
| 803 // If this is a symbolic relocation, compute the symbol's address. | |
| 804 if (__builtin_expect(rel_symbol != 0, 0)) { | |
| 805 if (!ResolveSymbol(rel_type, | |
| 806 rel_symbol, | |
| 807 symbols, | |
| 808 resolver, | |
| 809 reloc, | |
| 810 &sym_addr, | |
| 811 error)) { | |
| 812 return false; | |
| 813 } | |
| 814 resolved = true; | |
| 815 } | |
| 816 | |
| 817 if (!ApplyRelaReloc(rela, sym_addr, resolved, error)) | |
| 818 return false; | 967 return false; |
| 819 } | 968 } |
| 820 | 969 |
| 821 return true; | 970 return true; |
| 822 } | 971 } |
| 823 | 972 |
| 824 #ifdef __mips__ | 973 #ifdef __mips__ |
| 825 bool ElfRelocations::RelocateMipsGot(const ElfSymbols* symbols, | 974 bool ElfRelocations::RelocateMipsGot(const ElfSymbols* symbols, |
| 826 SymbolResolver* resolver, | 975 SymbolResolver* resolver, |
| 827 Error* error) { | 976 Error* error) { |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 903 #ifdef __mips__ | 1052 #ifdef __mips__ |
| 904 case R_MIPS_REL32: | 1053 case R_MIPS_REL32: |
| 905 *dst_ptr += map_delta; | 1054 *dst_ptr += map_delta; |
| 906 break; | 1055 break; |
| 907 #endif | 1056 #endif |
| 908 default: | 1057 default: |
| 909 ; | 1058 ; |
| 910 } | 1059 } |
| 911 } | 1060 } |
| 912 | 1061 |
| 1062 // Args for ApplyAndroidRelocation handler function. | |
| 1063 struct RelocateAndroidRelocationArgs { | |
|
rmcilroy
2015/04/13 10:36:10
nit - move down to just above RelocateAndroidReloc
simonb (inactive)
2015/04/28 14:39:41
Done.
| |
| 1064 size_t src_addr; | |
| 1065 size_t dst_addr; | |
| 1066 size_t map_addr; | |
| 1067 size_t size; | |
| 1068 }; | |
| 1069 | |
| 1070 void ElfRelocations::RelocateAndroidReloc(const ELF::Rela* relocation, | |
| 1071 size_t src_addr, | |
| 1072 size_t dst_addr, | |
| 1073 size_t map_addr, | |
| 1074 size_t size) { | |
| 1075 // Add this value to each source address to get the corresponding | |
| 1076 // destination address. | |
| 1077 const size_t dst_delta = dst_addr - src_addr; | |
| 1078 const size_t map_delta = map_addr - src_addr; | |
| 1079 | |
| 1080 const ELF::Word rel_type = ELF_R_TYPE(relocation->r_info); | |
| 1081 const ELF::Word rel_symbol = ELF_R_SYM(relocation->r_info); | |
| 1082 ELF::Addr src_reloc = | |
| 1083 static_cast<ELF::Addr>(relocation->r_offset + load_bias_); | |
| 1084 | |
| 1085 if (rel_type == 0 || rel_symbol != 0) { | |
| 1086 // Ignore empty and symbolic relocations | |
| 1087 return; | |
| 1088 } | |
| 1089 | |
| 1090 if (src_reloc < src_addr || src_reloc >= src_addr + size) { | |
| 1091 // Ignore entries that don't relocate addresses inside the source section. | |
| 1092 return; | |
| 1093 } | |
| 1094 | |
| 1095 AdjustRelocation(rel_type, src_reloc, dst_delta, map_delta); | |
| 1096 } | |
| 1097 | |
| 1098 // Static ForEachAndroidRelocation() handler. | |
| 1099 bool ElfRelocations::RelocateAndroidRelocation(ElfRelocations* relocations, | |
| 1100 const ELF::Rela* relocation, | |
| 1101 void* opaque) { | |
| 1102 // Unpack args from opaque, to obtain addrs and size; | |
| 1103 RelocateAndroidRelocationArgs* args = | |
| 1104 reinterpret_cast<RelocateAndroidRelocationArgs*>(opaque); | |
| 1105 const size_t src_addr = args->src_addr; | |
| 1106 const size_t dst_addr = args->dst_addr; | |
| 1107 const size_t map_addr = args->map_addr; | |
| 1108 const size_t size = args->size; | |
| 1109 | |
| 1110 // Relocate the given relocation. Because the r_addend field is ignored | |
| 1111 // in relocating RELA relocations we do not need to convert from REL to | |
| 1112 // RELA and supply alternative relocator functions; instead we can work | |
| 1113 // here directly on the RELA supplied by ForEachAndroidRelocation(), even | |
| 1114 // on REL architectures. | |
| 1115 relocations->RelocateAndroidReloc(relocation, | |
| 1116 src_addr, dst_addr, map_addr, size); | |
| 1117 return true; | |
| 1118 } | |
| 1119 | |
| 1120 void ElfRelocations::RelocateAndroidRelocations(size_t src_addr, | |
| 1121 size_t dst_addr, | |
| 1122 size_t map_addr, | |
| 1123 size_t size) { | |
| 1124 if (!android_relocations_) | |
| 1125 return; | |
| 1126 | |
| 1127 assert(IsValidAndroidPackedRelocations(android_relocations_, | |
| 1128 android_relocations_size_)); | |
| 1129 | |
| 1130 RelocateAndroidRelocationArgs args; | |
| 1131 args.src_addr = src_addr; | |
| 1132 args.dst_addr = dst_addr; | |
| 1133 args.map_addr = map_addr; | |
| 1134 args.size = size; | |
| 1135 ForEachAndroidRelocation(&RelocateAndroidRelocation, &args); | |
| 1136 } | |
| 1137 | |
| 913 void ElfRelocations::RelocateRela(size_t src_addr, | 1138 void ElfRelocations::RelocateRela(size_t src_addr, |
| 914 size_t dst_addr, | 1139 size_t dst_addr, |
| 915 size_t map_addr, | 1140 size_t map_addr, |
| 916 size_t size) { | 1141 size_t size) { |
| 917 // Add this value to each source address to get the corresponding | 1142 // Add this value to each source address to get the corresponding |
| 918 // destination address. | 1143 // destination address. |
| 919 const size_t dst_delta = dst_addr - src_addr; | 1144 const size_t dst_delta = dst_addr - src_addr; |
| 920 const size_t map_delta = map_addr - src_addr; | 1145 const size_t map_delta = map_addr - src_addr; |
| 921 | 1146 |
| 922 // Ignore PLT relocations, which all target symbols (ignored here). | 1147 // Ignore PLT relocations, which all target symbols (ignored here). |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 978 | 1203 |
| 979 void ElfRelocations::CopyAndRelocate(size_t src_addr, | 1204 void ElfRelocations::CopyAndRelocate(size_t src_addr, |
| 980 size_t dst_addr, | 1205 size_t dst_addr, |
| 981 size_t map_addr, | 1206 size_t map_addr, |
| 982 size_t size) { | 1207 size_t size) { |
| 983 // First, a straight copy. | 1208 // First, a straight copy. |
| 984 ::memcpy(reinterpret_cast<void*>(dst_addr), | 1209 ::memcpy(reinterpret_cast<void*>(dst_addr), |
| 985 reinterpret_cast<void*>(src_addr), | 1210 reinterpret_cast<void*>(src_addr), |
| 986 size); | 1211 size); |
| 987 | 1212 |
| 1213 // Relocate android relocations. | |
| 1214 RelocateAndroidRelocations(src_addr, dst_addr, map_addr, size); | |
| 1215 | |
| 988 // Relocate relocations. | 1216 // Relocate relocations. |
| 989 if (relocations_type_ == DT_REL) | 1217 if (relocations_type_ == DT_REL) |
| 990 RelocateRel(src_addr, dst_addr, map_addr, size); | 1218 RelocateRel(src_addr, dst_addr, map_addr, size); |
| 991 | 1219 |
| 992 if (relocations_type_ == DT_RELA) | 1220 if (relocations_type_ == DT_RELA) |
| 993 RelocateRela(src_addr, dst_addr, map_addr, size); | 1221 RelocateRela(src_addr, dst_addr, map_addr, size); |
| 994 | 1222 |
| 995 #ifdef __mips__ | 1223 #ifdef __mips__ |
| 996 // Add this value to each source address to get the corresponding | 1224 // Add this value to each source address to get the corresponding |
| 997 // destination address. | 1225 // destination address. |
| 998 const size_t dst_delta = dst_addr - src_addr; | 1226 const size_t dst_delta = dst_addr - src_addr; |
| 999 const size_t map_delta = map_addr - src_addr; | 1227 const size_t map_delta = map_addr - src_addr; |
| 1000 | 1228 |
| 1001 // Only relocate local GOT entries. | 1229 // Only relocate local GOT entries. |
| 1002 ELF::Addr* got = plt_got_; | 1230 ELF::Addr* got = plt_got_; |
| 1003 if (got) { | 1231 if (got) { |
| 1004 for (ELF::Addr n = 2; n < mips_local_got_count_; ++n) { | 1232 for (ELF::Addr n = 2; n < mips_local_got_count_; ++n) { |
| 1005 size_t got_addr = reinterpret_cast<size_t>(&got[n]); | 1233 size_t got_addr = reinterpret_cast<size_t>(&got[n]); |
| 1006 if (got_addr < src_addr || got_addr >= src_addr + size) | 1234 if (got_addr < src_addr || got_addr >= src_addr + size) |
| 1007 continue; | 1235 continue; |
| 1008 ELF::Addr* dst_ptr = reinterpret_cast<ELF::Addr*>(got_addr + dst_delta); | 1236 ELF::Addr* dst_ptr = reinterpret_cast<ELF::Addr*>(got_addr + dst_delta); |
| 1009 *dst_ptr += map_delta; | 1237 *dst_ptr += map_delta; |
| 1010 } | 1238 } |
| 1011 } | 1239 } |
| 1012 #endif | 1240 #endif |
| 1013 } | 1241 } |
| 1014 | 1242 |
| 1015 } // namespace crazy | 1243 } // namespace crazy |
| OLD | NEW |