1 //===-- ArmUnwindInfo.cpp ---------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include <vector> 11 12 #include "lldb/Core/Module.h" 13 #include "lldb/Core/Section.h" 14 #include "lldb/Host/Endian.h" 15 #include "lldb/Symbol/ArmUnwindInfo.h" 16 #include "lldb/Symbol/SymbolVendor.h" 17 #include "lldb/Symbol/UnwindPlan.h" 18 #include "Utility/ARM_DWARF_Registers.h" 19 20 /* 21 * Unwind information reader and parser for the ARM exception handling ABI 22 * 23 * Implemented based on: 24 * Exception Handling ABI for the ARM Architecture 25 * Document number: ARM IHI 0038A (current through ABI r2.09) 26 * Date of Issue: 25th January 2007, reissued 30th November 2012 27 * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0038a/IHI0038A_ehabi.pdf 28 */ 29 30 using namespace lldb; 31 using namespace lldb_private; 32 33 // Converts a prel31 avlue to lldb::addr_t with sign extension 34 static addr_t 35 Prel31ToAddr(uint32_t prel31) 36 { 37 addr_t res = prel31; 38 if (prel31 & (1<<30)) 39 res |= 0xffffffff80000000ULL; 40 return res; 41 } 42 43 ArmUnwindInfo::ArmExidxEntry::ArmExidxEntry(uint32_t f, lldb::addr_t a, uint32_t d) : 44 file_address(f), address(a), data(d) 45 { 46 } 47 48 bool 49 ArmUnwindInfo::ArmExidxEntry::operator<(const ArmExidxEntry& other) const 50 { 51 return address < other.address; 52 } 53 54 ArmUnwindInfo::ArmUnwindInfo(const ObjectFile& objfile, 55 SectionSP& arm_exidx, 56 SectionSP& arm_extab) : 57 m_byte_order(objfile.GetByteOrder()), 58 m_arm_exidx_sp(arm_exidx), 59 m_arm_extab_sp(arm_extab) 60 { 61 objfile.ReadSectionData(arm_exidx.get(), m_arm_exidx_data); 62 objfile.ReadSectionData(arm_extab.get(), m_arm_extab_data); 63 64 addr_t exidx_base_addr = m_arm_exidx_sp->GetFileAddress(); 65 66 offset_t offset = 0; 67 while (m_arm_exidx_data.ValidOffset(offset)) 68 { 69 lldb::addr_t file_addr = exidx_base_addr + offset; 70 lldb::addr_t addr = exidx_base_addr + 71 (addr_t)offset + 72 Prel31ToAddr(m_arm_exidx_data.GetU32(&offset)); 73 uint32_t data = m_arm_exidx_data.GetU32(&offset); 74 m_exidx_entries.emplace_back(file_addr, addr, data); 75 } 76 77 // Sort the entries in the exidx section. The entries should be sorted inside the section but 78 // some old compiler isn't sorted them. 79 std::sort(m_exidx_entries.begin(), m_exidx_entries.end()); 80 } 81 82 ArmUnwindInfo::~ArmUnwindInfo() 83 { 84 } 85 86 // Read a byte from the unwind instruction stream with the given offset. 87 // Custom function is required because have to red in order of significance within their containing 88 // word (most significant byte first) and in increasing word address order. 89 uint8_t 90 ArmUnwindInfo::GetByteAtOffset(const uint32_t* data, uint16_t offset) const 91 { 92 uint32_t value = data[offset / 4]; 93 if (m_byte_order != endian::InlHostByteOrder()) 94 value = llvm::ByteSwap_32(value); 95 return (value >> ((3 - (offset % 4)) * 8)) & 0xff; 96 } 97 98 uint64_t 99 ArmUnwindInfo::GetULEB128(const uint32_t* data, uint16_t& offset, uint16_t max_offset) const 100 { 101 uint64_t result = 0; 102 uint8_t shift = 0; 103 while (offset < max_offset) 104 { 105 uint8_t byte = GetByteAtOffset(data, offset++); 106 result |= (byte & 0x7f) << shift; 107 if ((byte & 0x80) == 0) 108 break; 109 shift += 7; 110 } 111 return result; 112 } 113 114 bool 115 ArmUnwindInfo::GetUnwindPlan(Target &target, const Address& addr, UnwindPlan& unwind_plan) 116 { 117 const uint32_t* data = (const uint32_t*)GetExceptionHandlingTableEntry(addr); 118 if (data == nullptr) 119 return false; // No unwind information for the function 120 121 if (data[0] == 0x1) 122 return false; // EXIDX_CANTUNWIND 123 124 uint16_t byte_count = 0; 125 uint16_t byte_offset = 0; 126 if (data[0] & 0x80000000) 127 { 128 switch ((data[0] >> 24) & 0x0f) 129 { 130 case 0: 131 byte_count = 4; 132 byte_offset = 1; 133 break; 134 case 1: 135 case 2: 136 byte_count = 4 * ((data[0] >> 16) & 0xff) + 4; 137 byte_offset = 2; 138 break; 139 default: 140 // Unhandled personality routine index 141 return false; 142 } 143 } 144 else 145 { 146 byte_count = 4 * ((data[1] >> 24) & 0xff) + 8; 147 byte_offset = 5; 148 } 149 150 uint8_t vsp_reg = dwarf_sp; 151 int32_t vsp = 0; 152 std::vector<std::pair<uint32_t, int32_t>> register_offsets; // register -> (offset from vsp_reg) 153 154 while (byte_offset < byte_count) 155 { 156 uint8_t byte1 = GetByteAtOffset(data, byte_offset++); 157 if ((byte1&0xc0) == 0x00) 158 { 159 // 00xxxxxx 160 // vsp = vsp + (xxxxxx << 2) + 4. Covers range 0x04-0x100 inclusive 161 vsp += ((byte1 & 0x3f) << 2) + 4; 162 } 163 else if ((byte1&0xc0) == 0x40) 164 { 165 // 01xxxxxx 166 // vsp = vsp – (xxxxxx << 2) - 4. Covers range 0x04-0x100 inclusive 167 vsp -= ((byte1 & 0x3f) << 2) + 4; 168 } 169 else if ((byte1&0xf0) == 0x80) 170 { 171 if (byte_offset >= byte_count) 172 return false; 173 174 uint8_t byte2 = GetByteAtOffset(data, byte_offset++); 175 if (byte1 == 0x80 && byte2 == 0) 176 { 177 // 10000000 00000000 178 // Refuse to unwind (for example, out of a cleanup) (see remark a) 179 return false; 180 } 181 else 182 { 183 // 1000iiii iiiiiiii (i not all 0) 184 // Pop up to 12 integer registers under masks {r15-r12}, {r11-r4} (see remark b) 185 uint16_t regs = ((byte1&0x0f) << 8) | byte2; 186 for (uint8_t i = 0; i < 12; ++i) 187 { 188 if (regs & (1<<i)) 189 { 190 register_offsets.emplace_back(dwarf_r4 + i, vsp); 191 vsp += 4; 192 } 193 } 194 } 195 } 196 else if ((byte1&0xff) == 0x9d) 197 { 198 // 10011101 199 // Reserved as prefix for ARM register to register moves 200 return false; 201 } 202 else if ((byte1&0xff) == 0x9f) 203 { 204 // 10011111 205 // Reserved as prefix for Intel Wireless MMX register to register moves 206 return false; 207 } 208 else if ((byte1&0xf0) == 0x90) 209 { 210 // 1001nnnn (nnnn != 13,15) 211 // Set vsp = r[nnnn] 212 vsp_reg = dwarf_r0 + (byte1&0x0f); 213 } 214 else if ((byte1&0xf8) == 0xa0) 215 { 216 // 10100nnn 217 // Pop r4-r[4+nnn] 218 uint8_t n = byte1&0x7; 219 for (uint8_t i = 0; i <= n; ++i) 220 { 221 register_offsets.emplace_back(dwarf_r4 + i, vsp); 222 vsp += 4; 223 } 224 } 225 else if ((byte1&0xf8) == 0xa8) 226 { 227 // 10101nnn 228 // Pop r4-r[4+nnn], r14 229 uint8_t n = byte1&0x7; 230 for (uint8_t i = 0; i <= n; ++i) 231 { 232 register_offsets.emplace_back(dwarf_r4 + i, vsp); 233 vsp += 4; 234 } 235 236 register_offsets.emplace_back(dwarf_lr, vsp); 237 vsp += 4; 238 } 239 else if ((byte1&0xff) == 0xb0) 240 { 241 // 10110000 242 // Finish (see remark c) 243 break; 244 } 245 else if ((byte1&0xff) == 0xb1) 246 { 247 if (byte_offset >= byte_count) 248 return false; 249 250 uint8_t byte2 = GetByteAtOffset(data, byte_offset++); 251 if ((byte2&0xff) == 0x00) 252 { 253 // 10110001 00000000 254 // Spare (see remark f) 255 return false; 256 } 257 else if ((byte2&0xf0) == 0x00) 258 { 259 // 10110001 0000iiii (i not all 0) 260 // Pop integer registers under mask {r3, r2, r1, r0} 261 for (uint8_t i = 0; i < 4; ++i) 262 { 263 if (byte2 & (1<<i)) 264 { 265 register_offsets.emplace_back(dwarf_r0 + i, vsp); 266 vsp += 4; 267 } 268 } 269 } 270 else 271 { 272 // 10110001 xxxxyyyy 273 // Spare (xxxx != 0000) 274 return false; 275 } 276 } 277 else if ((byte1&0xff) == 0xb2) 278 { 279 // 10110010 uleb128 280 // vsp = vsp + 0x204+ (uleb128 << 2) 281 uint64_t uleb128 = GetULEB128(data, byte_offset, byte_count); 282 vsp += 0x204 + (uleb128 << 2); 283 } 284 else if ((byte1&0xff) == 0xb3) 285 { 286 // 10110011 sssscccc 287 // Pop VFP double-precision registers D[ssss]-D[ssss+cccc] saved (as if) by FSTMFDX (see remark d) 288 if (byte_offset >= byte_count) 289 return false; 290 291 uint8_t byte2 = GetByteAtOffset(data, byte_offset++); 292 uint8_t s = (byte2&0xf0) >> 4; 293 uint8_t c = (byte2&0x0f) >> 0; 294 for (uint8_t i = 0; i <= c; ++i) 295 { 296 register_offsets.emplace_back(dwarf_d0 + s + i, vsp); 297 vsp += 8; 298 } 299 vsp += 4; 300 } 301 else if ((byte1&0xfc) == 0xb4) 302 { 303 // 101101nn 304 // Spare (was Pop FPA) 305 return false; 306 } 307 else if ((byte1&0xf8) == 0xb8) 308 { 309 // 10111nnn 310 // Pop VFP double-precision registers D[8]-D[8+nnn] saved (as if) by FSTMFDX (see remark d) 311 uint8_t n = byte1&0x07; 312 for (uint8_t i = 0; i <= n; ++i) 313 { 314 register_offsets.emplace_back(dwarf_d8 + i, vsp); 315 vsp += 8; 316 } 317 vsp += 4; 318 } 319 else if ((byte1&0xf8) == 0xc0) 320 { 321 // 11000nnn (nnn != 6,7) 322 // Intel Wireless MMX pop wR[10]-wR[10+nnn] 323 324 // 11000110 sssscccc 325 // Intel Wireless MMX pop wR[ssss]-wR[ssss+cccc] (see remark e) 326 327 // 11000111 00000000 328 // Spare 329 330 // 11000111 0000iiii 331 // Intel Wireless MMX pop wCGR registers under mask {wCGR3,2,1,0} 332 333 // 11000111 xxxxyyyy 334 // Spare (xxxx != 0000) 335 336 return false; 337 } 338 else if ((byte1&0xff) == 0xc8) 339 { 340 // 11001000 sssscccc 341 // Pop VFP double precision registers D[16+ssss]-D[16+ssss+cccc] saved (as if) by FSTMFDD (see remarks d,e) 342 if (byte_offset >= byte_count) 343 return false; 344 345 uint8_t byte2 = GetByteAtOffset(data, byte_offset++); 346 uint8_t s = (byte2&0xf0) >> 4; 347 uint8_t c = (byte2&0x0f) >> 0; 348 for (uint8_t i = 0; i <= c; ++i) 349 { 350 register_offsets.emplace_back(dwarf_d16 + s + i, vsp); 351 vsp += 8; 352 } 353 } 354 else if ((byte1&0xff) == 0xc9) 355 { 356 // 11001001 sssscccc 357 // Pop VFP double precision registers D[ssss]-D[ssss+cccc] saved (as if) by FSTMFDD (see remark d) 358 if (byte_offset >= byte_count) 359 return false; 360 361 uint8_t byte2 = GetByteAtOffset(data, byte_offset++); 362 uint8_t s = (byte2&0xf0) >> 4; 363 uint8_t c = (byte2&0x0f) >> 0; 364 for (uint8_t i = 0; i <= c; ++i) 365 { 366 register_offsets.emplace_back(dwarf_d0 + s + i, vsp); 367 vsp += 8; 368 } 369 } 370 else if ((byte1&0xf8) == 0xc8) 371 { 372 // 11001yyy 373 // Spare (yyy != 000, 001) 374 return false; 375 } 376 else if ((byte1&0xf8) == 0xc0) 377 { 378 // 11010nnn 379 // Pop VFP double-precision registers D[8]-D[8+nnn] saved (as if) by FSTMFDD (see remark d) 380 uint8_t n = byte1&0x07; 381 for (uint8_t i = 0; i <= n; ++i) 382 { 383 register_offsets.emplace_back(dwarf_d8 + i, vsp); 384 vsp += 8; 385 } 386 } 387 else if ((byte1&0xc0) == 0xc0) 388 { 389 // 11xxxyyy Spare (xxx != 000, 001, 010) 390 return false; 391 } 392 else 393 { 394 return false; 395 } 396 } 397 398 UnwindPlan::RowSP row = std::make_shared<UnwindPlan::Row>(); 399 row->SetOffset(0); 400 row->GetCFAValue().SetIsRegisterPlusOffset(vsp_reg, vsp); 401 402 bool have_location_for_pc = false; 403 for (const auto& offset : register_offsets) 404 { 405 have_location_for_pc |= offset.first == dwarf_pc; 406 row->SetRegisterLocationToAtCFAPlusOffset(offset.first, offset.second - vsp, true); 407 } 408 409 if (!have_location_for_pc) 410 { 411 UnwindPlan::Row::RegisterLocation lr_location; 412 if (row->GetRegisterInfo(dwarf_lr, lr_location)) 413 row->SetRegisterInfo(dwarf_pc, lr_location); 414 else 415 row->SetRegisterLocationToRegister(dwarf_pc, dwarf_lr, false); 416 } 417 418 unwind_plan.AppendRow(row); 419 unwind_plan.SetSourceName ("ARM.exidx unwind info"); 420 unwind_plan.SetSourcedFromCompiler (eLazyBoolYes); 421 unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo); 422 unwind_plan.SetRegisterKind (eRegisterKindDWARF); 423 424 return true; 425 } 426 427 const uint8_t* 428 ArmUnwindInfo::GetExceptionHandlingTableEntry(const Address& addr) 429 { 430 auto it = std::upper_bound(m_exidx_entries.begin(), 431 m_exidx_entries.end(), 432 ArmExidxEntry{0, addr.GetFileAddress(), 0}); 433 if (it == m_exidx_entries.begin()) 434 return nullptr; 435 --it; 436 437 if (it->data == 0x1) 438 return nullptr; // EXIDX_CANTUNWIND 439 440 if (it->data & 0x80000000) 441 return (const uint8_t*)&it->data; 442 443 addr_t data_file_addr = it->file_address + 4 + Prel31ToAddr(it->data); 444 return m_arm_extab_data.GetDataStart() + (data_file_addr - m_arm_extab_sp->GetFileAddress()); 445 } 446