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
3 // found in the LICENSE file.
5 #include "crazy_linker_elf_relocations.h"
9 #include "crazy_linker_debug.h"
10 #include "crazy_linker_elf_symbols.h"
11 #include "crazy_linker_elf_view.h"
12 #include "crazy_linker_error.h"
13 #include "crazy_linker_leb128.h"
14 #include "crazy_linker_system.h"
15 #include "crazy_linker_util.h"
16 #include "linker_phdr.h"
18 #define DEBUG_RELOCATIONS 0
20 #define RLOG(...) LOG_IF(DEBUG_RELOCATIONS, __VA_ARGS__)
21 #define RLOG_ERRNO(...) LOG_ERRNO_IF(DEBUG_RELOCATIONS, __VA_ARGS__)
35 // Processor-specific relocation types supported by the linker.
38 /* arm32 relocations */
41 #define R_ARM_GLOB_DAT 21
42 #define R_ARM_JUMP_SLOT 22
44 #define R_ARM_RELATIVE 23
46 #define RELATIVE_RELOCATION_CODE R_ARM_RELATIVE
52 /* arm64 relocations */
53 #define R_AARCH64_ABS64 257
54 #define R_AARCH64_COPY 1024
55 #define R_AARCH64_GLOB_DAT 1025
56 #define R_AARCH64_JUMP_SLOT 1026
57 #define R_AARCH64_RELATIVE 1027
59 #define RELATIVE_RELOCATION_CODE R_AARCH64_RELATIVE
65 /* i386 relocations */
68 #define R_386_GLOB_DAT 6
69 #define R_386_JMP_SLOT 7
70 #define R_386_RELATIVE 8
76 /* x86_64 relocations */
78 #define R_X86_64_PC32 2
79 #define R_X86_64_GLOB_DAT 6
80 #define R_X86_64_JMP_SLOT 7
81 #define R_X86_64_RELATIVE 8
89 // List of known relocation types the relocator knows about.
91 RELOCATION_TYPE_UNKNOWN = 0,
92 RELOCATION_TYPE_ABSOLUTE = 1,
93 RELOCATION_TYPE_RELATIVE = 2,
94 RELOCATION_TYPE_PC_RELATIVE = 3,
95 RELOCATION_TYPE_COPY = 4,
98 // Convert an ELF relocation type info a RelocationType value.
99 RelocationType GetRelocationType(ELF::Word r_type) {
102 case R_ARM_JUMP_SLOT:
105 return RELOCATION_TYPE_ABSOLUTE;
109 return RELOCATION_TYPE_RELATIVE;
112 return RELOCATION_TYPE_COPY;
116 case R_AARCH64_JUMP_SLOT:
117 case R_AARCH64_GLOB_DAT:
118 case R_AARCH64_ABS64:
119 return RELOCATION_TYPE_ABSOLUTE;
121 case R_AARCH64_RELATIVE:
122 return RELOCATION_TYPE_RELATIVE;
125 return RELOCATION_TYPE_COPY;
132 return RELOCATION_TYPE_ABSOLUTE;
135 return RELOCATION_TYPE_RELATIVE;
138 return RELOCATION_TYPE_PC_RELATIVE;
142 case R_X86_64_JMP_SLOT:
143 case R_X86_64_GLOB_DAT:
145 return RELOCATION_TYPE_ABSOLUTE;
147 case R_X86_64_RELATIVE:
148 return RELOCATION_TYPE_RELATIVE;
151 return RELOCATION_TYPE_PC_RELATIVE;
156 return RELOCATION_TYPE_RELATIVE;
160 return RELOCATION_TYPE_UNKNOWN;
166 bool ElfRelocations::Init(const ElfView* view, Error* error) {
167 // Save these for later.
168 phdr_ = view->phdr();
169 phdr_count_ = view->phdr_count();
170 load_bias_ = view->load_bias();
172 // We handle only Rel or Rela, but not both. If DT_RELA or DT_RELASZ
173 // then we require DT_PLTREL to agree.
174 bool has_rela_relocations = false;
175 bool has_rel_relocations = false;
177 // Parse the dynamic table.
178 ElfView::DynamicIterator dyn(view);
179 for (; dyn.HasNext(); dyn.GetNext()) {
180 ELF::Addr dyn_value = dyn.GetValue();
181 uintptr_t dyn_addr = dyn.GetAddress(view->load_bias());
183 const ELF::Addr tag = dyn.GetTag();
186 RLOG(" DT_PLTREL value=%d\n", dyn_value);
187 if (dyn_value != DT_REL && dyn_value != DT_RELA) {
188 *error = "Invalid DT_PLTREL value in dynamic section";
191 relocations_type_ = dyn_value;
194 RLOG(" DT_JMPREL addr=%p\n", dyn_addr);
195 plt_relocations_ = dyn_addr;
198 plt_relocations_size_ = dyn_value;
199 RLOG(" DT_PLTRELSZ size=%d\n", dyn_value);
203 RLOG(" %s addr=%p\n",
204 (tag == DT_RELA) ? "DT_RELA" : "DT_REL",
207 *error = "Unsupported DT_RELA/DT_REL combination in dynamic section";
210 relocations_ = dyn_addr;
212 has_rela_relocations = true;
214 has_rel_relocations = true;
218 RLOG(" %s size=%d\n",
219 (tag == DT_RELASZ) ? "DT_RELASZ" : "DT_RELSZ",
221 if (relocations_size_) {
222 *error = "Unsupported DT_RELASZ/DT_RELSZ combination in dyn section";
225 relocations_size_ = dyn_value;
226 if (tag == DT_RELASZ)
227 has_rela_relocations = true;
229 has_rel_relocations = true;
232 // Only used on MIPS currently. Could also be used on other platforms
233 // when lazy binding (i.e. RTLD_LAZY) is implemented.
234 RLOG(" DT_PLTGOT addr=%p\n", dyn_addr);
235 plt_got_ = reinterpret_cast<ELF::Addr*>(dyn_addr);
238 RLOG(" DT_TEXTREL\n");
239 has_text_relocations_ = true;
242 RLOG(" DT_SYMBOLIC\n");
243 has_symbolic_ = true;
246 if (dyn_value & DF_TEXTREL)
247 has_text_relocations_ = true;
248 if (dyn_value & DF_SYMBOLIC)
249 has_symbolic_ = true;
250 RLOG(" DT_FLAGS has_text_relocations=%s has_symbolic=%s\n",
251 has_text_relocations_ ? "true" : "false",
252 has_symbolic_ ? "true" : "false");
254 #if defined(__mips__)
255 case DT_MIPS_SYMTABNO:
256 RLOG(" DT_MIPS_SYMTABNO value=%d\n", dyn_value);
257 mips_symtab_count_ = dyn_value;
260 case DT_MIPS_LOCAL_GOTNO:
261 RLOG(" DT_MIPS_LOCAL_GOTNO value=%d\n", dyn_value);
262 mips_local_got_count_ = dyn_value;
266 RLOG(" DT_MIPS_GOTSYM value=%d\n", dyn_value);
267 mips_gotsym_ = dyn_value;
275 if (has_rel_relocations && has_rela_relocations) {
276 *error = "Combining DT_REL and DT_RELA is not currently supported";
280 // If DT_PLTREL did not explicitly assign relocations_type_, set it
281 // here based on the type of relocations found.
282 if (relocations_type_ != DT_REL && relocations_type_ != DT_RELA) {
283 if (has_rel_relocations)
284 relocations_type_ = DT_REL;
285 else if (has_rela_relocations)
286 relocations_type_ = DT_RELA;
289 if (relocations_type_ == DT_REL && has_rela_relocations) {
290 *error = "Found DT_RELA in dyn section, but DT_PLTREL is DT_REL";
293 if (relocations_type_ == DT_RELA && has_rel_relocations) {
294 *error = "Found DT_REL in dyn section, but DT_PLTREL is DT_RELA";
301 bool ElfRelocations::ApplyAll(const ElfSymbols* symbols,
302 SymbolResolver* resolver,
304 LOG("%s: Enter\n", __FUNCTION__);
306 if (has_text_relocations_) {
307 if (phdr_table_unprotect_segments(phdr_, phdr_count_, load_bias_) < 0) {
308 error->Format("Can't unprotect loadable segments: %s", strerror(errno));
313 #if defined(__arm__) || defined(__aarch64__)
314 if (!ApplyPackedRelocations(error))
318 if (relocations_type_ == DT_REL) {
319 if (!ApplyRelRelocs(reinterpret_cast<ELF::Rel*>(relocations_),
320 relocations_size_ / sizeof(ELF::Rel),
325 if (!ApplyRelRelocs(reinterpret_cast<ELF::Rel*>(plt_relocations_),
326 plt_relocations_size_ / sizeof(ELF::Rel),
333 if (relocations_type_ == DT_RELA) {
334 if (!ApplyRelaRelocs(reinterpret_cast<ELF::Rela*>(relocations_),
335 relocations_size_ / sizeof(ELF::Rela),
340 if (!ApplyRelaRelocs(reinterpret_cast<ELF::Rela*>(plt_relocations_),
341 plt_relocations_size_ / sizeof(ELF::Rela),
349 if (!RelocateMipsGot(symbols, resolver, error))
353 if (has_text_relocations_) {
354 if (phdr_table_protect_segments(phdr_, phdr_count_, load_bias_) < 0) {
355 error->Format("Can't reprotect loadable segments: %s", strerror(errno));
360 LOG("%s: Done\n", __FUNCTION__);
364 #if defined(__arm__) || defined(__aarch64__)
366 void ElfRelocations::RegisterPackedRelocations(uint8_t* packed_relocations) {
367 packed_relocations_ = packed_relocations;
370 bool ElfRelocations::ApplyPackedRel(const uint8_t* packed_relocations,
372 Leb128Decoder decoder(packed_relocations);
374 // Find the count of pairs and the start address.
375 size_t pairs = decoder.Dequeue();
376 const ELF::Addr start_address = decoder.Dequeue();
378 // Emit initial relative 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))
387 size_t unpacked_count = 1;
389 // Emit relocations for each count-delta pair.
391 size_t count = decoder.Dequeue();
392 const size_t delta = decoder.Dequeue();
394 // Emit count relative relocations with delta offset.
396 relocation.r_offset += delta;
397 if (!ApplyRelReloc(&relocation, sym_addr, resolved, error))
405 RLOG("%s: unpacked_count=%d\n", __FUNCTION__, unpacked_count);
409 bool ElfRelocations::ApplyPackedRela(const uint8_t* packed_relocations,
411 Sleb128Decoder decoder(packed_relocations);
413 // Find the count of pairs.
414 size_t pairs = decoder.Dequeue();
416 ELF::Addr offset = 0;
417 ELF::Sxword addend = 0;
419 const ELF::Addr sym_addr = 0;
420 const bool resolved = false;
422 size_t unpacked_count = 0;
424 // Emit relocations for each deltas pair.
426 offset += decoder.Dequeue();
427 addend += decoder.Dequeue();
429 ELF::Rela relocation;
430 relocation.r_offset = offset;
431 relocation.r_info = ELF_R_INFO(0, RELATIVE_RELOCATION_CODE);
432 relocation.r_addend = addend;
433 if (!ApplyRelaReloc(&relocation, sym_addr, resolved, error))
439 RLOG("%s: unpacked_count=%d\n", __FUNCTION__, unpacked_count);
443 bool ElfRelocations::ApplyPackedRelocations(Error* error) {
444 if (!packed_relocations_)
447 // Check for an initial APR1 header, packed relocations.
448 if (packed_relocations_[0] == 'A' &&
449 packed_relocations_[1] == 'P' &&
450 packed_relocations_[2] == 'R' &&
451 packed_relocations_[3] == '1') {
452 return ApplyPackedRel(packed_relocations_ + 4, error);
455 // Check for an initial APA1 header, packed relocations with addend.
456 if (packed_relocations_[0] == 'A' &&
457 packed_relocations_[1] == 'P' &&
458 packed_relocations_[2] == 'A' &&
459 packed_relocations_[3] == '1') {
460 return ApplyPackedRela(packed_relocations_ + 4, error);
463 error->Format("Bad packed relocations ident, expected APR1 or APA1");
466 #endif // __arm__ || __aarch64__
468 bool ElfRelocations::ApplyRelaReloc(const ELF::Rela* rela,
470 bool resolved CRAZY_UNUSED,
472 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);
474 const ELF::Sword CRAZY_UNUSED addend = rela->r_addend;
476 const ELF::Addr reloc = static_cast<ELF::Addr>(rela->r_offset + load_bias_);
478 RLOG(" rela reloc=%p offset=%p type=%d addend=%p\n",
484 // Apply the relocation.
485 ELF::Addr* CRAZY_UNUSED target = reinterpret_cast<ELF::Addr*>(reloc);
488 case R_AARCH64_JUMP_SLOT:
489 RLOG(" R_AARCH64_JUMP_SLOT target=%p addr=%p\n",
492 *target = sym_addr + addend;
495 case R_AARCH64_GLOB_DAT:
496 RLOG(" R_AARCH64_GLOB_DAT target=%p addr=%p\n",
499 *target = sym_addr + addend;
502 case R_AARCH64_ABS64:
503 RLOG(" R_AARCH64_ABS64 target=%p (%p) addr=%p\n",
507 *target += sym_addr + addend;
510 case R_AARCH64_RELATIVE:
511 RLOG(" R_AARCH64_RELATIVE target=%p (%p) bias=%p\n",
514 load_bias_ + addend);
515 if (__builtin_expect(rela_symbol, 0)) {
516 *error = "Invalid relative relocation with symbol";
519 *target = load_bias_ + addend;
523 // NOTE: These relocations are forbidden in shared libraries.
524 RLOG(" R_AARCH64_COPY\n");
525 *error = "Invalid R_AARCH64_COPY relocation in shared library";
527 #endif // __aarch64__
530 case R_X86_64_JMP_SLOT:
531 *target = sym_addr + addend;
534 case R_X86_64_GLOB_DAT:
535 *target = sym_addr + addend;
538 case R_X86_64_RELATIVE:
540 *error = "Invalid relative relocation with symbol";
543 *target = load_bias_ + addend;
547 *target = sym_addr + addend;
551 *target = sym_addr + (addend - reloc);
556 error->Format("Invalid relocation type (%d)", rela_type);
563 bool ElfRelocations::ApplyRelReloc(const ELF::Rel* rel,
565 bool resolved CRAZY_UNUSED,
567 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);
570 const ELF::Addr reloc = static_cast<ELF::Addr>(rel->r_offset + load_bias_);
572 RLOG(" rel reloc=%p offset=%p type=%d\n", reloc, rel->r_offset, rel_type);
574 // Apply the relocation.
575 ELF::Addr* CRAZY_UNUSED target = reinterpret_cast<ELF::Addr*>(reloc);
578 case R_ARM_JUMP_SLOT:
579 RLOG(" R_ARM_JUMP_SLOT target=%p addr=%p\n", target, sym_addr);
584 RLOG(" R_ARM_GLOB_DAT target=%p addr=%p\n", target, sym_addr);
589 RLOG(" R_ARM_ABS32 target=%p (%p) addr=%p\n",
597 RLOG(" R_ARM_REL32 target=%p (%p) addr=%p offset=%p\n",
602 *target += sym_addr - rel->r_offset;
606 RLOG(" R_ARM_RELATIVE target=%p (%p) bias=%p\n",
610 if (__builtin_expect(rel_symbol, 0)) {
611 *error = "Invalid relative relocation with symbol";
614 *target += load_bias_;
618 // NOTE: These relocations are forbidden in shared libraries.
619 // The Android linker has special code to deal with this, which
620 // is not needed here.
621 RLOG(" R_ARM_COPY\n");
622 *error = "Invalid R_ARM_COPY relocation in shared library";
637 *error = "Invalid relative relocation with symbol";
640 *target += load_bias_;
648 *target += (sym_addr - reloc);
657 *target += load_bias_;
662 error->Format("Invalid relocation type (%d)", rel_type);
669 bool ElfRelocations::ResolveSymbol(ELF::Word rel_type,
670 ELF::Word rel_symbol,
671 const ElfSymbols* symbols,
672 SymbolResolver* resolver,
676 const char* sym_name = symbols->LookupNameById(rel_symbol);
677 RLOG(" symbol name='%s'\n", sym_name);
678 void* address = resolver->Lookup(sym_name);
681 // The symbol was found, so compute its address.
682 RLOG("%s: symbol %s resolved to %p\n", __FUNCTION__, sym_name, address);
683 *sym_addr = reinterpret_cast<ELF::Addr>(address);
687 // The symbol was not found. Normally this is an error except
688 // if this is a weak reference.
689 if (!symbols->IsWeakById(rel_symbol)) {
690 error->Format("Could not find symbol '%s'", sym_name);
694 RLOG("%s: weak reference to unresolved symbol %s\n", __FUNCTION__, sym_name);
696 // IHI0044C AAELF 4.5.1.1:
697 // Libraries are not searched to resolve weak references.
698 // It is not an error for a weak reference to remain
701 // During linking, the value of an undefined weak reference is:
702 // - Zero if the relocation type is absolute
703 // - The address of the place if the relocation is pc-relative
704 // - The address of nominal base address if the relocation
705 // type is base-relative.
706 RelocationType r = GetRelocationType(rel_type);
707 if (r == RELOCATION_TYPE_ABSOLUTE || r == RELOCATION_TYPE_RELATIVE) {
712 if (r == RELOCATION_TYPE_PC_RELATIVE) {
718 "Invalid weak relocation type (%d) for unknown symbol '%s'",
724 bool ElfRelocations::ApplyRelRelocs(const ELF::Rel* rel,
726 const ElfSymbols* symbols,
727 SymbolResolver* resolver,
729 RLOG("%s: rel=%p rel_count=%d\n", __FUNCTION__, rel, rel_count);
734 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);
736 const ELF::Word rel_symbol = ELF_R_SYM(rel->r_info);
738 ELF::Addr sym_addr = 0;
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",
751 bool resolved = false;
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,
767 if (!ApplyRelReloc(rel, sym_addr, resolved, error))
774 bool ElfRelocations::ApplyRelaRelocs(const ELF::Rela* rela,
776 const ElfSymbols* symbols,
777 SymbolResolver* resolver,
779 RLOG("%s: rela=%p rela_count=%d\n", __FUNCTION__, rela, rela_count);
784 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);
786 const ELF::Word rel_symbol = ELF_R_SYM(rela->r_info);
788 ELF::Addr sym_addr = 0;
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",
801 bool resolved = false;
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,
817 if (!ApplyRelaReloc(rela, sym_addr, resolved, error))
825 bool ElfRelocations::RelocateMipsGot(const ElfSymbols* symbols,
826 SymbolResolver* resolver,
831 // Handle the local GOT entries.
832 // This mimics what the system linker does.
833 // Note from the system linker:
834 // got[0]: lazy resolver function address.
835 // got[1]: may be used for a GNU extension.
836 // Set it to a recognizable address in case someone calls it
837 // (should be _rtld_bind_start).
838 ELF::Addr* got = plt_got_;
840 if (got[1] & 0x80000000)
843 for (ELF::Addr n = 2; n < mips_local_got_count_; ++n)
844 got[n] += load_bias_;
846 // Handle the global GOT entries.
847 got += mips_local_got_count_;
848 for (size_t idx = mips_gotsym_; idx < mips_symtab_count_; idx++, got++) {
849 const char* sym_name = symbols->LookupNameById(idx);
850 void* sym_addr = resolver->Lookup(sym_name);
852 // Found symbol, update GOT entry.
853 *got = reinterpret_cast<ELF::Addr>(sym_addr);
857 if (symbols->IsWeakById(idx)) {
858 // Undefined symbols are only ok if this is a weak reference.
859 // Update GOT entry to 0 though.
864 error->Format("Cannot locate symbol %s", sym_name);
872 void ElfRelocations::AdjustRelocation(ELF::Word rel_type,
876 ELF::Addr* dst_ptr = reinterpret_cast<ELF::Addr*>(src_reloc + dst_delta);
881 *dst_ptr += map_delta;
886 case R_AARCH64_RELATIVE:
887 *dst_ptr += map_delta;
889 #endif // __aarch64__
893 *dst_ptr += map_delta;
898 case R_X86_64_RELATIVE:
899 *dst_ptr += map_delta;
905 *dst_ptr += map_delta;
913 void ElfRelocations::RelocateRela(size_t src_addr,
917 // Add this value to each source address to get the corresponding
918 // destination address.
919 const size_t dst_delta = dst_addr - src_addr;
920 const size_t map_delta = map_addr - src_addr;
922 // Ignore PLT relocations, which all target symbols (ignored here).
923 const ELF::Rela* rel = reinterpret_cast<ELF::Rela*>(relocations_);
924 const size_t relocations_count = relocations_size_ / sizeof(ELF::Rela);
925 const ELF::Rela* rel_limit = rel + relocations_count;
927 for (; rel < rel_limit; ++rel) {
928 const ELF::Word rel_type = ELF_R_TYPE(rel->r_info);
929 const ELF::Word rel_symbol = ELF_R_SYM(rel->r_info);
930 ELF::Addr src_reloc = static_cast<ELF::Addr>(rel->r_offset + load_bias_);
932 if (rel_type == 0 || rel_symbol != 0) {
933 // Ignore empty and symbolic relocations
937 if (src_reloc < src_addr || src_reloc >= src_addr + size) {
938 // Ignore entries that don't relocate addresses inside the source section.
942 AdjustRelocation(rel_type, src_reloc, dst_delta, map_delta);
946 void ElfRelocations::RelocateRel(size_t src_addr,
950 // Add this value to each source address to get the corresponding
951 // destination address.
952 const size_t dst_delta = dst_addr - src_addr;
953 const size_t map_delta = map_addr - src_addr;
955 // Ignore PLT relocations, which all target symbols (ignored here).
956 const ELF::Rel* rel = reinterpret_cast<ELF::Rel*>(relocations_);
957 const size_t relocations_count = relocations_size_ / sizeof(ELF::Rel);
958 const ELF::Rel* rel_limit = rel + relocations_count;
960 for (; rel < rel_limit; ++rel) {
961 const ELF::Word rel_type = ELF_R_TYPE(rel->r_info);
962 const ELF::Word rel_symbol = ELF_R_SYM(rel->r_info);
963 ELF::Addr src_reloc = static_cast<ELF::Addr>(rel->r_offset + load_bias_);
965 if (rel_type == 0 || rel_symbol != 0) {
966 // Ignore empty and symbolic relocations
970 if (src_reloc < src_addr || src_reloc >= src_addr + size) {
971 // Ignore entries that don't relocate addresses inside the source section.
975 AdjustRelocation(rel_type, src_reloc, dst_delta, map_delta);
979 void ElfRelocations::CopyAndRelocate(size_t src_addr,
983 // First, a straight copy.
984 ::memcpy(reinterpret_cast<void*>(dst_addr),
985 reinterpret_cast<void*>(src_addr),
988 // Relocate relocations.
989 if (relocations_type_ == DT_REL)
990 RelocateRel(src_addr, dst_addr, map_addr, size);
992 if (relocations_type_ == DT_RELA)
993 RelocateRela(src_addr, dst_addr, map_addr, size);
996 // Add this value to each source address to get the corresponding
997 // destination address.
998 const size_t dst_delta = dst_addr - src_addr;
999 const size_t map_delta = map_addr - src_addr;
1001 // Only relocate local GOT entries.
1002 ELF::Addr* got = plt_got_;
1004 for (ELF::Addr n = 2; n < mips_local_got_count_; ++n) {
1005 size_t got_addr = reinterpret_cast<size_t>(&got[n]);
1006 if (got_addr < src_addr || got_addr >= src_addr + size)
1008 ELF::Addr* dst_ptr = reinterpret_cast<ELF::Addr*>(got_addr + dst_delta);
1009 *dst_ptr += map_delta;
1015 } // namespace crazy