| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "courgette/disassembler_elf_32_arm.h" | 5 #include "courgette/disassembler_elf_32_arm.h" |
| 6 | 6 |
| 7 #include <stddef.h> | |
| 8 #include <stdint.h> | |
| 9 | |
| 10 #include <algorithm> | |
| 11 #include <string> | |
| 12 #include <vector> | 7 #include <vector> |
| 13 | 8 |
| 14 #include "base/logging.h" | 9 #include "base/logging.h" |
| 15 | 10 #include "base/memory/scoped_ptr.h" |
| 16 #include "courgette/assembly_program.h" | 11 #include "courgette/assembly_program.h" |
| 17 #include "courgette/courgette.h" | 12 #include "courgette/courgette.h" |
| 18 #include "courgette/encoded_program.h" | |
| 19 | 13 |
| 20 namespace courgette { | 14 namespace courgette { |
| 21 | 15 |
| 22 CheckBool DisassemblerElf32ARM::Compress(ARM_RVA type, | 16 CheckBool DisassemblerElf32ARM::Compress(ARM_RVA type, |
| 23 uint32_t arm_op, | 17 uint32_t arm_op, |
| 24 RVA rva, | 18 RVA rva, |
| 25 uint16_t* c_op, | 19 uint16_t* c_op, |
| 26 uint32_t* addr) { | 20 uint32_t* addr) { |
| 27 // This method takes an ARM or thumb opcode, extracts the relative | 21 // Notation for bit ranges in comments: |
| 28 // target address from it (addr), and creates a corresponding | 22 // - Listing bits from highest to lowest. |
| 29 // Courgette opcode (c_op). | 23 // - A-Z or (j1), (j2), etc.: single bit in source. |
| 30 // | 24 // - a-z: multiple, consecutive bits in source. |
| 31 // Details on ARM the opcodes, and how the relative targets are | |
| 32 // computed were taken from the "ARM Architecture Reference Manual", | |
| 33 // section A4.1.5 and the "Thumb-2 supplement", section 4.6.12. | |
| 34 // ARM_OFF24 is for the ARM opcode. The rest are for thumb opcodes. | |
| 35 switch (type) { | 25 switch (type) { |
| 36 case ARM_OFF8: { | 26 case ARM_OFF8: { |
| 37 // The offset is given by lower 8 bits of the op. It is a 9-bit | 27 // Encoding T1. |
| 38 // offset, shifted right one bit and signed extended. | 28 // The offset is given by lower 8 bits of the op. It is a 9-bit offset, |
| 29 // shifted right 1 bit, and signed extended. |
| 30 // arm_op = aaaaaaaa Snnnnnnn |
| 31 // *addr := SSSSSSSS SSSSSSSS SSSSSSSS nnnnnnn0 + 100 |
| 32 // *c_op := 00010000 aaaaaaaa |
| 39 uint32_t temp = (arm_op & 0x00FF) << 1; | 33 uint32_t temp = (arm_op & 0x00FF) << 1; |
| 40 if (temp & 0x0100) | 34 if (temp & 0x0100) |
| 41 temp |= 0xFFFFFE00; | 35 temp |= 0xFFFFFE00; |
| 42 temp += 4; // Offset from _next_ PC. | 36 temp += 4; // Offset from _next_ PC. |
| 43 fflush(stdout); | |
| 44 | 37 |
| 45 (*addr) = temp; | 38 (*addr) = temp; |
| 46 (*c_op) = static_cast<uint16_t>(arm_op >> 8) | 0x1000; | 39 (*c_op) = static_cast<uint16_t>(arm_op >> 8) | 0x1000; |
| 47 break; | 40 break; |
| 48 } | 41 } |
| 49 case ARM_OFF11: { | 42 case ARM_OFF11: { |
| 50 // The offset is given by lower 11 bits of the op, and is a | 43 // Encoding T2. |
| 51 // 12-bit offset, shifted right one bit and sign extended. | 44 // The offset is given by lower 11 bits of the op, and is a 12-bit offset, |
| 45 // shifted right 1 bit, and sign extended. |
| 46 // arm_op = aaaaaSnn nnnnnnnn |
| 47 // *addr := SSSSSSSS SSSSSSSS SSSSSnnn nnnnnnn0 + 100 |
| 48 // *c_op := 00100000 000aaaaa |
| 52 uint32_t temp = (arm_op & 0x07FF) << 1; | 49 uint32_t temp = (arm_op & 0x07FF) << 1; |
| 53 if (temp & 0x00000800) | 50 if (temp & 0x00000800) |
| 54 temp |= 0xFFFFF000; | 51 temp |= 0xFFFFF000; |
| 55 temp += 4; // Offset from _next_ PC. | 52 temp += 4; // Offset from _next_ PC. |
| 56 | 53 |
| 57 (*addr) = temp; | 54 (*addr) = temp; |
| 58 (*c_op) = static_cast<uint16_t>(arm_op >> 11) | 0x2000; | 55 (*c_op) = static_cast<uint16_t>(arm_op >> 11) | 0x2000; |
| 59 break; | 56 break; |
| 60 } | 57 } |
| 61 case ARM_OFF24: { | 58 case ARM_OFF24: { |
| 62 // The offset is given by the lower 24-bits of the op, shifted | 59 // The offset is given by the lower 24-bits of the op, shifted |
| 63 // left 2 bits, and sign extended. | 60 // left 2 bits, and sign extended. |
| 61 // arm_op = aaaaaaaa Snnnnnnn nnnnnnnn nnnnnnnn |
| 62 // *addr := SSSSSSSn nnnnnnnn nnnnnnnn nnnnnn00 + 1000 |
| 63 // *c_op := 00110000 aaaaaaaa |
| 64 uint32_t temp = (arm_op & 0x00FFFFFF) << 2; | 64 uint32_t temp = (arm_op & 0x00FFFFFF) << 2; |
| 65 if (temp & 0x02000000) | 65 if (temp & 0x02000000) |
| 66 temp |= 0xFC000000; | 66 temp |= 0xFC000000; |
| 67 temp += 8; | 67 temp += 8; |
| 68 | 68 |
| 69 (*addr) = temp; | 69 (*addr) = temp; |
| 70 (*c_op) = (arm_op >> 24) | 0x3000; | 70 (*c_op) = (arm_op >> 24) | 0x3000; |
| 71 break; | 71 break; |
| 72 } | 72 } |
| 73 case ARM_OFF25: { | 73 case ARM_OFF25: { |
| 74 // Encoding T4. |
| 75 // arm_op = aaaaaSmm mmmmmmmm BC(j1)D(j2)nnn nnnnnnnn |
| 76 // where CD is in {01, 10, 11} |
| 77 // i1 := ~(j1 ^ S) |
| 78 // i2 := ~(j2 ^ S) |
| 79 // If CD == 10: |
| 80 // pppp := (rva % 4 == 0) ? 0100 : 0010 |
| 81 // Else: |
| 82 // pppp := 0100 |
| 83 // *addr := SSSSSSSS (i1)(i2)mmmmmm mmmmnnnn nnnnnnn0 + pppp |
| 84 // *c_op := 0100pppp aaaaaBCD |
| 85 // TODO(huangs): aaaaa = 11110 and B = 1 always? Investigate and fix. |
| 74 uint32_t temp = 0; | 86 uint32_t temp = 0; |
| 75 temp |= (arm_op & 0x000007FF) << 1; // imm11 | 87 temp |= (arm_op & 0x000007FF) << 1; // imm11 |
| 76 temp |= (arm_op & 0x03FF0000) >> 4; // imm10 | 88 temp |= (arm_op & 0x03FF0000) >> 4; // imm10 |
| 77 | 89 |
| 78 uint32_t S = (arm_op & (1 << 26)) >> 26; | 90 uint32_t S = (arm_op & (1 << 26)) >> 26; |
| 79 uint32_t j2 = (arm_op & (1 << 11)) >> 11; | 91 uint32_t j2 = (arm_op & (1 << 11)) >> 11; |
| 80 uint32_t j1 = (arm_op & (1 << 13)) >> 13; | 92 uint32_t j1 = (arm_op & (1 << 13)) >> 13; |
| 81 bool bit12 = ((arm_op & (1 << 12)) >> 12) != 0; | 93 bool bit12 = ((arm_op & (1 << 12)) >> 12) != 0; // D |
| 82 bool bit14 = ((arm_op & (1 << 14)) >> 14) != 0; | 94 bool bit14 = ((arm_op & (1 << 14)) >> 14) != 0; // C |
| 83 | 95 |
| 84 uint32_t i2 = ~(j2 ^ S) & 1; | 96 uint32_t i2 = ~(j2 ^ S) & 1; |
| 85 uint32_t i1 = ~(j1 ^ S) & 1; | 97 uint32_t i1 = ~(j1 ^ S) & 1; |
| 86 bool toARM = bit14 && !bit12; | 98 bool toARM = bit14 && !bit12; |
| 87 | 99 |
| 88 temp |= (S << 24) | (i1 << 23) | (i2 << 22); | 100 temp |= (S << 24) | (i1 << 23) | (i2 << 22); |
| 89 | 101 |
| 90 if (temp & 0x01000000) // sign extension | 102 if (temp & 0x01000000) // sign extension |
| 91 temp |= 0xFE000000; | 103 temp |= 0xFE000000; |
| 92 uint32_t prefetch; | 104 uint32_t prefetch; |
| 93 if (toARM) { | 105 if (toARM) { |
| 94 // Align PC on 4-byte boundary | 106 // Align PC on 4-byte boundary. |
| 95 uint32_t align4byte = (rva % 4) ? 2 : 4; | 107 uint32_t align4byte = (rva % 4) ? 2 : 4; |
| 96 prefetch = align4byte; | 108 prefetch = align4byte; |
| 97 } else { | 109 } else { |
| 98 prefetch = 4; | 110 prefetch = 4; |
| 99 } | 111 } |
| 100 temp += prefetch; | 112 temp += prefetch; |
| 101 (*addr) = temp; | 113 (*addr) = temp; |
| 102 | 114 |
| 103 uint32_t temp2 = 0x4000; | 115 uint32_t temp2 = 0x4000; |
| 104 temp2 |= (arm_op & (1 << 12)) >> 12; | 116 temp2 |= (arm_op & (1 << 12)) >> 12; // .......D |
| 105 temp2 |= (arm_op & (1 << 14)) >> 13; | 117 temp2 |= (arm_op & (1 << 14)) >> 13; // ......C. |
| 106 temp2 |= (arm_op & (1 << 15)) >> 13; | 118 temp2 |= (arm_op & (1 << 15)) >> 13; // .....B.. |
| 107 temp2 |= (arm_op & 0xF8000000) >> 24; | 119 temp2 |= (arm_op & 0xF8000000) >> 24; // aaaaa... |
| 108 temp2 |= (prefetch & 0x0000000F) << 8; | 120 temp2 |= (prefetch & 0x0000000F) << 8; |
| 109 (*c_op) = static_cast<uint16_t>(temp2); | 121 (*c_op) = static_cast<uint16_t>(temp2); |
| 110 break; | 122 break; |
| 111 } | 123 } |
| 112 case ARM_OFF21: { | 124 case ARM_OFF21: { |
| 125 // Encoding T3. |
| 126 // arm_op = 11110Scc ccmmmmmm 10(j1)0(j2)nnn nnnnnnnn |
| 127 // *addr := SSSSSSSS SSSS(j1)(j2)mm mmmmnnnn nnnnnnn0 + 100 |
| 128 // *c_op := 01010000 0000cccc |
| 113 uint32_t temp = 0; | 129 uint32_t temp = 0; |
| 114 temp |= (arm_op & 0x000007FF) << 1; // imm11 | 130 temp |= (arm_op & 0x000007FF) << 1; // imm11 |
| 115 temp |= (arm_op & 0x003F0000) >> 4; // imm6 | 131 temp |= (arm_op & 0x003F0000) >> 4; // imm6 |
| 116 | 132 |
| 117 uint32_t S = (arm_op & (1 << 26)) >> 26; | 133 uint32_t S = (arm_op & (1 << 26)) >> 26; |
| 134 // TODO(huangs): Check with docs: Perhaps j1, j2 should swap? |
| 118 uint32_t j2 = (arm_op & (1 << 11)) >> 11; | 135 uint32_t j2 = (arm_op & (1 << 11)) >> 11; |
| 119 uint32_t j1 = (arm_op & (1 << 13)) >> 13; | 136 uint32_t j1 = (arm_op & (1 << 13)) >> 13; |
| 120 | 137 |
| 121 temp |= (S << 20) | (j1 << 19) | (j2 << 18); | 138 temp |= (S << 20) | (j1 << 19) | (j2 << 18); |
| 122 | 139 |
| 123 if (temp & 0x00100000) // sign extension | 140 if (temp & 0x00100000) // sign extension |
| 124 temp |= 0xFFE00000; | 141 temp |= 0xFFE00000; |
| 125 temp += 4; | 142 temp += 4; |
| 126 (*addr) = temp; | 143 (*addr) = temp; |
| 127 | 144 |
| 128 uint32_t temp2 = 0x5000; | 145 uint32_t temp2 = 0x5000; |
| 129 temp2 |= (arm_op & 0x03C00000) >> 22; // just save the cond | 146 temp2 |= (arm_op & 0x03C00000) >> 22; // just save the cond |
| 130 (*c_op) = static_cast<uint16_t>(temp2); | 147 (*c_op) = static_cast<uint16_t>(temp2); |
| 131 break; | 148 break; |
| 132 } | 149 } |
| 133 default: | 150 default: |
| 134 return false; | 151 return false; |
| 135 } | 152 } |
| 136 return true; | 153 return true; |
| 137 } | 154 } |
| 138 | 155 |
| 139 CheckBool DisassemblerElf32ARM::Decompress(ARM_RVA type, | 156 CheckBool DisassemblerElf32ARM::Decompress(ARM_RVA type, |
| 140 uint16_t c_op, | 157 uint16_t c_op, |
| 141 uint32_t addr, | 158 uint32_t addr, |
| 142 uint32_t* arm_op) { | 159 uint32_t* arm_op) { |
| 143 // Reverses the process in the compress() method. Takes the | |
| 144 // Courgette op and relative address and reconstructs the original | |
| 145 // ARM or thumb op. | |
| 146 switch (type) { | 160 switch (type) { |
| 147 case ARM_OFF8: | 161 case ARM_OFF8: |
| 162 // addr = SSSSSSSS SSSSSSSS SSSSSSSS nnnnnnn0 + 100 |
| 163 // c_op = 00010000 aaaaaaaa |
| 164 // *arm_op := aaaaaaaa Snnnnnnn |
| 148 (*arm_op) = ((c_op & 0x0FFF) << 8) | (((addr - 4) >> 1) & 0x000000FF); | 165 (*arm_op) = ((c_op & 0x0FFF) << 8) | (((addr - 4) >> 1) & 0x000000FF); |
| 149 break; | 166 break; |
| 150 case ARM_OFF11: | 167 case ARM_OFF11: |
| 168 // addr = SSSSSSSS SSSSSSSS SSSSSnnn nnnnnnn0 + 100 |
| 169 // c_op = 00100000 000aaaaa |
| 170 // *arm_op := aaaaaSnn nnnnnnnn |
| 151 (*arm_op) = ((c_op & 0x0FFF) << 11) | (((addr - 4) >> 1) & 0x000007FF); | 171 (*arm_op) = ((c_op & 0x0FFF) << 11) | (((addr - 4) >> 1) & 0x000007FF); |
| 152 break; | 172 break; |
| 153 case ARM_OFF24: | 173 case ARM_OFF24: |
| 174 // addr = SSSSSSSn nnnnnnnn nnnnnnnn nnnnnn00 + 1000 |
| 175 // c_op = 00110000 aaaaaaaa |
| 176 // *arm_op := aaaaaaaa Snnnnnnn nnnnnnnn nnnnnnnn |
| 154 (*arm_op) = ((c_op & 0x0FFF) << 24) | (((addr - 8) >> 2) & 0x00FFFFFF); | 177 (*arm_op) = ((c_op & 0x0FFF) << 24) | (((addr - 8) >> 2) & 0x00FFFFFF); |
| 155 break; | 178 break; |
| 156 case ARM_OFF25: { | 179 case ARM_OFF25: { |
| 180 // addr = SSSSSSSS (i1)(i2)mmmmmm mmmmnnnn nnnnnnn0 + pppp |
| 181 // c_op = 0100pppp aaaaaBCD |
| 182 // j1 := ~i1 ^ S |
| 183 // j2 := ~i2 ^ S |
| 184 // *arm_op := aaaaaSmm mmmmmmmm BC(j1)D(j2)nnn nnnnnnnn |
| 157 uint32_t temp = 0; | 185 uint32_t temp = 0; |
| 158 temp |= (c_op & (1 << 0)) << 12; | 186 temp |= (c_op & (1 << 0)) << 12; |
| 159 temp |= (c_op & (1 << 1)) << 13; | 187 temp |= (c_op & (1 << 1)) << 13; |
| 160 temp |= (c_op & (1 << 2)) << 13; | 188 temp |= (c_op & (1 << 2)) << 13; |
| 161 temp |= (c_op & (0xF8000000 >> 24)) << 24; | 189 temp |= (c_op & (0xF8000000 >> 24)) << 24; |
| 162 | 190 |
| 163 uint32_t prefetch = (c_op & 0x0F00) >> 8; | 191 uint32_t prefetch = (c_op & 0x0F00) >> 8; |
| 164 addr -= prefetch; | 192 addr -= prefetch; |
| 165 | 193 |
| 166 addr &= 0x01FFFFFF; | 194 addr &= 0x01FFFFFF; |
| 167 | 195 |
| 168 uint32_t S = (addr & (1 << 24)) >> 24; | 196 uint32_t S = (addr & (1 << 24)) >> 24; |
| 169 uint32_t i1 = (addr & (1 << 23)) >> 23; | 197 uint32_t i1 = (addr & (1 << 23)) >> 23; |
| 170 uint32_t i2 = (addr & (1 << 22)) >> 22; | 198 uint32_t i2 = (addr & (1 << 22)) >> 22; |
| 171 | 199 |
| 172 uint32_t j1 = ((~i1) ^ S) & 1; | 200 uint32_t j1 = ((~i1) ^ S) & 1; |
| 173 uint32_t j2 = ((~i2) ^ S) & 1; | 201 uint32_t j2 = ((~i2) ^ S) & 1; |
| 174 | 202 |
| 175 temp |= S << 26; | 203 temp |= S << 26; |
| 176 temp |= j2 << 11; | 204 temp |= j2 << 11; |
| 177 temp |= j1 << 13; | 205 temp |= j1 << 13; |
| 178 | 206 |
| 179 temp |= (addr & (0x000007FF << 1)) >> 1; | 207 temp |= (addr & (0x000007FF << 1)) >> 1; |
| 180 temp |= (addr & (0x03FF0000 >> 4)) << 4; | 208 temp |= (addr & (0x03FF0000 >> 4)) << 4; |
| 181 | 209 |
| 182 (*arm_op) = temp; | 210 (*arm_op) = temp; |
| 183 break; | 211 break; |
| 184 } | 212 } |
| 185 case ARM_OFF21: { | 213 case ARM_OFF21: { |
| 214 // addr = SSSSSSSS SSSS(j1)(j2)mm mmmmnnnn nnnnnnn0 + 100 |
| 215 // c_op = 01010000 0000cccc |
| 216 // *arm_op := 11110Scc ccmmmmmm 10(j1)0(j2)nnn nnnnnnnn |
| 186 uint32_t temp = 0xF0008000; | 217 uint32_t temp = 0xF0008000; |
| 187 temp |= (c_op & (0x03C00000 >> 22)) << 22; | 218 temp |= (c_op & (0x03C00000 >> 22)) << 22; |
| 188 | 219 |
| 189 addr -= 4; | 220 addr -= 4; |
| 190 addr &= 0x001FFFFF; | 221 addr &= 0x001FFFFF; |
| 191 | 222 |
| 192 uint32_t S = (addr & (1 << 20)) >> 20; | 223 uint32_t S = (addr & (1 << 20)) >> 20; |
| 193 uint32_t j1 = (addr & (1 << 19)) >> 19; | 224 uint32_t j1 = (addr & (1 << 19)) >> 19; |
| 194 uint32_t j2 = (addr & (1 << 18)) >> 18; | 225 uint32_t j2 = (addr & (1 << 18)) >> 18; |
| 195 | 226 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 223 return 4; | 254 return 4; |
| 224 default: | 255 default: |
| 225 return 0xFFFF; | 256 return 0xFFFF; |
| 226 } | 257 } |
| 227 } | 258 } |
| 228 | 259 |
| 229 CheckBool DisassemblerElf32ARM::TypedRVAARM::ComputeRelativeTarget( | 260 CheckBool DisassemblerElf32ARM::TypedRVAARM::ComputeRelativeTarget( |
| 230 const uint8_t* op_pointer) { | 261 const uint8_t* op_pointer) { |
| 231 arm_op_ = op_pointer; | 262 arm_op_ = op_pointer; |
| 232 switch (type_) { | 263 switch (type_) { |
| 233 case ARM_OFF8: | 264 case ARM_OFF8: // Falls through. |
| 234 // Fall through | |
| 235 case ARM_OFF11: { | 265 case ARM_OFF11: { |
| 236 RVA relative_target; | 266 RVA relative_target; |
| 237 CheckBool ret = Compress(type_, Read16LittleEndian(op_pointer), rva(), | 267 CheckBool ret = Compress(type_, |
| 238 &c_op_, &relative_target); | 268 Read16LittleEndian(op_pointer), |
| 269 rva(), |
| 270 &c_op_, |
| 271 &relative_target); |
| 239 set_relative_target(relative_target); | 272 set_relative_target(relative_target); |
| 240 return ret; | 273 return ret; |
| 241 } | 274 } |
| 242 case ARM_OFF24: { | 275 case ARM_OFF24: { |
| 243 RVA relative_target; | 276 RVA relative_target; |
| 244 CheckBool ret = Compress(type_, Read32LittleEndian(op_pointer), rva(), | 277 CheckBool ret = Compress(type_, |
| 245 &c_op_, &relative_target); | 278 Read32LittleEndian(op_pointer), |
| 279 rva(), |
| 280 &c_op_, |
| 281 &relative_target); |
| 246 set_relative_target(relative_target); | 282 set_relative_target(relative_target); |
| 247 return ret; | 283 return ret; |
| 248 } | 284 } |
| 249 case ARM_OFF25: | 285 case ARM_OFF25: // Falls through. |
| 250 // Fall through | |
| 251 case ARM_OFF21: { | 286 case ARM_OFF21: { |
| 252 // A thumb-2 op is 32 bits stored as two 16-bit words | 287 // A thumb-2 op is 32 bits stored as two 16-bit words |
| 253 uint32_t pval = (Read16LittleEndian(op_pointer) << 16) | | 288 uint32_t pval = (Read16LittleEndian(op_pointer) << 16) | |
| 254 Read16LittleEndian(op_pointer + 2); | 289 Read16LittleEndian(op_pointer + 2); |
| 255 RVA relative_target; | 290 RVA relative_target; |
| 256 CheckBool ret = Compress(type_, pval, rva(), &c_op_, &relative_target); | 291 CheckBool ret = Compress(type_, pval, rva(), &c_op_, &relative_target); |
| 257 set_relative_target(relative_target); | 292 set_relative_target(relative_target); |
| 258 return ret; | 293 return ret; |
| 259 } | 294 } |
| 260 default: | 295 default: |
| 261 return false; | 296 return false; |
| 262 } | 297 } |
| 263 } | 298 } |
| 264 | 299 |
| 265 CheckBool DisassemblerElf32ARM::TypedRVAARM::EmitInstruction( | 300 CheckBool DisassemblerElf32ARM::TypedRVAARM::EmitInstruction( |
| 266 AssemblyProgram* program, | 301 AssemblyProgram* program, |
| 267 RVA target_rva) { | 302 RVA target_rva) { |
| 268 return program->EmitRel32ARM(c_op(), | 303 return program->EmitRel32ARM(c_op(), |
| 269 program->FindOrMakeRel32Label(target_rva), | 304 program->FindOrMakeRel32Label(target_rva), |
| 270 arm_op_, | 305 arm_op_, |
| 271 op_size()); | 306 op_size()); |
| 272 } | 307 } |
| 273 | 308 |
| 274 DisassemblerElf32ARM::DisassemblerElf32ARM(const void* start, size_t length) | 309 DisassemblerElf32ARM::DisassemblerElf32ARM(const void* start, size_t length) |
| 275 : DisassemblerElf32(start, length) { | 310 : DisassemblerElf32(start, length) { |
| 276 } | 311 } |
| 277 | 312 |
| 278 // Convert an ELF relocation struction into an RVA | 313 // Convert an ELF relocation struction into an RVA. |
| 279 CheckBool DisassemblerElf32ARM::RelToRVA(Elf32_Rel rel, RVA* result) const { | 314 CheckBool DisassemblerElf32ARM::RelToRVA(Elf32_Rel rel, RVA* result) const { |
| 315 // The rightmost byte of r_info is the type. |
| 316 elf32_rel_arm_type_values type = |
| 317 static_cast<elf32_rel_arm_type_values>(rel.r_info & 0xFF); |
| 280 | 318 |
| 281 // The rightmost byte of r_info is the type... | 319 // The other 3 bytes of r_info are the symbol. |
| 282 elf32_rel_arm_type_values type = | |
| 283 (elf32_rel_arm_type_values)(unsigned char)rel.r_info; | |
| 284 | |
| 285 // The other 3 bytes of r_info are the symbol | |
| 286 uint32_t symbol = rel.r_info >> 8; | 320 uint32_t symbol = rel.r_info >> 8; |
| 287 | 321 |
| 288 switch(type) | 322 switch (type) { |
| 289 { | |
| 290 case R_ARM_RELATIVE: | 323 case R_ARM_RELATIVE: |
| 291 if (symbol != 0) | 324 if (symbol != 0) |
| 292 return false; | 325 return false; |
| 293 | 326 |
| 294 // This is a basic ABS32 relocation address | 327 // This is a basic ABS32 relocation address. |
| 295 *result = rel.r_offset; | 328 *result = rel.r_offset; |
| 296 return true; | 329 return true; |
| 297 | 330 |
| 298 default: | 331 default: |
| 299 return false; | 332 return false; |
| 300 } | 333 } |
| 301 } | 334 } |
| 302 | 335 |
| 303 CheckBool DisassemblerElf32ARM::ParseRelocationSection( | 336 CheckBool DisassemblerElf32ARM::ParseRelocationSection( |
| 304 const Elf32_Shdr *section_header, | 337 const Elf32_Shdr* section_header, |
| 305 AssemblyProgram* program) { | 338 AssemblyProgram* program) { |
| 306 // This method compresses a contiguous stretch of R_ARM_RELATIVE | 339 // This method compresses a contiguous stretch of R_ARM_RELATIVE entries in |
| 307 // entries in the relocation table with a Courgette relocation table | 340 // the relocation table with a Courgette relocation table instruction. |
| 308 // instruction. It skips any entries at the beginning that appear | 341 // It skips any entries at the beginning that appear in a section that |
| 309 // in a section that Courgette doesn't support, e.g. INIT. | 342 // Courgette doesn't support, e.g. INIT. |
| 343 // |
| 310 // Specifically, the entries should be | 344 // Specifically, the entries should be |
| 311 // (1) In the same relocation table | 345 // (1) In the same relocation table |
| 312 // (2) Are consecutive | 346 // (2) Are consecutive |
| 313 // (3) Are sorted in memory address order | 347 // (3) Are sorted in memory address order |
| 314 // | 348 // |
| 315 // Happily, this is normally the case, but it's not required by spec | 349 // Happily, this is normally the case, but it's not required by spec so we |
| 316 // so we check, and just don't do it if we don't match up. | 350 // check, and just don't do it if we don't match up. |
| 317 // | 351 // |
| 318 // The expectation is that one relocation section will contain | 352 // The expectation is that one relocation section will contain all of our |
| 319 // all of our R_ARM_RELATIVE entries in the expected order followed | 353 // R_ARM_RELATIVE entries in the expected order followed by assorted other |
| 320 // by assorted other entries we can't use special handling for. | 354 // entries we can't use special handling for. |
| 321 | 355 |
| 322 bool match = true; | 356 bool match = true; |
| 323 | 357 |
| 324 // Walk all the bytes in the section, matching relocation table or not | 358 // Walk all the bytes in the section, matching relocation table or not. |
| 325 size_t file_offset = section_header->sh_offset; | 359 FileOffset file_offset = section_header->sh_offset; |
| 326 size_t section_end = section_header->sh_offset + section_header->sh_size; | 360 FileOffset section_end = section_header->sh_offset + section_header->sh_size; |
| 327 | 361 |
| 328 Elf32_Rel *section_relocs_iter = | 362 const Elf32_Rel* section_relocs_iter = reinterpret_cast<const Elf32_Rel*>( |
| 329 (Elf32_Rel *)OffsetToPointer(section_header->sh_offset); | 363 FileOffsetToPointer(section_header->sh_offset)); |
| 330 | 364 |
| 331 uint32_t section_relocs_count = | 365 uint32_t section_relocs_count = |
| 332 section_header->sh_size / section_header->sh_entsize; | 366 section_header->sh_size / section_header->sh_entsize; |
| 333 | 367 |
| 334 if (abs32_locations_.size() > section_relocs_count) | 368 if (abs32_locations_.size() > section_relocs_count) |
| 335 match = false; | 369 match = false; |
| 336 | 370 |
| 337 if (!abs32_locations_.empty()) { | 371 if (!abs32_locations_.empty()) { |
| 338 std::vector<RVA>::iterator reloc_iter = abs32_locations_.begin(); | 372 std::vector<RVA>::iterator reloc_iter = abs32_locations_.begin(); |
| 339 | 373 |
| 340 for (uint32_t i = 0; i < section_relocs_count; i++) { | 374 for (uint32_t i = 0; i < section_relocs_count; ++i) { |
| 341 if (section_relocs_iter->r_offset == *reloc_iter) | 375 if (section_relocs_iter->r_offset == *reloc_iter) |
| 342 break; | 376 break; |
| 343 | 377 |
| 344 if (!ParseSimpleRegion(file_offset, file_offset + sizeof(Elf32_Rel), | 378 if (!ParseSimpleRegion(file_offset, |
| 345 program)) | 379 file_offset + sizeof(Elf32_Rel), |
| 380 program)) { |
| 346 return false; | 381 return false; |
| 382 } |
| 347 | 383 |
| 348 file_offset += sizeof(Elf32_Rel); | 384 file_offset += sizeof(Elf32_Rel); |
| 349 ++section_relocs_iter; | 385 ++section_relocs_iter; |
| 350 } | 386 } |
| 351 | 387 |
| 352 while (match && (reloc_iter != abs32_locations_.end())) { | 388 while (match && (reloc_iter != abs32_locations_.end())) { |
| 353 if (section_relocs_iter->r_info != R_ARM_RELATIVE || | 389 if (section_relocs_iter->r_info != R_ARM_RELATIVE || |
| 354 section_relocs_iter->r_offset != *reloc_iter) | 390 section_relocs_iter->r_offset != *reloc_iter) { |
| 355 match = false; | 391 match = false; |
| 392 } |
| 356 | 393 |
| 357 section_relocs_iter++; | 394 ++section_relocs_iter; |
| 358 reloc_iter++; | 395 ++reloc_iter; |
| 359 file_offset += sizeof(Elf32_Rel); | 396 file_offset += sizeof(Elf32_Rel); |
| 360 } | 397 } |
| 361 | 398 |
| 362 if (match) { | 399 if (match) { |
| 363 // Skip over relocation tables | 400 // Skip over relocation tables |
| 364 if (!program->EmitElfARMRelocationInstruction()) | 401 if (!program->EmitElfARMRelocationInstruction()) |
| 365 return false; | 402 return false; |
| 366 } | 403 } |
| 367 } | 404 } |
| 368 | 405 |
| 369 return ParseSimpleRegion(file_offset, section_end, program); | 406 return ParseSimpleRegion(file_offset, section_end, program); |
| 370 } | 407 } |
| 371 | 408 |
| 409 // TODO(huangs): Detect and avoid overlap with abs32 addresses. |
| 372 CheckBool DisassemblerElf32ARM::ParseRel32RelocsFromSection( | 410 CheckBool DisassemblerElf32ARM::ParseRel32RelocsFromSection( |
| 373 const Elf32_Shdr* section_header) { | 411 const Elf32_Shdr* section_header) { |
| 374 uint32_t start_file_offset = section_header->sh_offset; | 412 FileOffset start_file_offset = section_header->sh_offset; |
| 375 uint32_t end_file_offset = start_file_offset + section_header->sh_size; | 413 FileOffset end_file_offset = start_file_offset + section_header->sh_size; |
| 376 | 414 |
| 377 const uint8_t* start_pointer = OffsetToPointer(start_file_offset); | 415 const uint8_t* start_pointer = FileOffsetToPointer(start_file_offset); |
| 378 const uint8_t* end_pointer = OffsetToPointer(end_file_offset); | 416 const uint8_t* end_pointer = FileOffsetToPointer(end_file_offset); |
| 379 | 417 |
| 380 // Quick way to convert from Pointer to RVA within a single Section is to | 418 // Quick way to convert from Pointer to RVA within a single Section is to |
| 381 // subtract 'pointer_to_rva'. | 419 // subtract |pointer_to_rva|. |
| 382 const uint8_t* const adjust_pointer_to_rva = | 420 const uint8_t* const adjust_pointer_to_rva = |
| 383 start_pointer - section_header->sh_addr; | 421 start_pointer - section_header->sh_addr; |
| 384 | 422 |
| 385 // Find the rel32 relocations. | 423 // Find the rel32 relocations. |
| 386 const uint8_t* p = start_pointer; | 424 const uint8_t* p = start_pointer; |
| 387 bool on_32bit = 1; // 32-bit ARM ops appear on 32-bit boundaries, so track it | 425 bool on_32bit = 1; // 32-bit ARM ops appear on 32-bit boundaries, so track it |
| 388 while (p < end_pointer) { | 426 while (p < end_pointer) { |
| 389 // Heuristic discovery of rel32 locations in instruction stream: are the | 427 // Heuristic discovery of rel32 locations in instruction stream: are the |
| 390 // next few bytes the start of an instruction containing a rel32 | 428 // next few bytes the start of an instruction containing a rel32 |
| 391 // addressing mode? | 429 // addressing mode? |
| 392 | 430 scoped_ptr<TypedRVAARM> rel32_rva; |
| 393 TypedRVAARM* rel32_rva = NULL; | |
| 394 RVA target_rva = 0; | 431 RVA target_rva = 0; |
| 395 bool found = false; | 432 bool found = false; |
| 396 | 433 |
| 397 // 16-bit thumb ops | 434 // 16-bit thumb ops |
| 398 if (!found && (p + 3) <= end_pointer) { | 435 if (!found && p + 3 <= end_pointer) { |
| 399 uint16_t pval = Read16LittleEndian(p); | 436 uint16_t pval = Read16LittleEndian(p); |
| 400 if ((pval & 0xF000) == 0xD000) { | 437 if ((pval & 0xF000) == 0xD000) { |
| 401 RVA rva = static_cast<RVA>(p - adjust_pointer_to_rva); | 438 RVA rva = static_cast<RVA>(p - adjust_pointer_to_rva); |
| 402 | 439 |
| 403 rel32_rva = new TypedRVAARM(ARM_OFF8, rva); | 440 rel32_rva.reset(new TypedRVAARM(ARM_OFF8, rva)); |
| 404 if (!rel32_rva->ComputeRelativeTarget((uint8_t*)p)) { | 441 if (!rel32_rva->ComputeRelativeTarget(p)) |
| 405 return false; | 442 return false; |
| 406 } | 443 |
| 407 target_rva = rel32_rva->rva() + rel32_rva->relative_target(); | 444 target_rva = rel32_rva->rva() + rel32_rva->relative_target(); |
| 408 found = true; | 445 found = true; |
| 409 } else if ((pval & 0xF800) == 0xE000) { | 446 } else if ((pval & 0xF800) == 0xE000) { |
| 410 RVA rva = static_cast<RVA>(p - adjust_pointer_to_rva); | 447 RVA rva = static_cast<RVA>(p - adjust_pointer_to_rva); |
| 411 | 448 |
| 412 rel32_rva = new TypedRVAARM(ARM_OFF11, rva); | 449 rel32_rva.reset(new TypedRVAARM(ARM_OFF11, rva)); |
| 413 if (!rel32_rva->ComputeRelativeTarget((uint8_t*)p)) { | 450 if (!rel32_rva->ComputeRelativeTarget(p)) |
| 414 return false; | 451 return false; |
| 415 } | 452 |
| 416 target_rva = rel32_rva->rva() + rel32_rva->relative_target(); | 453 target_rva = rel32_rva->rva() + rel32_rva->relative_target(); |
| 417 found = true; | 454 found = true; |
| 418 } | 455 } |
| 419 } | 456 } |
| 420 | 457 |
| 421 // thumb-2 ops comprised of two 16-bit words | 458 // thumb-2 ops comprised of two 16-bit words. |
| 422 if (!found && (p + 5) <= end_pointer) { | 459 if (!found && p + 5 <= end_pointer) { |
| 423 // This is really two 16-bit words, not one 32-bit word. | 460 // This is really two 16-bit words, not one 32-bit word. |
| 424 uint32_t pval = (Read16LittleEndian(p) << 16) | Read16LittleEndian(p + 2); | 461 uint32_t pval = (Read16LittleEndian(p) << 16) | Read16LittleEndian(p + 2); |
| 425 if ((pval & 0xF8008000) == 0xF0008000) { | 462 if ((pval & 0xF8008000) == 0xF0008000) { |
| 426 // Covers thumb-2's 32-bit conditional/unconditional branches | 463 // Covers thumb-2's 32-bit conditional/unconditional branches |
| 427 | 464 if ((pval & (1 << 14)) || (pval & (1 << 12))) { |
| 428 if ( (pval & (1 << 14)) || (pval & (1 << 12)) ) { | |
| 429 // A branch, with link, or with link and exchange. | 465 // A branch, with link, or with link and exchange. |
| 430 RVA rva = static_cast<RVA>(p - adjust_pointer_to_rva); | 466 RVA rva = static_cast<RVA>(p - adjust_pointer_to_rva); |
| 431 | 467 |
| 432 rel32_rva = new TypedRVAARM(ARM_OFF25, rva); | 468 rel32_rva.reset(new TypedRVAARM(ARM_OFF25, rva)); |
| 433 if (!rel32_rva->ComputeRelativeTarget((uint8_t*)p)) { | 469 if (!rel32_rva->ComputeRelativeTarget(p)) |
| 434 return false; | 470 return false; |
| 435 } | 471 |
| 436 target_rva = rel32_rva->rva() + rel32_rva->relative_target(); | 472 target_rva = rel32_rva->rva() + rel32_rva->relative_target(); |
| 437 found = true; | 473 found = true; |
| 474 |
| 438 } else { | 475 } else { |
| 439 // TODO(paulgazz) make sure cond is not 111 | 476 // TODO(paulgazz) make sure cond is not 111 |
| 440 // A conditional branch instruction | 477 // A conditional branch instruction |
| 441 RVA rva = static_cast<RVA>(p - adjust_pointer_to_rva); | 478 RVA rva = static_cast<RVA>(p - adjust_pointer_to_rva); |
| 442 | 479 |
| 443 rel32_rva = new TypedRVAARM(ARM_OFF21, rva); | 480 rel32_rva.reset(new TypedRVAARM(ARM_OFF21, rva)); |
| 444 if (!rel32_rva->ComputeRelativeTarget((uint8_t*)p)) { | 481 if (!rel32_rva->ComputeRelativeTarget(p)) |
| 445 return false; | 482 return false; |
| 446 } | 483 |
| 447 target_rva = rel32_rva->rva() + rel32_rva->relative_target(); | 484 target_rva = rel32_rva->rva() + rel32_rva->relative_target(); |
| 448 found = true; | 485 found = true; |
| 449 } | 486 } |
| 450 } | 487 } |
| 451 } | 488 } |
| 452 | 489 |
| 453 // 32-bit ARM ops | 490 // 32-bit ARM ops. |
| 454 if (!found && on_32bit && (p + 5) <= end_pointer) { | 491 if (!found && on_32bit && (p + 5) <= end_pointer) { |
| 455 uint32_t pval = Read32LittleEndian(p); | 492 uint32_t pval = Read32LittleEndian(p); |
| 456 if ((pval & 0x0E000000) == 0x0A000000) { | 493 if ((pval & 0x0E000000) == 0x0A000000) { |
| 457 // Covers both 0x0A 0x0B ARM relative branches | 494 // Covers both 0x0A 0x0B ARM relative branches |
| 458 RVA rva = static_cast<RVA>(p - adjust_pointer_to_rva); | 495 RVA rva = static_cast<RVA>(p - adjust_pointer_to_rva); |
| 459 | 496 |
| 460 rel32_rva = new TypedRVAARM(ARM_OFF24, rva); | 497 rel32_rva.reset(new TypedRVAARM(ARM_OFF24, rva)); |
| 461 if (!rel32_rva->ComputeRelativeTarget((uint8_t*)p)) { | 498 if (!rel32_rva->ComputeRelativeTarget(p)) |
| 462 return false; | 499 return false; |
| 463 } | 500 |
| 464 target_rva = rel32_rva->rva() + rel32_rva->relative_target(); | 501 target_rva = rel32_rva->rva() + rel32_rva->relative_target(); |
| 465 found = true; | 502 found = true; |
| 466 } | 503 } |
| 467 } | 504 } |
| 468 | 505 |
| 469 if (found && IsValidRVA(target_rva)) { | 506 if (found && IsValidTargetRVA(target_rva)) { |
| 470 rel32_locations_.push_back(rel32_rva); | 507 uint16_t op_size = rel32_rva->op_size(); |
| 508 rel32_locations_.push_back(rel32_rva.release()); |
| 471 #if COURGETTE_HISTOGRAM_TARGETS | 509 #if COURGETTE_HISTOGRAM_TARGETS |
| 472 ++rel32_target_rvas_[target_rva]; | 510 ++rel32_target_rvas_[target_rva]; |
| 473 #endif | 511 #endif |
| 474 p += rel32_rva->op_size(); | 512 p += op_size; |
| 475 | 513 |
| 476 // A tricky way to update the on_32bit flag. Here is the truth table: | 514 // A tricky way to update the on_32bit flag. Here is the truth table: |
| 477 // on_32bit | on_32bit size is 4 | 515 // on_32bit | on_32bit size is 4 |
| 478 // ---------+--------------------- | 516 // ---------+--------------------- |
| 479 // 1 | 0 0 | 517 // 1 | 0 0 |
| 480 // 0 | 0 1 | 518 // 0 | 0 1 |
| 481 // 0 | 1 0 | 519 // 0 | 1 0 |
| 482 // 1 | 1 1 | 520 // 1 | 1 1 |
| 483 on_32bit = (~(on_32bit ^ (rel32_rva->op_size() == 4))) != 0; | 521 on_32bit = (~(on_32bit ^ (op_size == 4))) != 0; |
| 484 } else { | 522 } else { |
| 485 // Move 2 bytes at a time, but track 32-bit boundaries | 523 // Move 2 bytes at a time, but track 32-bit boundaries |
| 486 p += 2; | 524 p += 2; |
| 487 on_32bit = ((on_32bit + 1) % 2) != 0; | 525 on_32bit = ((on_32bit + 1) % 2) != 0; |
| 488 } | 526 } |
| 489 } | 527 } |
| 490 | 528 |
| 491 return true; | 529 return true; |
| 492 } | 530 } |
| 493 | 531 |
| 494 } // namespace courgette | 532 } // namespace courgette |
| OLD | NEW |