1 Introduction: 2 ------------- 3 4 Relative relocations are the bulk of dynamic relocations (the .rel.dyn 5 or .rela.dyn sections) in libchrome.<version>.so. The ELF standard 6 representation of them is wasteful. 7 8 Packing uses a combination of run length encoding, delta encoding, and LEB128 9 encoding to store them more efficiently. Packed relocations are placed in 10 a new .android.rel.dyn or .android.rela.dyn section. Packing reduces 11 the footprint of libchrome.<version>.so in the filesystem, in APK downloads, 12 and in memory when loaded on the device. 13 14 A packed libchrome.<version>.so is designed so that it can be loaded directly 15 on Android, but requires the explicit support of a crazy linker that has been 16 extended to understand packed relocations. Packed relocations are currently 17 only supported on ARM. 18 19 A packed libchrome.<version>.so cannot currently be used with the standard 20 Android runtime linker. 21 22 See src/*.h for design and implementation notes. 23 24 25 Notes: 26 ------ 27 28 Packing does not adjust debug data. An unstripped libchrome.<version>.so 29 can be packed and will run, but may no longer be useful for debugging. 30 31 Unpacking on the device requires the explicit support of an extended crazy 32 linker. Adds the following new .dynamic tags, used by the crazy linker to 33 find the packed .android.rel.dyn or .android.rela.dyn section data: 34 35 DT_ANDROID_REL_OFFSET = DT_LOOS (Operating System specific: 0x6000000d) 36 - The offset of packed relocation data in libchrome.<version>.so 37 DT_ANDROID_REL_SIZE = DT_LOOS + 1 (Operating System Specific: 0x6000000e) 38 - The size of packed relocation data in bytes 39 40 32 bit ARM libraries use relocations without addends. 64 bit ARM libraries 41 use relocations with addends. The packing strategy necessarily differs for 42 the two relocation types. 43 44 Where libchrome.<version>.so contains relocations without addends, the format 45 of .android.rel.dyn data is: 46 47 "APR1" identifier 48 N: the number of count-delta pairs in the encoding 49 A: the initial offset 50 N * C,D: N count-delta pairs 51 52 Where libchrome.<version>.so contains relocations with addends, the format 53 of .android.rela.dyn data is: 54 55 "APA1" identifier 56 N: the number of addr-addend delta pairs in the encoding 57 N * A,V: N addr-addend delta pairs 58 59 All numbers in the encoding stream are stored as LEB128 values. For details 60 see http://en.wikipedia.org/wiki/LEB128. 61 62 The streaming unpacking algorithm for 32 bit ARM is: 63 64 skip over "APR1" 65 pairs, addr = next leb128 value, next leb128 value 66 emit R_ARM_RELATIVE relocation with r_offset = addr 67 while pairs: 68 count, delta = next leb128 value, next leb128 value 69 while count: 70 addr += delta 71 emit R_ARM_RELATIVE relocation with r_offset = addr 72 count-- 73 pairs--; 74 75 The streaming unpacking algorithm for 64 bit ARM is: 76 77 skip over "APA1" 78 pairs = next signed leb128 value 79 addr, addend = 0, 0 80 while pairs: 81 addr += next signed leb128 value 82 addend += next signed leb128 value 83 emit R_AARCH64_RELATIVE relocation with r_offset = addr, r_addend = addend 84 pairs--; 85 86 87 Usage instructions: 88 ------------------- 89 90 To pack relocations, add an empty .android.rel.dyn or .android.rela.dyn and 91 then run the tool: 92 93 echo -n 'NULL' >/tmp/small 94 if file libchrome.<version>.so | grep -q 'ELF 32'; then 95 arm-linux-androideabi-objcopy 96 --add-section .android.rel.dyn=/tmp/small 97 libchrome.<version>.so libchrome.<version>.so.packed 98 else 99 aarch64-linux-android-objcopy 100 --add-section .android.rela.dyn=/tmp/small 101 libchrome.<version>.so libchrome.<version>.so.packed 102 fi 103 rm /tmp/small 104 relocation_packer libchrome.<version>.so.packed 105 106 To unpack and restore the shared library to its original state: 107 108 cp libchrome.<version>.so.packed unpackable 109 relocation_packer -u unpackable 110 if file libchrome.<version>.so | grep -q 'ELF 32'; then 111 arm-linux-androideabi-objcopy \ 112 --remove-section=.android.rel.dyn unpackable libchrome.<version>.so 113 else 114 aarch64-linux-android-objcopy \ 115 --remove-section=.android.rela.dyn unpackable libchrome.<version>.so 116 endif 117 rm unpackable 118 119 120 Bugs & TODOs: 121 ------------- 122 123 Requires two free slots in the .dynamic section. Uses these to add data that 124 tells the crazy linker where to find the packed relocation data. Fails 125 if insufficient free slots exist (use gold --spare-dynamic-slots to increase 126 the allocation). 127 128 Requires libelf 0.158 or later. Earlier libelf releases may be buggy in 129 ways that prevent the packer from working correctly. 130 131 132 Testing: 133 -------- 134 135 Unittests run under gtest, on the host system. 136