summaryrefslogtreecommitdiff
path: root/gdb/amd64-windows-tdep.c
diff options
context:
space:
mode:
authorJoel Brobecker <brobecker@adacore.com>2015-11-23 09:53:31 -0800
committerJoel Brobecker <brobecker@adacore.com>2015-11-23 09:53:31 -0800
commita6a20ad7a16346e2d630b312a94a4cbae60fca45 (patch)
tree3a8c4fff81d4c5ce67a1d25206375c081320901e /gdb/amd64-windows-tdep.c
parent416dc9c6e9acd57255015d255799ac031a262182 (diff)
infinite loop stopping at "pop" insn on x64-windows
We noticed the following hang trying to run a program where one of the subroutines we built without debugging info (opaque_routine): $ gdb my_program (gdb) break opaque_routine (gdb) run [...hangs...] The problem comes from the fact that, at the breakpoint's address, we have the following code: => 0x0000000000401994 <+4>: pop %rbp At some point after hitting the breakpoint and stopping, GDB calls amd64_windows_frame_decode_epilogue, which then gets stuck in the following infinite loop: | /* We don't care about the instruction deallocating the frame: | if it hasn't been executed, the pc is still in the body, | if it has been executed, the following epilog decoding will work. */ | | /* First decode: | - pop reg [41 58-5f] or [58-5f]. */ | | while (1) | { | /* Read opcode. */ | if (target_read_memory (pc, &op, 1) != 0) | return -1; | | if (op >= 0x40 && op <= 0x4f) | { | /* REX prefix. */ | rex = op; | | /* Read opcode. */ | if (target_read_memory (pc + 1, &op, 1) != 0) | return -1; | } | else | rex = 0; | | if (op >= 0x58 && op <= 0x5f) | { | /* pop reg */ | gdb_byte reg = (op & 0x0f) | ((rex & 1) << 3); | | cache->prev_reg_addr[amd64_windows_w2gdb_regnum[reg]] = cur_sp; | cur_sp += 8; | } | else | break; | | /* Allow the user to break this loop. This shouldn't happen as the | number of consecutive pop should be small. */ | QUIT; | } Nothing in that loop updates PC, and therefore, because the instruction we stopped at is a "pop", we keep looping forever doing the same thing over and over! This patch fixes the issue by advancing PC to the beginning of the next instruction if the current one is a "pop reg" instruction. gdb/ChangeLog: * amd64-windows-tdep.c (amd64_windows_frame_decode_epilogue): Increment PC in while loop skipping "pop reg" instructions.
Diffstat (limited to 'gdb/amd64-windows-tdep.c')
-rw-r--r--gdb/amd64-windows-tdep.c1
1 files changed, 1 insertions, 0 deletions
diff --git a/gdb/amd64-windows-tdep.c b/gdb/amd64-windows-tdep.c
index 296bdb2710..c04b730f2f 100644
--- a/gdb/amd64-windows-tdep.c
+++ b/gdb/amd64-windows-tdep.c
@@ -488,6 +488,7 @@ amd64_windows_frame_decode_epilogue (struct frame_info *this_frame,
cache->prev_reg_addr[amd64_windows_w2gdb_regnum[reg]] = cur_sp;
cur_sp += 8;
+ pc += rex ? 2 : 1;
}
else
break;