OLD | NEW |
(Empty) | |
| 1 Introduction: |
| 2 ------------- |
| 3 |
| 4 R_ARM_RELATIVE relocations are the bulk of dynamic relocations (the .rel.dyn |
| 5 section) in libchrome.<version>.so. The ELF standard representation of them |
| 6 is wasteful. |
| 7 |
| 8 Packing uses run length encoding to store them more efficiently. Packed |
| 9 relocations are placed in a new .android.rel.dyn section. Packing reduces |
| 10 the footprint of libchrome.<version>.so in the filesystem, in APK downloads, |
| 11 and in memory when loaded on the device. |
| 12 |
| 13 A packed libchrome.<version>.so is designed so that it can be loaded directly |
| 14 on Android, but requires the explicit support of a crazy linker that has been |
| 15 extended to understand packed relocations. Packed relocations are currently |
| 16 only supported on ARM. |
| 17 |
| 18 A packed libchrome.<version>.so cannot currently be used with the standard |
| 19 Android runtime linker. |
| 20 |
| 21 See src/*.h for design and implementation notes. |
| 22 |
| 23 |
| 24 Notes: |
| 25 ------ |
| 26 |
| 27 Packing does not adjust debug data. An unstripped libchrome.<version>.so |
| 28 can be packed and will run, but may no longer be useful for debugging. |
| 29 |
| 30 Unpacking on the device requires the explicit support of an extended crazy |
| 31 linker. Adds the following new .dynamic tags, used by the crazy linker to |
| 32 find the packed .android.rel.dyn section data: |
| 33 |
| 34 DT_ANDROID_ARM_REL_OFFSET = DT_LOPROC (Processor specific: 0x70000000) |
| 35 - The offset of .android.rel.dyn data in libchrome.<version>.so |
| 36 DT_ANDROID_ARM_REL_SIZE = DT_LOPROC + 1 (Processor Specific: 0x70000001) |
| 37 - The size of .android.rel.dyn data in bytes |
| 38 |
| 39 The format of .android.rel.dyn data is: |
| 40 |
| 41 "APR1" identifier |
| 42 N: the number of count-delta pairs in the encoding |
| 43 A: the initial offset |
| 44 N * C,D: N count-delta pairs |
| 45 |
| 46 All numbers in the encoding stream are stored as LEB128 values. For details |
| 47 see http://en.wikipedia.org/wiki/LEB128. |
| 48 |
| 49 The streaming unpacking algorithm is: |
| 50 |
| 51 skip over "APR1" |
| 52 pairs, addr = next leb128 value, next leb128 value |
| 53 emit R_ARM_RELATIVE relocation with r_offset = addr |
| 54 while pairs: |
| 55 count, delta = next leb128 value, next leb128 value |
| 56 while count: |
| 57 addr += delta |
| 58 emit R_ARM_RELATIVE relocation with r_offset = addr |
| 59 count-- |
| 60 pairs--; |
| 61 |
| 62 |
| 63 Usage instructions: |
| 64 ------------------- |
| 65 |
| 66 To pack relocations, add an empty .android.rel.dyn and then run the tool: |
| 67 |
| 68 echo -n 'NULL' >/tmp/small |
| 69 arm-linux-gnueabi-objcopy \ |
| 70 --add-section .android.rel.dyn=/tmp/small \ |
| 71 libchrome.<version>.so libchrome.<version>.so.packed |
| 72 rm /tmp/small |
| 73 relocation_packer libchrome.<version>.so.packed |
| 74 |
| 75 To unpack and restore the shared library to its original state: |
| 76 |
| 77 cp libchrome.<version>.so.packed unpackable |
| 78 relocation_packer -u unpackable |
| 79 arm-linux-gnueabi-objcopy \ |
| 80 --remove-section=.android.rel.dyn unpackable libchrome.<version>.so |
| 81 rm unpackable |
| 82 |
| 83 |
| 84 Bugs & TODOs: |
| 85 ------------- |
| 86 |
| 87 Currently only supports arm32. Support for arm64 requires some extension |
| 88 and modification. |
| 89 |
| 90 Requires two free slots in the .dynamic section. Uses these to add data that |
| 91 tells the crazy linker where to find the packed .android.rel.dyn data. Fails |
| 92 if insufficient free slots exist (use gold --spare-dynamic-slots to increase |
| 93 the allocation). |
| 94 |
| 95 Requires libelf 0.158 or later. Earlier libelf releases may be buggy in |
| 96 ways that prevent the packer from working correctly. |
| 97 |
| 98 |
| 99 Testing: |
| 100 -------- |
| 101 |
| 102 Unittests run under gtest, on the host system. |
OLD | NEW |