| 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 28 matching lines...) Expand all Loading... |
| 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: |
| 234 // Fall through | 265 // Falls through. |
| 235 case ARM_OFF11: { | 266 case ARM_OFF11: { |
| 236 RVA relative_target; | 267 RVA relative_target; |
| 237 CheckBool ret = Compress(type_, Read16LittleEndian(op_pointer), rva(), | 268 CheckBool ret = Compress(type_, |
| 238 &c_op_, &relative_target); | 269 Read16LittleEndian(op_pointer), |
| 270 rva(), |
| 271 &c_op_, |
| 272 &relative_target); |
| 239 set_relative_target(relative_target); | 273 set_relative_target(relative_target); |
| 240 return ret; | 274 return ret; |
| 241 } | 275 } |
| 242 case ARM_OFF24: { | 276 case ARM_OFF24: { |
| 243 RVA relative_target; | 277 RVA relative_target; |
| 244 CheckBool ret = Compress(type_, Read32LittleEndian(op_pointer), rva(), | 278 CheckBool ret = Compress(type_, |
| 245 &c_op_, &relative_target); | 279 Read32LittleEndian(op_pointer), |
| 280 rva(), |
| 281 &c_op_, |
| 282 &relative_target); |
| 246 set_relative_target(relative_target); | 283 set_relative_target(relative_target); |
| 247 return ret; | 284 return ret; |
| 248 } | 285 } |
| 249 case ARM_OFF25: | 286 case ARM_OFF25: |
| 250 // Fall through | 287 // Fall through |
| 251 case ARM_OFF21: { | 288 case ARM_OFF21: { |
| 252 // A thumb-2 op is 32 bits stored as two 16-bit words | 289 // A thumb-2 op is 32 bits stored as two 16-bit words |
| 253 uint32_t pval = (Read16LittleEndian(op_pointer) << 16) | | 290 uint32_t pval = (Read16LittleEndian(op_pointer) << 16) | |
| 254 Read16LittleEndian(op_pointer + 2); | 291 Read16LittleEndian(op_pointer + 2); |
| 255 RVA relative_target; | 292 RVA relative_target; |
| 256 CheckBool ret = Compress(type_, pval, rva(), &c_op_, &relative_target); | 293 CheckBool ret = Compress(type_, pval, rva(), &c_op_, &relative_target); |
| 257 set_relative_target(relative_target); | 294 set_relative_target(relative_target); |
| 258 return ret; | 295 return ret; |
| 259 } | 296 } |
| 260 default: | 297 default: |
| 261 return false; | 298 return false; |
| 262 } | 299 } |
| 263 } | 300 } |
| 264 | 301 |
| 265 CheckBool DisassemblerElf32ARM::TypedRVAARM::EmitInstruction( | 302 CheckBool DisassemblerElf32ARM::TypedRVAARM::EmitInstruction( |
| 266 AssemblyProgram* program, | 303 AssemblyProgram* program, |
| 267 RVA target_rva) { | 304 RVA target_rva) { |
| 268 return program->EmitRel32ARM(c_op(), | 305 return program->EmitRel32ARM(c_op(), |
| 269 program->FindOrMakeRel32Label(target_rva), | 306 program->FindOrMakeRel32Label(target_rva), |
| 270 arm_op_, | 307 arm_op_, |
| 271 op_size()); | 308 op_size()); |
| 272 } | 309 } |
| 273 | 310 |
| 274 DisassemblerElf32ARM::DisassemblerElf32ARM(const void* start, size_t length) | 311 DisassemblerElf32ARM::DisassemblerElf32ARM(const void* start, size_t length) |
| 275 : DisassemblerElf32(start, length) { | 312 : DisassemblerElf32(start, length) { |
| 276 } | 313 } |
| 277 | 314 |
| 278 // Convert an ELF relocation struction into an RVA | 315 // Convert an ELF relocation struction into an RVA. |
| 279 CheckBool DisassemblerElf32ARM::RelToRVA(Elf32_Rel rel, RVA* result) const { | 316 CheckBool DisassemblerElf32ARM::RelToRVA(Elf32_Rel rel, RVA* result) const { |
| 317 // The rightmost byte of r_info is the type. |
| 318 elf32_rel_arm_type_values type = |
| 319 static_cast<elf32_rel_arm_type_values>(rel.r_info & 0xFF); |
| 280 | 320 |
| 281 // The rightmost byte of r_info is the type... | 321 // 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; | 322 uint32_t symbol = rel.r_info >> 8; |
| 287 | 323 |
| 288 switch(type) | 324 switch(type) { |
| 289 { | |
| 290 case R_ARM_RELATIVE: | 325 case R_ARM_RELATIVE: |
| 291 if (symbol != 0) | 326 if (symbol != 0) |
| 292 return false; | 327 return false; |
| 293 | 328 |
| 294 // This is a basic ABS32 relocation address | 329 // This is a basic ABS32 relocation address. |
| 295 *result = rel.r_offset; | 330 *result = rel.r_offset; |
| 296 return true; | 331 return true; |
| 297 | 332 |
| 298 default: | 333 default: |
| 299 return false; | 334 return false; |
| 300 } | 335 } |
| 301 } | 336 } |
| 302 | 337 |
| 303 CheckBool DisassemblerElf32ARM::ParseRelocationSection( | 338 CheckBool DisassemblerElf32ARM::ParseRelocationSection( |
| 304 const Elf32_Shdr *section_header, | 339 const Elf32_Shdr* section_header, |
| 305 AssemblyProgram* program) { | 340 AssemblyProgram* program) { |
| 306 // This method compresses a contiguous stretch of R_ARM_RELATIVE | 341 // This method compresses a contiguous stretch of R_ARM_RELATIVE entries in |
| 307 // entries in the relocation table with a Courgette relocation table | 342 // the relocation table with a Courgette relocation table instruction. |
| 308 // instruction. It skips any entries at the beginning that appear | 343 // 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. | 344 // Courgette doesn't support, e.g. INIT. |
| 345 // |
| 310 // Specifically, the entries should be | 346 // Specifically, the entries should be |
| 311 // (1) In the same relocation table | 347 // (1) In the same relocation table |
| 312 // (2) Are consecutive | 348 // (2) Are consecutive |
| 313 // (3) Are sorted in memory address order | 349 // (3) Are sorted in memory address order |
| 314 // | 350 // |
| 315 // Happily, this is normally the case, but it's not required by spec | 351 // 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. | 352 // check, and just don't do it if we don't match up. |
| 317 // | 353 // |
| 318 // The expectation is that one relocation section will contain | 354 // 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 | 355 // R_ARM_RELATIVE entries in the expected order followed by assorted other |
| 320 // by assorted other entries we can't use special handling for. | 356 // entries we can't use special handling for. |
| 321 | 357 |
| 322 bool match = true; | 358 bool match = true; |
| 323 | 359 |
| 324 // Walk all the bytes in the section, matching relocation table or not | 360 // Walk all the bytes in the section, matching relocation table or not. |
| 325 size_t file_offset = section_header->sh_offset; | 361 FileOffset file_offset = section_header->sh_offset; |
| 326 size_t section_end = section_header->sh_offset + section_header->sh_size; | 362 FileOffset section_end = section_header->sh_offset + section_header->sh_size; |
| 327 | 363 |
| 328 Elf32_Rel *section_relocs_iter = | 364 const Elf32_Rel* section_relocs_iter = reinterpret_cast<const Elf32_Rel*>( |
| 329 (Elf32_Rel *)OffsetToPointer(section_header->sh_offset); | 365 FileOffsetToPointer(section_header->sh_offset)); |
| 330 | 366 |
| 331 uint32_t section_relocs_count = | 367 uint32_t section_relocs_count = |
| 332 section_header->sh_size / section_header->sh_entsize; | 368 section_header->sh_size / section_header->sh_entsize; |
| 333 | 369 |
| 334 if (abs32_locations_.size() > section_relocs_count) | 370 if (abs32_locations_.size() > section_relocs_count) |
| 335 match = false; | 371 match = false; |
| 336 | 372 |
| 337 if (!abs32_locations_.empty()) { | 373 if (!abs32_locations_.empty()) { |
| 338 std::vector<RVA>::iterator reloc_iter = abs32_locations_.begin(); | 374 std::vector<RVA>::iterator reloc_iter = abs32_locations_.begin(); |
| 339 | 375 |
| 340 for (uint32_t i = 0; i < section_relocs_count; i++) { | 376 for (uint32_t i = 0; i < section_relocs_count; ++i) { |
| 341 if (section_relocs_iter->r_offset == *reloc_iter) | 377 if (section_relocs_iter->r_offset == *reloc_iter) |
| 342 break; | 378 break; |
| 343 | 379 |
| 344 if (!ParseSimpleRegion(file_offset, file_offset + sizeof(Elf32_Rel), | 380 if (!ParseSimpleRegion(file_offset, |
| 345 program)) | 381 file_offset + sizeof(Elf32_Rel), |
| 382 program)) { |
| 346 return false; | 383 return false; |
| 384 } |
| 347 | 385 |
| 348 file_offset += sizeof(Elf32_Rel); | 386 file_offset += sizeof(Elf32_Rel); |
| 349 ++section_relocs_iter; | 387 ++section_relocs_iter; |
| 350 } | 388 } |
| 351 | 389 |
| 352 while (match && (reloc_iter != abs32_locations_.end())) { | 390 while (match && (reloc_iter != abs32_locations_.end())) { |
| 353 if (section_relocs_iter->r_info != R_ARM_RELATIVE || | 391 if (section_relocs_iter->r_info != R_ARM_RELATIVE || |
| 354 section_relocs_iter->r_offset != *reloc_iter) | 392 section_relocs_iter->r_offset != *reloc_iter) { |
| 355 match = false; | 393 match = false; |
| 394 } |
| 356 | 395 |
| 357 section_relocs_iter++; | 396 ++section_relocs_iter; |
| 358 reloc_iter++; | 397 ++reloc_iter; |
| 359 file_offset += sizeof(Elf32_Rel); | 398 file_offset += sizeof(Elf32_Rel); |
| 360 } | 399 } |
| 361 | 400 |
| 362 if (match) { | 401 if (match) { |
| 363 // Skip over relocation tables | 402 // Skip over relocation tables |
| 364 if (!program->EmitElfARMRelocationInstruction()) | 403 if (!program->EmitElfARMRelocationInstruction()) |
| 365 return false; | 404 return false; |
| 366 } | 405 } |
| 367 } | 406 } |
| 368 | 407 |
| 369 return ParseSimpleRegion(file_offset, section_end, program); | 408 return ParseSimpleRegion(file_offset, section_end, program); |
| 370 } | 409 } |
| 371 | 410 |
| 411 // TODO(huangs): Detect and avoid overlap with abs32 addresses. |
| 372 CheckBool DisassemblerElf32ARM::ParseRel32RelocsFromSection( | 412 CheckBool DisassemblerElf32ARM::ParseRel32RelocsFromSection( |
| 373 const Elf32_Shdr* section_header) { | 413 const Elf32_Shdr* section_header) { |
| 374 uint32_t start_file_offset = section_header->sh_offset; | 414 FileOffset start_file_offset = section_header->sh_offset; |
| 375 uint32_t end_file_offset = start_file_offset + section_header->sh_size; | 415 FileOffset end_file_offset = start_file_offset + section_header->sh_size; |
| 376 | 416 |
| 377 const uint8_t* start_pointer = OffsetToPointer(start_file_offset); | 417 const uint8_t* start_pointer = FileOffsetToPointer(start_file_offset); |
| 378 const uint8_t* end_pointer = OffsetToPointer(end_file_offset); | 418 const uint8_t* end_pointer = FileOffsetToPointer(end_file_offset); |
| 379 | 419 |
| 380 // Quick way to convert from Pointer to RVA within a single Section is to | 420 // Quick way to convert from Pointer to RVA within a single Section is to |
| 381 // subtract 'pointer_to_rva'. | 421 // subtract |pointer_to_rva|. |
| 382 const uint8_t* const adjust_pointer_to_rva = | 422 const uint8_t* const adjust_pointer_to_rva = |
| 383 start_pointer - section_header->sh_addr; | 423 start_pointer - section_header->sh_addr; |
| 384 | 424 |
| 385 // Find the rel32 relocations. | 425 // Find the rel32 relocations. |
| 386 const uint8_t* p = start_pointer; | 426 const uint8_t* p = start_pointer; |
| 387 bool on_32bit = 1; // 32-bit ARM ops appear on 32-bit boundaries, so track it | 427 bool on_32bit = 1; // 32-bit ARM ops appear on 32-bit boundaries, so track it |
| 388 while (p < end_pointer) { | 428 while (p < end_pointer) { |
| 389 // Heuristic discovery of rel32 locations in instruction stream: are the | 429 // Heuristic discovery of rel32 locations in instruction stream: are the |
| 390 // next few bytes the start of an instruction containing a rel32 | 430 // next few bytes the start of an instruction containing a rel32 |
| 391 // addressing mode? | 431 // addressing mode? |
| 392 | 432 scoped_ptr<TypedRVAARM> rel32_rva; |
| 393 TypedRVAARM* rel32_rva = NULL; | |
| 394 RVA target_rva = 0; | 433 RVA target_rva = 0; |
| 395 bool found = false; | 434 bool found = false; |
| 396 | 435 |
| 397 // 16-bit thumb ops | 436 // 16-bit thumb ops |
| 398 if (!found && (p + 3) <= end_pointer) { | 437 if (!found && p + 3 <= end_pointer) { |
| 399 uint16_t pval = Read16LittleEndian(p); | 438 uint16_t pval = Read16LittleEndian(p); |
| 400 if ((pval & 0xF000) == 0xD000) { | 439 if ((pval & 0xF000) == 0xD000) { |
| 401 RVA rva = static_cast<RVA>(p - adjust_pointer_to_rva); | 440 RVA rva = static_cast<RVA>(p - adjust_pointer_to_rva); |
| 402 | 441 |
| 403 rel32_rva = new TypedRVAARM(ARM_OFF8, rva); | 442 rel32_rva.reset(new TypedRVAARM(ARM_OFF8, rva)); |
| 404 if (!rel32_rva->ComputeRelativeTarget((uint8_t*)p)) { | 443 if (!rel32_rva->ComputeRelativeTarget(p)) |
| 405 return false; | 444 return false; |
| 406 } | 445 |
| 407 target_rva = rel32_rva->rva() + rel32_rva->relative_target(); | 446 target_rva = rel32_rva->rva() + rel32_rva->relative_target(); |
| 408 found = true; | 447 found = true; |
| 409 } else if ((pval & 0xF800) == 0xE000) { | 448 } else if ((pval & 0xF800) == 0xE000) { |
| 410 RVA rva = static_cast<RVA>(p - adjust_pointer_to_rva); | 449 RVA rva = static_cast<RVA>(p - adjust_pointer_to_rva); |
| 411 | 450 |
| 412 rel32_rva = new TypedRVAARM(ARM_OFF11, rva); | 451 rel32_rva.reset(new TypedRVAARM(ARM_OFF11, rva)); |
| 413 if (!rel32_rva->ComputeRelativeTarget((uint8_t*)p)) { | 452 if (!rel32_rva->ComputeRelativeTarget(p)) |
| 414 return false; | 453 return false; |
| 415 } | 454 |
| 416 target_rva = rel32_rva->rva() + rel32_rva->relative_target(); | 455 target_rva = rel32_rva->rva() + rel32_rva->relative_target(); |
| 417 found = true; | 456 found = true; |
| 418 } | 457 } |
| 419 } | 458 } |
| 420 | 459 |
| 421 // thumb-2 ops comprised of two 16-bit words | 460 // thumb-2 ops comprised of two 16-bit words. |
| 422 if (!found && (p + 5) <= end_pointer) { | 461 if (!found && p + 5 <= end_pointer) { |
| 423 // This is really two 16-bit words, not one 32-bit word. | 462 // This is really two 16-bit words, not one 32-bit word. |
| 424 uint32_t pval = (Read16LittleEndian(p) << 16) | Read16LittleEndian(p + 2); | 463 uint32_t pval = (Read16LittleEndian(p) << 16) | Read16LittleEndian(p + 2); |
| 425 if ((pval & 0xF8008000) == 0xF0008000) { | 464 if ((pval & 0xF8008000) == 0xF0008000) { |
| 426 // Covers thumb-2's 32-bit conditional/unconditional branches | 465 // Covers thumb-2's 32-bit conditional/unconditional branches |
| 427 | 466 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. | 467 // A branch, with link, or with link and exchange. |
| 430 RVA rva = static_cast<RVA>(p - adjust_pointer_to_rva); | 468 RVA rva = static_cast<RVA>(p - adjust_pointer_to_rva); |
| 431 | 469 |
| 432 rel32_rva = new TypedRVAARM(ARM_OFF25, rva); | 470 rel32_rva.reset(new TypedRVAARM(ARM_OFF25, rva)); |
| 433 if (!rel32_rva->ComputeRelativeTarget((uint8_t*)p)) { | 471 if (!rel32_rva->ComputeRelativeTarget(p)) |
| 434 return false; | 472 return false; |
| 435 } | 473 |
| 436 target_rva = rel32_rva->rva() + rel32_rva->relative_target(); | 474 target_rva = rel32_rva->rva() + rel32_rva->relative_target(); |
| 437 found = true; | 475 found = true; |
| 476 |
| 438 } else { | 477 } else { |
| 439 // TODO(paulgazz) make sure cond is not 111 | 478 // TODO(paulgazz) make sure cond is not 111 |
| 440 // A conditional branch instruction | 479 // A conditional branch instruction |
| 441 RVA rva = static_cast<RVA>(p - adjust_pointer_to_rva); | 480 RVA rva = static_cast<RVA>(p - adjust_pointer_to_rva); |
| 442 | 481 |
| 443 rel32_rva = new TypedRVAARM(ARM_OFF21, rva); | 482 rel32_rva.reset(new TypedRVAARM(ARM_OFF21, rva)); |
| 444 if (!rel32_rva->ComputeRelativeTarget((uint8_t*)p)) { | 483 if (!rel32_rva->ComputeRelativeTarget(p)) |
| 445 return false; | 484 return false; |
| 446 } | 485 |
| 447 target_rva = rel32_rva->rva() + rel32_rva->relative_target(); | 486 target_rva = rel32_rva->rva() + rel32_rva->relative_target(); |
| 448 found = true; | 487 found = true; |
| 449 } | 488 } |
| 450 } | 489 } |
| 451 } | 490 } |
| 452 | 491 |
| 453 // 32-bit ARM ops | 492 // 32-bit ARM ops. |
| 454 if (!found && on_32bit && (p + 5) <= end_pointer) { | 493 if (!found && on_32bit && (p + 5) <= end_pointer) { |
| 455 uint32_t pval = Read32LittleEndian(p); | 494 uint32_t pval = Read32LittleEndian(p); |
| 456 if ((pval & 0x0E000000) == 0x0A000000) { | 495 if ((pval & 0x0E000000) == 0x0A000000) { |
| 457 // Covers both 0x0A 0x0B ARM relative branches | 496 // Covers both 0x0A 0x0B ARM relative branches |
| 458 RVA rva = static_cast<RVA>(p - adjust_pointer_to_rva); | 497 RVA rva = static_cast<RVA>(p - adjust_pointer_to_rva); |
| 459 | 498 |
| 460 rel32_rva = new TypedRVAARM(ARM_OFF24, rva); | 499 rel32_rva.reset(new TypedRVAARM(ARM_OFF24, rva)); |
| 461 if (!rel32_rva->ComputeRelativeTarget((uint8_t*)p)) { | 500 if (!rel32_rva->ComputeRelativeTarget(p)) |
| 462 return false; | 501 return false; |
| 463 } | 502 |
| 464 target_rva = rel32_rva->rva() + rel32_rva->relative_target(); | 503 target_rva = rel32_rva->rva() + rel32_rva->relative_target(); |
| 465 found = true; | 504 found = true; |
| 466 } | 505 } |
| 467 } | 506 } |
| 468 | 507 |
| 469 if (found && IsValidRVA(target_rva)) { | 508 if (found && IsValidTargetRVA(target_rva)) { |
| 470 rel32_locations_.push_back(rel32_rva); | 509 uint16_t op_size = rel32_rva->op_size(); |
| 510 rel32_locations_.push_back(rel32_rva.release()); |
| 471 #if COURGETTE_HISTOGRAM_TARGETS | 511 #if COURGETTE_HISTOGRAM_TARGETS |
| 472 ++rel32_target_rvas_[target_rva]; | 512 ++rel32_target_rvas_[target_rva]; |
| 473 #endif | 513 #endif |
| 474 p += rel32_rva->op_size(); | 514 p += op_size; |
| 475 | 515 |
| 476 // A tricky way to update the on_32bit flag. Here is the truth table: | 516 // A tricky way to update the on_32bit flag. Here is the truth table: |
| 477 // on_32bit | on_32bit size is 4 | 517 // on_32bit | on_32bit size is 4 |
| 478 // ---------+--------------------- | 518 // ---------+--------------------- |
| 479 // 1 | 0 0 | 519 // 1 | 0 0 |
| 480 // 0 | 0 1 | 520 // 0 | 0 1 |
| 481 // 0 | 1 0 | 521 // 0 | 1 0 |
| 482 // 1 | 1 1 | 522 // 1 | 1 1 |
| 483 on_32bit = (~(on_32bit ^ (rel32_rva->op_size() == 4))) != 0; | 523 on_32bit = (~(on_32bit ^ (op_size == 4))) != 0; |
| 484 } else { | 524 } else { |
| 485 // Move 2 bytes at a time, but track 32-bit boundaries | 525 // Move 2 bytes at a time, but track 32-bit boundaries |
| 486 p += 2; | 526 p += 2; |
| 487 on_32bit = ((on_32bit + 1) % 2) != 0; | 527 on_32bit = ((on_32bit + 1) % 2) != 0; |
| 488 } | 528 } |
| 489 } | 529 } |
| 490 | 530 |
| 491 return true; | 531 return true; |
| 492 } | 532 } |
| 493 | 533 |
| 494 } // namespace courgette | 534 } // namespace courgette |
| OLD | NEW |