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

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

Issue 340523003: Support for unpacked ARM packed relocations. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@fork_switch
Patch Set: Tidy README.chromium Created 6 years, 6 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 <errno.h> 7 #include <errno.h>
8 8
9 #include "crazy_linker_debug.h" 9 #include "crazy_linker_debug.h"
10 #include "crazy_linker_elf_symbols.h" 10 #include "crazy_linker_elf_symbols.h"
11 #include "crazy_linker_elf_view.h" 11 #include "crazy_linker_elf_view.h"
12 #include "crazy_linker_error.h" 12 #include "crazy_linker_error.h"
13 #include "crazy_linker_system.h"
13 #include "crazy_linker_util.h" 14 #include "crazy_linker_util.h"
14 #include "linker_phdr.h" 15 #include "linker_phdr.h"
15 16
16 #define DEBUG_RELOCATIONS 0 17 #define DEBUG_RELOCATIONS 0
17 18
18 #define RLOG(...) LOG_IF(DEBUG_RELOCATIONS, __VA_ARGS__) 19 #define RLOG(...) LOG_IF(DEBUG_RELOCATIONS, __VA_ARGS__)
19 #define RLOG_ERRNO(...) LOG_ERRNO_IF(DEBUG_RELOCATIONS, __VA_ARGS__) 20 #define RLOG_ERRNO(...) LOG_ERRNO_IF(DEBUG_RELOCATIONS, __VA_ARGS__)
20 21
21 #ifndef DF_SYMBOLIC 22 #ifndef DF_SYMBOLIC
22 #define DF_SYMBOLIC 2 23 #define DF_SYMBOLIC 2
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
58 59
59 /* i386 relocations */ 60 /* i386 relocations */
60 #define R_386_32 1 61 #define R_386_32 1
61 #define R_386_PC32 2 62 #define R_386_PC32 2
62 #define R_386_GLOB_DAT 6 63 #define R_386_GLOB_DAT 6
63 #define R_386_JMP_SLOT 7 64 #define R_386_JMP_SLOT 7
64 #define R_386_RELATIVE 8 65 #define R_386_RELATIVE 8
65 66
66 #endif // __i386__ 67 #endif // __i386__
67 68
69 // Processor-specific extension dynamic tags for packed relocations.
70 #ifdef __arm__
71
72 #define DT_ANDROID_ARM_REL_OFFSET (DT_LOPROC)
73 #define DT_ANDROID_ARM_REL_SIZE (DT_LOPROC + 1)
rmcilroy 2014/06/18 10:56:05 nit - just move this up to the preceding ifdef __a
simonb1 2014/06/18 15:41:28 Moved to crazy_linker_shared_library.cpp in patch
74
75 #endif // __arm__
76
68 namespace crazy { 77 namespace crazy {
69 78
70 namespace { 79 namespace {
71 80
72 // List of known relocation types the relocator knows about. 81 // List of known relocation types the relocator knows about.
73 enum RelocationType { 82 enum RelocationType {
74 RELOCATION_TYPE_UNKNOWN = 0, 83 RELOCATION_TYPE_UNKNOWN = 0,
75 RELOCATION_TYPE_ABSOLUTE = 1, 84 RELOCATION_TYPE_ABSOLUTE = 1,
76 RELOCATION_TYPE_RELATIVE = 2, 85 RELOCATION_TYPE_RELATIVE = 2,
77 RELOCATION_TYPE_PC_RELATIVE = 3, 86 RELOCATION_TYPE_PC_RELATIVE = 3,
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
214 break; 223 break;
215 case DT_FLAGS: 224 case DT_FLAGS:
216 if (dyn_value & DF_TEXTREL) 225 if (dyn_value & DF_TEXTREL)
217 has_text_relocations_ = true; 226 has_text_relocations_ = true;
218 if (dyn_value & DF_SYMBOLIC) 227 if (dyn_value & DF_SYMBOLIC)
219 has_symbolic_ = true; 228 has_symbolic_ = true;
220 RLOG(" DT_FLAGS has_text_relocations=%s has_symbolic=%s\n", 229 RLOG(" DT_FLAGS has_text_relocations=%s has_symbolic=%s\n",
221 has_text_relocations_ ? "true" : "false", 230 has_text_relocations_ ? "true" : "false",
222 has_symbolic_ ? "true" : "false"); 231 has_symbolic_ ? "true" : "false");
223 break; 232 break;
233 #if defined(__arm__)
234 case DT_ANDROID_ARM_REL_OFFSET:
235 arm_packed_relocations_ = dyn.GetOffset();
236 RLOG(" DT_ANDROID_ARM_REL_OFFSET addr=%p\n", arm_packed_relocations_);
237 break;
238 case DT_ANDROID_ARM_REL_SIZE:
239 arm_packed_relocations_size_ = dyn.GetValue();
240 RLOG(" DT_ANDROID_ARM_REL_SIZE=%d\n", arm_packed_relocations_size_);
241 break;
242 #endif
224 #if defined(__mips__) 243 #if defined(__mips__)
225 case DT_MIPS_SYMTABNO: 244 case DT_MIPS_SYMTABNO:
226 RLOG(" DT_MIPS_SYMTABNO value=%d\n", dyn_value); 245 RLOG(" DT_MIPS_SYMTABNO value=%d\n", dyn_value);
227 mips_symtab_count_ = dyn_value; 246 mips_symtab_count_ = dyn_value;
228 break; 247 break;
229 248
230 case DT_MIPS_LOCAL_GOTNO: 249 case DT_MIPS_LOCAL_GOTNO:
231 RLOG(" DT_MIPS_LOCAL_GOTNO value=%d\n", dyn_value); 250 RLOG(" DT_MIPS_LOCAL_GOTNO value=%d\n", dyn_value);
232 mips_local_got_count_ = dyn_value; 251 mips_local_got_count_ = dyn_value;
233 break; 252 break;
(...skipping 20 matching lines...) Expand all
254 if (relocations_type_ == DT_RELA && has_rel_relocations) { 273 if (relocations_type_ == DT_RELA && has_rel_relocations) {
255 *error = "Found DT_REL in dyn section, but DT_PLTREL is DT_RELA"; 274 *error = "Found DT_REL in dyn section, but DT_PLTREL is DT_RELA";
256 return false; 275 return false;
257 } 276 }
258 277
259 return true; 278 return true;
260 } 279 }
261 280
262 bool ElfRelocations::ApplyAll(const ElfSymbols* symbols, 281 bool ElfRelocations::ApplyAll(const ElfSymbols* symbols,
263 SymbolResolver* resolver, 282 SymbolResolver* resolver,
283 const char* full_path CRAZY_UNUSED,
rmcilroy 2014/06/18 10:56:05 Rather than passing the full path here, and having
simonb1 2014/06/18 15:41:28 Done. It's a bit more diffuse, so greater occurre
264 Error* error) { 284 Error* error) {
265 LOG("%s: Enter\n", __FUNCTION__); 285 LOG("%s: Enter\n", __FUNCTION__);
266 286
267 if (has_text_relocations_) { 287 if (has_text_relocations_) {
268 if (phdr_table_unprotect_segments(phdr_, phdr_count_, load_bias_) < 0) { 288 if (phdr_table_unprotect_segments(phdr_, phdr_count_, load_bias_) < 0) {
269 error->Format("Can't unprotect loadable segments: %s", strerror(errno)); 289 error->Format("Can't unprotect loadable segments: %s", strerror(errno));
270 return false; 290 return false;
271 } 291 }
272 } 292 }
273 293
274 if (relocations_type_ == DT_REL) { 294 if (relocations_type_ == DT_REL) {
275 if (!ApplyRelRelocs(reinterpret_cast<ELF::Rel*>(plt_relocations_), 295 if (!ApplyRelRelocs(reinterpret_cast<ELF::Rel*>(plt_relocations_),
276 plt_relocations_size_ / sizeof(ELF::Rel), 296 plt_relocations_size_ / sizeof(ELF::Rel),
277 symbols, 297 symbols,
278 resolver, 298 resolver,
279 error)) 299 error))
280 return false; 300 return false;
281 if (!ApplyRelRelocs(reinterpret_cast<ELF::Rel*>(relocations_), 301 if (!ApplyRelRelocs(reinterpret_cast<ELF::Rel*>(relocations_),
282 relocations_size_ / sizeof(ELF::Rel), 302 relocations_size_ / sizeof(ELF::Rel),
283 symbols, 303 symbols,
284 resolver, 304 resolver,
285 error)) 305 error))
286 return false; 306 return false;
287 } 307 }
288 308
289 else if (relocations_type_ == DT_RELA) { 309 if (relocations_type_ == DT_RELA) {
290 if (!ApplyRelaRelocs(reinterpret_cast<ELF::Rela*>(plt_relocations_), 310 if (!ApplyRelaRelocs(reinterpret_cast<ELF::Rela*>(plt_relocations_),
291 plt_relocations_size_ / sizeof(ELF::Rela), 311 plt_relocations_size_ / sizeof(ELF::Rela),
292 symbols, 312 symbols,
293 resolver, 313 resolver,
294 error)) 314 error))
295 return false; 315 return false;
296 if (!ApplyRelaRelocs(reinterpret_cast<ELF::Rela*>(relocations_), 316 if (!ApplyRelaRelocs(reinterpret_cast<ELF::Rela*>(relocations_),
297 relocations_size_ / sizeof(ELF::Rela), 317 relocations_size_ / sizeof(ELF::Rela),
298 symbols, 318 symbols,
299 resolver, 319 resolver,
300 error)) 320 error))
301 return false; 321 return false;
302 } 322 }
303 323
324 #ifdef __arm__
325 if (!ApplyArmPackedRelocs(full_path, error))
326 return false;
327 #endif
328
304 #ifdef __mips__ 329 #ifdef __mips__
305 if (!RelocateMipsGot(symbols, resolver, error)) 330 if (!RelocateMipsGot(symbols, resolver, error))
306 return false; 331 return false;
307 #endif 332 #endif
308 333
309 if (has_text_relocations_) { 334 if (has_text_relocations_) {
310 if (phdr_table_protect_segments(phdr_, phdr_count_, load_bias_) < 0) { 335 if (phdr_table_protect_segments(phdr_, phdr_count_, load_bias_) < 0) {
311 error->Format("Can't reprotect loadable segments: %s", strerror(errno)); 336 error->Format("Can't reprotect loadable segments: %s", strerror(errno));
312 return false; 337 return false;
313 } 338 }
(...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after
634 error); 659 error);
635 } 660 }
636 661
637 if (!ApplyRelaReloc(rela, sym_addr, resolved, error)) 662 if (!ApplyRelaReloc(rela, sym_addr, resolved, error))
638 return false; 663 return false;
639 } 664 }
640 665
641 return true; 666 return true;
642 } 667 }
643 668
669 #ifdef __arm__
670
671 // Helper class for decoding packed ARM relocation data.
672 // http://en.wikipedia.org/wiki/LEB128
673 class Leb128Decoder {
674 public:
675 explicit Leb128Decoder(const uint8_t* encoding)
676 : encoding_(encoding), cursor_(0) { }
677
678 uint32_t Dequeue() {
679 size_t extent = cursor_;
680 while (encoding_[extent] >> 7)
681 extent++;
682
683 uint32_t value = 0;
684 for (size_t i = extent; i > cursor_; --i) {
685 value = (value << 7) | (encoding_[i] & 127);
686 }
687 value = (value << 7) | (encoding_[cursor_] & 127);
688
689 cursor_ = extent + 1;
690 return value;
691 }
692
693 private:
694 const uint8_t* encoding_;
695 size_t cursor_;
696 };
697
698 // Helper class to provide a simple scoped buffer. ScopedPtr is not
699 // usable here because it calls delete, not delete [].
700 class ScopedBuffer {
701 public:
702 explicit ScopedBuffer(size_t bytes) : buffer_(new uint8_t[bytes]) { }
703 ~ScopedBuffer() { delete [] buffer_; }
704
705 uint8_t* Get() { return buffer_; }
706
707 private:
708 uint8_t* buffer_;
709 };
710
711 bool ElfRelocations::ApplyArmPackedRelocs(const char* full_path,
712 Error* error) {
713 RLOG("%s: packed_relocations=%p, packed_relocations_size=%d\n",
714 __FUNCTION__,
715 arm_packed_relocations_,
716 arm_packed_relocations_size_);
717
718 if (arm_packed_relocations_size_ == 0)
719 return true;
720
721 // Allocate and then read the packed relocations section.
722 ScopedBuffer scoped_packed_data(arm_packed_relocations_size_);
723 uint8_t* packed_data = scoped_packed_data.Get();
724
725 FileDescriptor fd;
726 if (!fd.OpenReadOnly(full_path)) {
727 error->Format("Error opening file '%s'", full_path);
728 return false;
729 }
730 if (fd.SeekTo(arm_packed_relocations_) == -1) {
731 error->Format("Error seeking to %d in file '%s'",
732 arm_packed_relocations_,
733 full_path);
734 return false;
735 }
736 const ssize_t bytes = fd.Read(packed_data, arm_packed_relocations_size_);
737 if (bytes != arm_packed_relocations_size_) {
738 error->Format("Error reading %d bytes from file '%s'",
739 arm_packed_relocations_size_,
740 full_path);
741 return false;
742 }
743 fd.Close();
744
745 Leb128Decoder decoder(packed_data);
746
747 // Check for the initial APR1 header.
748 if (decoder.Dequeue() != 'A' || decoder.Dequeue() != 'P' ||
749 decoder.Dequeue() != 'R' || decoder.Dequeue() != '1') {
750 error->Format("Bad packed relocations ident, expected APR1");
751 return false;
752 }
753
754 // Find the count of pairs and the start address.
755 size_t pairs = decoder.Dequeue();
756 const Elf32_Addr start_address = decoder.Dequeue();
757
758 // Emit initial R_ARM_RELATIVE relocation.
759 Elf32_Rel relocation = {start_address, R_ARM_RELATIVE};
760 const ELF::Addr sym_addr = 0;
761 const bool resolved = false;
762 if (!ApplyRelReloc(&relocation, sym_addr, resolved, error))
763 return false;
764
765 size_t unpacked_count = 1;
766
767 // Emit relocations for each count-delta pair.
768 while (pairs) {
769 size_t count = decoder.Dequeue();
770 const size_t delta = decoder.Dequeue();
771
772 // Emit count R_ARM_RELATIVE relocations with delta offset.
773 while (count) {
774 relocation.r_offset += delta;
775 if (!ApplyRelReloc(&relocation, sym_addr, resolved, error))
776 return false;
777 unpacked_count++;
778 count--;
779 }
780 pairs--;
781 }
782
783 RLOG("%s: unpacked_count=%d\n", __FUNCTION__, unpacked_count);
784 return true;
785 }
786
787 #endif // __arm__
788
644 #ifdef __mips__ 789 #ifdef __mips__
645 bool ElfRelocations::RelocateMipsGot(const ElfSymbols* symbols, 790 bool ElfRelocations::RelocateMipsGot(const ElfSymbols* symbols,
646 SymbolResolver* resolver, 791 SymbolResolver* resolver,
647 Error* error) { 792 Error* error) {
648 if (!plt_got_) 793 if (!plt_got_)
649 return true; 794 return true;
650 795
651 // Handle the local GOT entries. 796 // Handle the local GOT entries.
652 // This mimics what the system linker does. 797 // This mimics what the system linker does.
653 // Note from the system linker: 798 // Note from the system linker:
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after
820 if (got_addr < src_addr || got_addr >= src_addr + size) 965 if (got_addr < src_addr || got_addr >= src_addr + size)
821 continue; 966 continue;
822 ELF::Addr* dst_ptr = reinterpret_cast<ELF::Addr*>(got_addr + dst_delta); 967 ELF::Addr* dst_ptr = reinterpret_cast<ELF::Addr*>(got_addr + dst_delta);
823 *dst_ptr += map_delta; 968 *dst_ptr += map_delta;
824 } 969 }
825 } 970 }
826 #endif 971 #endif
827 } 972 }
828 973
829 } // namespace crazy 974 } // namespace crazy
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698