1 /* Copyright (C) 2007-2024 Free Software Foundation, Inc. 2 3 This file is part of GDB. 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 3 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 17 18 #include "win32-low.h" 19 #include "x86-low.h" 20 #include "gdbsupport/x86-xstate.h" 21 #ifdef __x86_64__ 22 #include "arch/amd64.h" 23 #endif 24 #include "arch/i386.h" 25 #include "tdesc.h" 26 #include "x86-tdesc.h" 27 28 using namespace windows_nat; 29 30 #ifndef CONTEXT_EXTENDED_REGISTERS 31 #define CONTEXT_EXTENDED_REGISTERS 0 32 #endif 33 34 #define I386_FISEG_REGNUM 27 35 #define I386_FOP_REGNUM 31 36 37 #define I386_CS_REGNUM 10 38 #define I386_GS_REGNUM 15 39 40 #define AMD64_FISEG_REGNUM 35 41 #define AMD64_FOP_REGNUM 39 42 43 #define AMD64_CS_REGNUM 18 44 #define AMD64_GS_REGNUM 23 45 46 #define FLAG_TRACE_BIT 0x100 47 48 static struct x86_debug_reg_state debug_reg_state; 49 50 static void 51 update_debug_registers (thread_info *thread) 52 { 53 windows_thread_info *th = (windows_thread_info *) thread_target_data (thread); 54 55 /* The actual update is done later just before resuming the lwp, 56 we just mark that the registers need updating. */ 57 th->debug_registers_changed = true; 58 } 59 60 /* Update the inferior's debug register REGNUM from STATE. */ 61 62 static void 63 x86_dr_low_set_addr (int regnum, CORE_ADDR addr) 64 { 65 gdb_assert (DR_FIRSTADDR <= regnum && regnum <= DR_LASTADDR); 66 67 /* Only update the threads of this process. */ 68 for_each_thread (current_thread->id.pid (), update_debug_registers); 69 } 70 71 /* Update the inferior's DR7 debug control register from STATE. */ 72 73 static void 74 x86_dr_low_set_control (unsigned long control) 75 { 76 /* Only update the threads of this process. */ 77 for_each_thread (current_thread->id.pid (), update_debug_registers); 78 } 79 80 /* Return the current value of a DR register of the current thread's 81 context. */ 82 83 static DWORD64 84 win32_get_current_dr (int dr) 85 { 86 windows_thread_info *th 87 = (windows_thread_info *) thread_target_data (current_thread); 88 89 win32_require_context (th); 90 91 #ifdef __x86_64__ 92 #define RET_DR(DR) \ 93 case DR: \ 94 return th->wow64_context.Dr ## DR 95 96 if (windows_process.wow64_process) 97 { 98 switch (dr) 99 { 100 RET_DR (0); 101 RET_DR (1); 102 RET_DR (2); 103 RET_DR (3); 104 RET_DR (6); 105 RET_DR (7); 106 } 107 } 108 else 109 #undef RET_DR 110 #endif 111 #define RET_DR(DR) \ 112 case DR: \ 113 return th->context.Dr ## DR 114 115 { 116 switch (dr) 117 { 118 RET_DR (0); 119 RET_DR (1); 120 RET_DR (2); 121 RET_DR (3); 122 RET_DR (6); 123 RET_DR (7); 124 } 125 } 126 127 #undef RET_DR 128 129 gdb_assert_not_reached ("unhandled dr"); 130 } 131 132 static CORE_ADDR 133 x86_dr_low_get_addr (int regnum) 134 { 135 gdb_assert (DR_FIRSTADDR <= regnum && regnum <= DR_LASTADDR); 136 137 return win32_get_current_dr (regnum - DR_FIRSTADDR); 138 } 139 140 static unsigned long 141 x86_dr_low_get_control (void) 142 { 143 return win32_get_current_dr (7); 144 } 145 146 /* Get the value of the DR6 debug status register from the inferior 147 and record it in STATE. */ 148 149 static unsigned long 150 x86_dr_low_get_status (void) 151 { 152 return win32_get_current_dr (6); 153 } 154 155 /* Low-level function vector. */ 156 struct x86_dr_low_type x86_dr_low = 157 { 158 x86_dr_low_set_control, 159 x86_dr_low_set_addr, 160 x86_dr_low_get_addr, 161 x86_dr_low_get_status, 162 x86_dr_low_get_control, 163 sizeof (void *), 164 }; 165 166 /* Breakpoint/watchpoint support. */ 167 168 static int 169 i386_supports_z_point_type (char z_type) 170 { 171 switch (z_type) 172 { 173 case Z_PACKET_HW_BP: 174 case Z_PACKET_WRITE_WP: 175 case Z_PACKET_ACCESS_WP: 176 return 1; 177 default: 178 return 0; 179 } 180 } 181 182 static int 183 i386_insert_point (enum raw_bkpt_type type, CORE_ADDR addr, 184 int size, struct raw_breakpoint *bp) 185 { 186 switch (type) 187 { 188 case raw_bkpt_type_hw: 189 case raw_bkpt_type_write_wp: 190 case raw_bkpt_type_access_wp: 191 { 192 enum target_hw_bp_type hw_type 193 = raw_bkpt_type_to_target_hw_bp_type (type); 194 195 return x86_dr_insert_watchpoint (&debug_reg_state, 196 hw_type, addr, size); 197 } 198 default: 199 /* Unsupported. */ 200 return 1; 201 } 202 } 203 204 static int 205 i386_remove_point (enum raw_bkpt_type type, CORE_ADDR addr, 206 int size, struct raw_breakpoint *bp) 207 { 208 switch (type) 209 { 210 case raw_bkpt_type_hw: 211 case raw_bkpt_type_write_wp: 212 case raw_bkpt_type_access_wp: 213 { 214 enum target_hw_bp_type hw_type 215 = raw_bkpt_type_to_target_hw_bp_type (type); 216 217 return x86_dr_remove_watchpoint (&debug_reg_state, 218 hw_type, addr, size); 219 } 220 default: 221 /* Unsupported. */ 222 return 1; 223 } 224 } 225 226 static int 227 x86_stopped_by_watchpoint (void) 228 { 229 return x86_dr_stopped_by_watchpoint (&debug_reg_state); 230 } 231 232 static CORE_ADDR 233 x86_stopped_data_address (void) 234 { 235 CORE_ADDR addr; 236 if (x86_dr_stopped_data_address (&debug_reg_state, &addr)) 237 return addr; 238 return 0; 239 } 240 241 static void 242 i386_initial_stuff (void) 243 { 244 x86_low_init_dregs (&debug_reg_state); 245 } 246 247 static void 248 i386_get_thread_context (windows_thread_info *th) 249 { 250 /* Requesting the CONTEXT_EXTENDED_REGISTERS register set fails if 251 the system doesn't support extended registers. */ 252 static DWORD extended_registers = CONTEXT_EXTENDED_REGISTERS; 253 254 again: 255 #ifdef __x86_64__ 256 if (windows_process.wow64_process) 257 th->wow64_context.ContextFlags = (CONTEXT_FULL 258 | CONTEXT_FLOATING_POINT 259 | CONTEXT_DEBUG_REGISTERS 260 | extended_registers); 261 else 262 #endif 263 th->context.ContextFlags = (CONTEXT_FULL 264 | CONTEXT_FLOATING_POINT 265 | CONTEXT_DEBUG_REGISTERS 266 | extended_registers); 267 268 BOOL ret; 269 #ifdef __x86_64__ 270 if (windows_process.wow64_process) 271 ret = Wow64GetThreadContext (th->h, &th->wow64_context); 272 else 273 #endif 274 ret = GetThreadContext (th->h, &th->context); 275 if (!ret) 276 { 277 DWORD e = GetLastError (); 278 279 if (extended_registers && e == ERROR_INVALID_PARAMETER) 280 { 281 extended_registers = 0; 282 goto again; 283 } 284 285 error ("GetThreadContext failure %ld\n", (long) e); 286 } 287 } 288 289 static void 290 i386_prepare_to_resume (windows_thread_info *th) 291 { 292 if (th->debug_registers_changed) 293 { 294 struct x86_debug_reg_state *dr = &debug_reg_state; 295 296 win32_require_context (th); 297 298 #ifdef __x86_64__ 299 if (windows_process.wow64_process) 300 { 301 th->wow64_context.Dr0 = dr->dr_mirror[0]; 302 th->wow64_context.Dr1 = dr->dr_mirror[1]; 303 th->wow64_context.Dr2 = dr->dr_mirror[2]; 304 th->wow64_context.Dr3 = dr->dr_mirror[3]; 305 /* th->wow64_context.Dr6 = dr->dr_status_mirror; 306 FIXME: should we set dr6 also ?? */ 307 th->wow64_context.Dr7 = dr->dr_control_mirror; 308 } 309 else 310 #endif 311 { 312 th->context.Dr0 = dr->dr_mirror[0]; 313 th->context.Dr1 = dr->dr_mirror[1]; 314 th->context.Dr2 = dr->dr_mirror[2]; 315 th->context.Dr3 = dr->dr_mirror[3]; 316 /* th->context.Dr6 = dr->dr_status_mirror; 317 FIXME: should we set dr6 also ?? */ 318 th->context.Dr7 = dr->dr_control_mirror; 319 } 320 321 th->debug_registers_changed = false; 322 } 323 } 324 325 static void 326 i386_thread_added (windows_thread_info *th) 327 { 328 th->debug_registers_changed = true; 329 } 330 331 static void 332 i386_single_step (windows_thread_info *th) 333 { 334 #ifdef __x86_64__ 335 if (windows_process.wow64_process) 336 th->wow64_context.EFlags |= FLAG_TRACE_BIT; 337 else 338 #endif 339 th->context.EFlags |= FLAG_TRACE_BIT; 340 } 341 342 /* An array of offset mappings into a Win32 Context structure. 343 This is a one-to-one mapping which is indexed by gdb's register 344 numbers. It retrieves an offset into the context structure where 345 the 4 byte register is located. 346 An offset value of -1 indicates that Win32 does not provide this 347 register in it's CONTEXT structure. In this case regptr will return 348 a pointer into a dummy register. */ 349 #ifdef __x86_64__ 350 #define context_offset(x) (offsetof (WOW64_CONTEXT, x)) 351 #else 352 #define context_offset(x) ((int)&(((CONTEXT *)NULL)->x)) 353 #endif 354 static const int i386_mappings[] = { 355 context_offset (Eax), 356 context_offset (Ecx), 357 context_offset (Edx), 358 context_offset (Ebx), 359 context_offset (Esp), 360 context_offset (Ebp), 361 context_offset (Esi), 362 context_offset (Edi), 363 context_offset (Eip), 364 context_offset (EFlags), 365 context_offset (SegCs), 366 context_offset (SegSs), 367 context_offset (SegDs), 368 context_offset (SegEs), 369 context_offset (SegFs), 370 context_offset (SegGs), 371 context_offset (FloatSave.RegisterArea[0 * 10]), 372 context_offset (FloatSave.RegisterArea[1 * 10]), 373 context_offset (FloatSave.RegisterArea[2 * 10]), 374 context_offset (FloatSave.RegisterArea[3 * 10]), 375 context_offset (FloatSave.RegisterArea[4 * 10]), 376 context_offset (FloatSave.RegisterArea[5 * 10]), 377 context_offset (FloatSave.RegisterArea[6 * 10]), 378 context_offset (FloatSave.RegisterArea[7 * 10]), 379 context_offset (FloatSave.ControlWord), 380 context_offset (FloatSave.StatusWord), 381 context_offset (FloatSave.TagWord), 382 context_offset (FloatSave.ErrorSelector), 383 context_offset (FloatSave.ErrorOffset), 384 context_offset (FloatSave.DataSelector), 385 context_offset (FloatSave.DataOffset), 386 context_offset (FloatSave.ErrorSelector), 387 /* XMM0-7 */ 388 context_offset (ExtendedRegisters[10 * 16]), 389 context_offset (ExtendedRegisters[11 * 16]), 390 context_offset (ExtendedRegisters[12 * 16]), 391 context_offset (ExtendedRegisters[13 * 16]), 392 context_offset (ExtendedRegisters[14 * 16]), 393 context_offset (ExtendedRegisters[15 * 16]), 394 context_offset (ExtendedRegisters[16 * 16]), 395 context_offset (ExtendedRegisters[17 * 16]), 396 /* MXCSR */ 397 context_offset (ExtendedRegisters[24]) 398 }; 399 #undef context_offset 400 401 #ifdef __x86_64__ 402 403 #define context_offset(x) (offsetof (CONTEXT, x)) 404 static const int amd64_mappings[] = 405 { 406 context_offset (Rax), 407 context_offset (Rbx), 408 context_offset (Rcx), 409 context_offset (Rdx), 410 context_offset (Rsi), 411 context_offset (Rdi), 412 context_offset (Rbp), 413 context_offset (Rsp), 414 context_offset (R8), 415 context_offset (R9), 416 context_offset (R10), 417 context_offset (R11), 418 context_offset (R12), 419 context_offset (R13), 420 context_offset (R14), 421 context_offset (R15), 422 context_offset (Rip), 423 context_offset (EFlags), 424 context_offset (SegCs), 425 context_offset (SegSs), 426 context_offset (SegDs), 427 context_offset (SegEs), 428 context_offset (SegFs), 429 context_offset (SegGs), 430 context_offset (FloatSave.FloatRegisters[0]), 431 context_offset (FloatSave.FloatRegisters[1]), 432 context_offset (FloatSave.FloatRegisters[2]), 433 context_offset (FloatSave.FloatRegisters[3]), 434 context_offset (FloatSave.FloatRegisters[4]), 435 context_offset (FloatSave.FloatRegisters[5]), 436 context_offset (FloatSave.FloatRegisters[6]), 437 context_offset (FloatSave.FloatRegisters[7]), 438 context_offset (FloatSave.ControlWord), 439 context_offset (FloatSave.StatusWord), 440 context_offset (FloatSave.TagWord), 441 context_offset (FloatSave.ErrorSelector), 442 context_offset (FloatSave.ErrorOffset), 443 context_offset (FloatSave.DataSelector), 444 context_offset (FloatSave.DataOffset), 445 context_offset (FloatSave.ErrorSelector) 446 /* XMM0-7 */ , 447 context_offset (Xmm0), 448 context_offset (Xmm1), 449 context_offset (Xmm2), 450 context_offset (Xmm3), 451 context_offset (Xmm4), 452 context_offset (Xmm5), 453 context_offset (Xmm6), 454 context_offset (Xmm7), 455 context_offset (Xmm8), 456 context_offset (Xmm9), 457 context_offset (Xmm10), 458 context_offset (Xmm11), 459 context_offset (Xmm12), 460 context_offset (Xmm13), 461 context_offset (Xmm14), 462 context_offset (Xmm15), 463 /* MXCSR */ 464 context_offset (FloatSave.MxCsr) 465 }; 466 #undef context_offset 467 468 #endif /* __x86_64__ */ 469 470 /* Return true if R is the FISEG register. */ 471 static bool 472 is_fiseg_register (int r) 473 { 474 #ifdef __x86_64__ 475 if (!windows_process.wow64_process) 476 return r == AMD64_FISEG_REGNUM; 477 else 478 #endif 479 return r == I386_FISEG_REGNUM; 480 } 481 482 /* Return true if R is the FOP register. */ 483 static bool 484 is_fop_register (int r) 485 { 486 #ifdef __x86_64__ 487 if (!windows_process.wow64_process) 488 return r == AMD64_FOP_REGNUM; 489 else 490 #endif 491 return r == I386_FOP_REGNUM; 492 } 493 494 /* Return true if R is a segment register. */ 495 static bool 496 is_segment_register (int r) 497 { 498 #ifdef __x86_64__ 499 if (!windows_process.wow64_process) 500 return r >= AMD64_CS_REGNUM && r <= AMD64_GS_REGNUM; 501 else 502 #endif 503 return r >= I386_CS_REGNUM && r <= I386_GS_REGNUM; 504 } 505 506 /* Fetch register from gdbserver regcache data. */ 507 static void 508 i386_fetch_inferior_register (struct regcache *regcache, 509 windows_thread_info *th, int r) 510 { 511 const int *mappings; 512 #ifdef __x86_64__ 513 if (!windows_process.wow64_process) 514 mappings = amd64_mappings; 515 else 516 #endif 517 mappings = i386_mappings; 518 519 char *context_offset; 520 #ifdef __x86_64__ 521 if (windows_process.wow64_process) 522 context_offset = (char *) &th->wow64_context + mappings[r]; 523 else 524 #endif 525 context_offset = (char *) &th->context + mappings[r]; 526 527 /* GDB treats some registers as 32-bit, where they are in fact only 528 16 bits long. These cases must be handled specially to avoid 529 reading extraneous bits from the context. */ 530 if (is_fiseg_register (r) || is_segment_register (r)) 531 { 532 gdb_byte bytes[4] = {}; 533 memcpy (bytes, context_offset, 2); 534 supply_register (regcache, r, bytes); 535 } 536 else if (is_fop_register (r)) 537 { 538 long l = (*((long *) context_offset) >> 16) & ((1 << 11) - 1); 539 supply_register (regcache, r, (char *) &l); 540 } 541 else 542 supply_register (regcache, r, context_offset); 543 } 544 545 /* Store a new register value into the thread context of TH. */ 546 static void 547 i386_store_inferior_register (struct regcache *regcache, 548 windows_thread_info *th, int r) 549 { 550 const int *mappings; 551 #ifdef __x86_64__ 552 if (!windows_process.wow64_process) 553 mappings = amd64_mappings; 554 else 555 #endif 556 mappings = i386_mappings; 557 558 char *context_offset; 559 #ifdef __x86_64__ 560 if (windows_process.wow64_process) 561 context_offset = (char *) &th->wow64_context + mappings[r]; 562 else 563 #endif 564 context_offset = (char *) &th->context + mappings[r]; 565 566 /* GDB treats some registers as 32-bit, where they are in fact only 567 16 bits long. These cases must be handled specially to avoid 568 overwriting other registers in the context. */ 569 if (is_fiseg_register (r) || is_segment_register (r)) 570 { 571 gdb_byte bytes[4]; 572 collect_register (regcache, r, bytes); 573 memcpy (context_offset, bytes, 2); 574 } 575 else if (is_fop_register (r)) 576 { 577 gdb_byte bytes[4]; 578 collect_register (regcache, r, bytes); 579 /* The value of FOP occupies the top two bytes in the context, 580 so write the two low-order bytes from the cache into the 581 appropriate spot. */ 582 memcpy (context_offset + 2, bytes, 2); 583 } 584 else 585 collect_register (regcache, r, context_offset); 586 } 587 588 static const unsigned char i386_win32_breakpoint = 0xcc; 589 #define i386_win32_breakpoint_len 1 590 591 static void 592 i386_arch_setup (void) 593 { 594 struct target_desc *tdesc; 595 596 #ifdef __x86_64__ 597 tdesc = amd64_create_target_description (X86_XSTATE_SSE_MASK, false, 598 false, false); 599 init_target_desc (tdesc, amd64_expedite_regs); 600 win32_tdesc = tdesc; 601 #endif 602 603 tdesc = i386_create_target_description (X86_XSTATE_SSE_MASK, false, false); 604 init_target_desc (tdesc, i386_expedite_regs); 605 #ifdef __x86_64__ 606 wow64_win32_tdesc = tdesc; 607 #else 608 win32_tdesc = tdesc; 609 #endif 610 } 611 612 /* Implement win32_target_ops "num_regs" method. */ 613 614 static int 615 i386_win32_num_regs (void) 616 { 617 int num_regs; 618 #ifdef __x86_64__ 619 if (!windows_process.wow64_process) 620 num_regs = sizeof (amd64_mappings) / sizeof (amd64_mappings[0]); 621 else 622 #endif 623 num_regs = sizeof (i386_mappings) / sizeof (i386_mappings[0]); 624 return num_regs; 625 } 626 627 /* Implement win32_target_ops "get_pc" method. */ 628 629 static CORE_ADDR 630 i386_win32_get_pc (struct regcache *regcache) 631 { 632 bool use_64bit = register_size (regcache->tdesc, 0) == 8; 633 634 if (use_64bit) 635 { 636 uint64_t pc; 637 638 collect_register_by_name (regcache, "rip", &pc); 639 return (CORE_ADDR) pc; 640 } 641 else 642 { 643 uint32_t pc; 644 645 collect_register_by_name (regcache, "eip", &pc); 646 return (CORE_ADDR) pc; 647 } 648 } 649 650 /* Implement win32_target_ops "set_pc" method. */ 651 652 static void 653 i386_win32_set_pc (struct regcache *regcache, CORE_ADDR pc) 654 { 655 bool use_64bit = register_size (regcache->tdesc, 0) == 8; 656 657 if (use_64bit) 658 { 659 uint64_t newpc = pc; 660 661 supply_register_by_name (regcache, "rip", &newpc); 662 } 663 else 664 { 665 uint32_t newpc = pc; 666 667 supply_register_by_name (regcache, "eip", &newpc); 668 } 669 } 670 671 struct win32_target_ops the_low_target = { 672 i386_arch_setup, 673 i386_win32_num_regs, 674 i386_initial_stuff, 675 i386_get_thread_context, 676 i386_prepare_to_resume, 677 i386_thread_added, 678 i386_fetch_inferior_register, 679 i386_store_inferior_register, 680 i386_single_step, 681 &i386_win32_breakpoint, 682 i386_win32_breakpoint_len, 683 1, 684 i386_win32_get_pc, 685 i386_win32_set_pc, 686 i386_supports_z_point_type, 687 i386_insert_point, 688 i386_remove_point, 689 x86_stopped_by_watchpoint, 690 x86_stopped_data_address 691 }; 692