Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(70)

Side by Side Diff: third_party/android_crazy_linker/src/src/crazy_linker_elf_relocations.cpp

Issue 1072533002: crazy linker: convert relocation unpacking to Android style. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698