1 //===-- NativeRegisterContextNetBSD_x86_64.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 #if defined(__x86_64__) 11 12 #include "NativeRegisterContextNetBSD_x86_64.h" 13 14 #include "lldb/Core/RegisterValue.h" 15 #include "lldb/Host/HostInfo.h" 16 #include "lldb/Utility/DataBufferHeap.h" 17 #include "lldb/Utility/Error.h" 18 #include "lldb/Utility/Log.h" 19 20 #include "Plugins/Process/Utility/RegisterContextNetBSD_x86_64.h" 21 22 #include <elf.h> 23 24 using namespace lldb_private; 25 using namespace lldb_private::process_netbsd; 26 27 // ---------------------------------------------------------------------------- 28 // Private namespace. 29 // ---------------------------------------------------------------------------- 30 31 namespace { 32 // x86 64-bit general purpose registers. 33 static const uint32_t g_gpr_regnums_x86_64[] = { 34 lldb_rax_x86_64, lldb_rbx_x86_64, lldb_rcx_x86_64, lldb_rdx_x86_64, 35 lldb_rdi_x86_64, lldb_rsi_x86_64, lldb_rbp_x86_64, lldb_rsp_x86_64, 36 lldb_r8_x86_64, lldb_r9_x86_64, lldb_r10_x86_64, lldb_r11_x86_64, 37 lldb_r12_x86_64, lldb_r13_x86_64, lldb_r14_x86_64, lldb_r15_x86_64, 38 lldb_rip_x86_64, lldb_rflags_x86_64, lldb_cs_x86_64, lldb_fs_x86_64, 39 lldb_gs_x86_64, lldb_ss_x86_64, lldb_ds_x86_64, lldb_es_x86_64, 40 lldb_eax_x86_64, lldb_ebx_x86_64, lldb_ecx_x86_64, lldb_edx_x86_64, 41 lldb_edi_x86_64, lldb_esi_x86_64, lldb_ebp_x86_64, lldb_esp_x86_64, 42 lldb_r8d_x86_64, // Low 32 bits or r8 43 lldb_r9d_x86_64, // Low 32 bits or r9 44 lldb_r10d_x86_64, // Low 32 bits or r10 45 lldb_r11d_x86_64, // Low 32 bits or r11 46 lldb_r12d_x86_64, // Low 32 bits or r12 47 lldb_r13d_x86_64, // Low 32 bits or r13 48 lldb_r14d_x86_64, // Low 32 bits or r14 49 lldb_r15d_x86_64, // Low 32 bits or r15 50 lldb_ax_x86_64, lldb_bx_x86_64, lldb_cx_x86_64, lldb_dx_x86_64, 51 lldb_di_x86_64, lldb_si_x86_64, lldb_bp_x86_64, lldb_sp_x86_64, 52 lldb_r8w_x86_64, // Low 16 bits or r8 53 lldb_r9w_x86_64, // Low 16 bits or r9 54 lldb_r10w_x86_64, // Low 16 bits or r10 55 lldb_r11w_x86_64, // Low 16 bits or r11 56 lldb_r12w_x86_64, // Low 16 bits or r12 57 lldb_r13w_x86_64, // Low 16 bits or r13 58 lldb_r14w_x86_64, // Low 16 bits or r14 59 lldb_r15w_x86_64, // Low 16 bits or r15 60 lldb_ah_x86_64, lldb_bh_x86_64, lldb_ch_x86_64, lldb_dh_x86_64, 61 lldb_al_x86_64, lldb_bl_x86_64, lldb_cl_x86_64, lldb_dl_x86_64, 62 lldb_dil_x86_64, lldb_sil_x86_64, lldb_bpl_x86_64, lldb_spl_x86_64, 63 lldb_r8l_x86_64, // Low 8 bits or r8 64 lldb_r9l_x86_64, // Low 8 bits or r9 65 lldb_r10l_x86_64, // Low 8 bits or r10 66 lldb_r11l_x86_64, // Low 8 bits or r11 67 lldb_r12l_x86_64, // Low 8 bits or r12 68 lldb_r13l_x86_64, // Low 8 bits or r13 69 lldb_r14l_x86_64, // Low 8 bits or r14 70 lldb_r15l_x86_64, // Low 8 bits or r15 71 LLDB_INVALID_REGNUM // register sets need to end with this flag 72 }; 73 static_assert((sizeof(g_gpr_regnums_x86_64) / sizeof(g_gpr_regnums_x86_64[0])) - 74 1 == 75 k_num_gpr_registers_x86_64, 76 "g_gpr_regnums_x86_64 has wrong number of register infos"); 77 78 // Number of register sets provided by this context. 79 enum { k_num_extended_register_sets = 2, k_num_register_sets = 4 }; 80 81 // Register sets for x86 64-bit. 82 static const RegisterSet g_reg_sets_x86_64[k_num_register_sets] = { 83 {"General Purpose Registers", "gpr", k_num_gpr_registers_x86_64, 84 g_gpr_regnums_x86_64}, 85 }; 86 87 #define REG_CONTEXT_SIZE (GetRegisterInfoInterface().GetGPRSize()) 88 89 } // namespace 90 91 NativeRegisterContextNetBSD * 92 NativeRegisterContextNetBSD::CreateHostNativeRegisterContextNetBSD( 93 const ArchSpec &target_arch, NativeThreadProtocol &native_thread, 94 uint32_t concrete_frame_idx) { 95 return new NativeRegisterContextNetBSD_x86_64(target_arch, native_thread, 96 concrete_frame_idx); 97 } 98 99 // ---------------------------------------------------------------------------- 100 // NativeRegisterContextNetBSD_x86_64 members. 101 // ---------------------------------------------------------------------------- 102 103 static RegisterInfoInterface * 104 CreateRegisterInfoInterface(const ArchSpec &target_arch) { 105 assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) && 106 "Register setting path assumes this is a 64-bit host"); 107 // X86_64 hosts know how to work with 64-bit and 32-bit EXEs using the 108 // x86_64 register context. 109 return new RegisterContextNetBSD_x86_64(target_arch); 110 } 111 112 NativeRegisterContextNetBSD_x86_64::NativeRegisterContextNetBSD_x86_64( 113 const ArchSpec &target_arch, NativeThreadProtocol &native_thread, 114 uint32_t concrete_frame_idx) 115 : NativeRegisterContextNetBSD(native_thread, concrete_frame_idx, 116 CreateRegisterInfoInterface(target_arch)), 117 m_gpr_x86_64() {} 118 119 // CONSIDER after local and llgs debugging are merged, register set support can 120 // be moved into a base x86-64 class with IsRegisterSetAvailable made virtual. 121 uint32_t NativeRegisterContextNetBSD_x86_64::GetRegisterSetCount() const { 122 uint32_t sets = 0; 123 for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) { 124 if (GetSetForNativeRegNum(set_index) != -1) 125 ++sets; 126 } 127 128 return sets; 129 } 130 131 const RegisterSet * 132 NativeRegisterContextNetBSD_x86_64::GetRegisterSet(uint32_t set_index) const { 133 switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) { 134 case llvm::Triple::x86_64: 135 return &g_reg_sets_x86_64[set_index]; 136 default: 137 assert(false && "Unhandled target architecture."); 138 return nullptr; 139 } 140 141 return nullptr; 142 } 143 144 int NativeRegisterContextNetBSD_x86_64::GetSetForNativeRegNum( 145 int reg_num) const { 146 if (reg_num < lldb_fctrl_x86_64) 147 return GPRegSet; 148 else 149 return -1; 150 } 151 152 int NativeRegisterContextNetBSD_x86_64::ReadRegisterSet(uint32_t set) { 153 switch (set) { 154 case GPRegSet: 155 ReadGPR(); 156 return 0; 157 case FPRegSet: 158 ReadFPR(); 159 return 0; 160 default: 161 break; 162 } 163 return -1; 164 } 165 int NativeRegisterContextNetBSD_x86_64::WriteRegisterSet(uint32_t set) { 166 switch (set) { 167 case GPRegSet: 168 WriteGPR(); 169 return 0; 170 case FPRegSet: 171 WriteFPR(); 172 return 0; 173 default: 174 break; 175 } 176 return -1; 177 } 178 179 Error NativeRegisterContextNetBSD_x86_64::ReadRegister( 180 const RegisterInfo *reg_info, RegisterValue ®_value) { 181 Error error; 182 183 if (!reg_info) { 184 error.SetErrorString("reg_info NULL"); 185 return error; 186 } 187 188 const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; 189 if (reg == LLDB_INVALID_REGNUM) { 190 // This is likely an internal register for lldb use only and should not be 191 // directly queried. 192 error.SetErrorStringWithFormat("register \"%s\" is an internal-only lldb " 193 "register, cannot read directly", 194 reg_info->name); 195 return error; 196 } 197 198 int set = GetSetForNativeRegNum(reg); 199 if (set == -1) { 200 // This is likely an internal register for lldb use only and should not be 201 // directly queried. 202 error.SetErrorStringWithFormat("register \"%s\" is in unrecognized set", 203 reg_info->name); 204 return error; 205 } 206 207 if (ReadRegisterSet(set) != 0) { 208 // This is likely an internal register for lldb use only and should not be 209 // directly queried. 210 error.SetErrorStringWithFormat( 211 "reading register set for register \"%s\" failed", reg_info->name); 212 return error; 213 } 214 215 switch (reg) { 216 case lldb_rax_x86_64: 217 reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_RAX]; 218 break; 219 case lldb_rbx_x86_64: 220 reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_RBX]; 221 break; 222 case lldb_rcx_x86_64: 223 reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_RCX]; 224 break; 225 case lldb_rdx_x86_64: 226 reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_RDX]; 227 break; 228 case lldb_rdi_x86_64: 229 reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_RDI]; 230 break; 231 case lldb_rsi_x86_64: 232 reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_RSI]; 233 break; 234 case lldb_rbp_x86_64: 235 reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_RBP]; 236 break; 237 case lldb_rsp_x86_64: 238 reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_RSP]; 239 break; 240 case lldb_r8_x86_64: 241 reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_R8]; 242 break; 243 case lldb_r9_x86_64: 244 reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_R9]; 245 break; 246 case lldb_r10_x86_64: 247 reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_R10]; 248 break; 249 case lldb_r11_x86_64: 250 reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_R11]; 251 break; 252 case lldb_r12_x86_64: 253 reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_R12]; 254 break; 255 case lldb_r13_x86_64: 256 reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_R13]; 257 break; 258 case lldb_r14_x86_64: 259 reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_R14]; 260 break; 261 case lldb_r15_x86_64: 262 reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_R15]; 263 break; 264 case lldb_rip_x86_64: 265 reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_RIP]; 266 break; 267 case lldb_rflags_x86_64: 268 reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_RFLAGS]; 269 break; 270 case lldb_cs_x86_64: 271 reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_CS]; 272 break; 273 case lldb_fs_x86_64: 274 reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_FS]; 275 break; 276 case lldb_gs_x86_64: 277 reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_GS]; 278 break; 279 case lldb_ss_x86_64: 280 reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_SS]; 281 break; 282 case lldb_ds_x86_64: 283 reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_DS]; 284 break; 285 case lldb_es_x86_64: 286 reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_ES]; 287 break; 288 } 289 290 return error; 291 } 292 293 Error NativeRegisterContextNetBSD_x86_64::WriteRegister( 294 const RegisterInfo *reg_info, const RegisterValue ®_value) { 295 296 Error error; 297 298 if (!reg_info) { 299 error.SetErrorString("reg_info NULL"); 300 return error; 301 } 302 303 const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; 304 if (reg == LLDB_INVALID_REGNUM) { 305 // This is likely an internal register for lldb use only and should not be 306 // directly queried. 307 error.SetErrorStringWithFormat("register \"%s\" is an internal-only lldb " 308 "register, cannot read directly", 309 reg_info->name); 310 return error; 311 } 312 313 int set = GetSetForNativeRegNum(reg); 314 if (set == -1) { 315 // This is likely an internal register for lldb use only and should not be 316 // directly queried. 317 error.SetErrorStringWithFormat("register \"%s\" is in unrecognized set", 318 reg_info->name); 319 return error; 320 } 321 322 if (ReadRegisterSet(set) != 0) { 323 // This is likely an internal register for lldb use only and should not be 324 // directly queried. 325 error.SetErrorStringWithFormat( 326 "reading register set for register \"%s\" failed", reg_info->name); 327 return error; 328 } 329 330 switch (reg) { 331 case lldb_rax_x86_64: 332 m_gpr_x86_64.regs[_REG_RAX] = reg_value.GetAsUInt64(); 333 break; 334 case lldb_rbx_x86_64: 335 m_gpr_x86_64.regs[_REG_RBX] = reg_value.GetAsUInt64(); 336 break; 337 case lldb_rcx_x86_64: 338 m_gpr_x86_64.regs[_REG_RCX] = reg_value.GetAsUInt64(); 339 break; 340 case lldb_rdx_x86_64: 341 m_gpr_x86_64.regs[_REG_RDX] = reg_value.GetAsUInt64(); 342 break; 343 case lldb_rdi_x86_64: 344 m_gpr_x86_64.regs[_REG_RDI] = reg_value.GetAsUInt64(); 345 break; 346 case lldb_rsi_x86_64: 347 m_gpr_x86_64.regs[_REG_RSI] = reg_value.GetAsUInt64(); 348 break; 349 case lldb_rbp_x86_64: 350 m_gpr_x86_64.regs[_REG_RBP] = reg_value.GetAsUInt64(); 351 break; 352 case lldb_rsp_x86_64: 353 m_gpr_x86_64.regs[_REG_RSP] = reg_value.GetAsUInt64(); 354 break; 355 case lldb_r8_x86_64: 356 m_gpr_x86_64.regs[_REG_R8] = reg_value.GetAsUInt64(); 357 break; 358 case lldb_r9_x86_64: 359 m_gpr_x86_64.regs[_REG_R9] = reg_value.GetAsUInt64(); 360 break; 361 case lldb_r10_x86_64: 362 m_gpr_x86_64.regs[_REG_R10] = reg_value.GetAsUInt64(); 363 break; 364 case lldb_r11_x86_64: 365 m_gpr_x86_64.regs[_REG_R11] = reg_value.GetAsUInt64(); 366 break; 367 case lldb_r12_x86_64: 368 m_gpr_x86_64.regs[_REG_R12] = reg_value.GetAsUInt64(); 369 break; 370 case lldb_r13_x86_64: 371 m_gpr_x86_64.regs[_REG_R13] = reg_value.GetAsUInt64(); 372 break; 373 case lldb_r14_x86_64: 374 m_gpr_x86_64.regs[_REG_R14] = reg_value.GetAsUInt64(); 375 break; 376 case lldb_r15_x86_64: 377 m_gpr_x86_64.regs[_REG_R15] = reg_value.GetAsUInt64(); 378 break; 379 case lldb_rip_x86_64: 380 m_gpr_x86_64.regs[_REG_RIP] = reg_value.GetAsUInt64(); 381 break; 382 case lldb_rflags_x86_64: 383 m_gpr_x86_64.regs[_REG_RFLAGS] = reg_value.GetAsUInt64(); 384 break; 385 case lldb_cs_x86_64: 386 m_gpr_x86_64.regs[_REG_CS] = reg_value.GetAsUInt64(); 387 break; 388 case lldb_fs_x86_64: 389 m_gpr_x86_64.regs[_REG_FS] = reg_value.GetAsUInt64(); 390 break; 391 case lldb_gs_x86_64: 392 m_gpr_x86_64.regs[_REG_GS] = reg_value.GetAsUInt64(); 393 break; 394 case lldb_ss_x86_64: 395 m_gpr_x86_64.regs[_REG_SS] = reg_value.GetAsUInt64(); 396 break; 397 case lldb_ds_x86_64: 398 m_gpr_x86_64.regs[_REG_DS] = reg_value.GetAsUInt64(); 399 break; 400 case lldb_es_x86_64: 401 m_gpr_x86_64.regs[_REG_ES] = reg_value.GetAsUInt64(); 402 break; 403 } 404 405 if (WriteRegisterSet(set) != 0) 406 error.SetErrorStringWithFormat("failed to write register set"); 407 408 return error; 409 } 410 411 Error NativeRegisterContextNetBSD_x86_64::ReadAllRegisterValues( 412 lldb::DataBufferSP &data_sp) { 413 Error error; 414 415 data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0)); 416 if (!data_sp) { 417 error.SetErrorStringWithFormat( 418 "failed to allocate DataBufferHeap instance of size %" PRIu64, 419 REG_CONTEXT_SIZE); 420 return error; 421 } 422 423 error = ReadGPR(); 424 if (error.Fail()) 425 return error; 426 427 uint8_t *dst = data_sp->GetBytes(); 428 if (dst == nullptr) { 429 error.SetErrorStringWithFormat("DataBufferHeap instance of size %" PRIu64 430 " returned a null pointer", 431 REG_CONTEXT_SIZE); 432 return error; 433 } 434 435 ::memcpy(dst, &m_gpr_x86_64, GetRegisterInfoInterface().GetGPRSize()); 436 dst += GetRegisterInfoInterface().GetGPRSize(); 437 438 RegisterValue value((uint64_t)-1); 439 const RegisterInfo *reg_info = 440 GetRegisterInfoInterface().GetDynamicRegisterInfo("orig_eax"); 441 if (reg_info == nullptr) 442 reg_info = GetRegisterInfoInterface().GetDynamicRegisterInfo("orig_rax"); 443 return error; 444 } 445 446 Error NativeRegisterContextNetBSD_x86_64::WriteAllRegisterValues( 447 const lldb::DataBufferSP &data_sp) { 448 Error error; 449 450 if (!data_sp) { 451 error.SetErrorStringWithFormat( 452 "NativeRegisterContextNetBSD_x86_64::%s invalid data_sp provided", 453 __FUNCTION__); 454 return error; 455 } 456 457 if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) { 458 error.SetErrorStringWithFormat( 459 "NativeRegisterContextNetBSD_x86_64::%s data_sp contained mismatched " 460 "data size, expected %" PRIu64 ", actual %" PRIu64, 461 __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize()); 462 return error; 463 } 464 465 uint8_t *src = data_sp->GetBytes(); 466 if (src == nullptr) { 467 error.SetErrorStringWithFormat("NativeRegisterContextNetBSD_x86_64::%s " 468 "DataBuffer::GetBytes() returned a null " 469 "pointer", 470 __FUNCTION__); 471 return error; 472 } 473 ::memcpy(&m_gpr_x86_64, src, GetRegisterInfoInterface().GetGPRSize()); 474 475 error = WriteGPR(); 476 if (error.Fail()) 477 return error; 478 src += GetRegisterInfoInterface().GetGPRSize(); 479 480 return error; 481 } 482 483 #endif // defined(__x86_64__) 484