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