Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
729a2462
Commit
729a2462
authored
Apr 04, 2020
by
Rémi Bernon
Committed by
Alexandre Julliard
Apr 06, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
winedbg: Add support for hardware watchpoints.
Signed-off-by:
Rémi Bernon
<
rbernon@codeweavers.com
>
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
40f1c669
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
186 additions
and
0 deletions
+186
-0
gdbproxy.c
programs/winedbg/gdbproxy.c
+186
-0
No files found.
programs/winedbg/gdbproxy.c
View file @
729a2462
...
...
@@ -67,6 +67,17 @@
WINE_DEFAULT_DEBUG_CHANNEL
(
winedbg
);
struct
gdb_xpoint
{
struct
list
entry
;
int
pid
;
int
tid
;
enum
be_xpoint_type
type
;
void
*
addr
;
int
size
;
unsigned
long
value
;
};
struct
gdb_context
{
/* gdb information */
...
...
@@ -86,6 +97,7 @@ struct gdb_context
/* generic GDB thread information */
int
exec_tid
;
/* tid used in step & continue */
int
other_tid
;
/* tid to be used in any other operation */
struct
list
xpoint_list
;
/* current Win32 trap env */
DEBUG_EVENT
de
;
DWORD
de_reply
;
...
...
@@ -98,6 +110,64 @@ struct gdb_context
BOOL
no_ack_mode
;
};
static
void
gdbctx_delete_xpoint
(
struct
gdb_context
*
gdbctx
,
struct
dbg_thread
*
thread
,
dbg_ctx_t
*
ctx
,
struct
gdb_xpoint
*
x
)
{
struct
dbg_process
*
process
=
thread
->
process
;
struct
backend_cpu
*
cpu
=
process
->
be_cpu
;
if
(
!
cpu
->
remove_Xpoint
(
process
->
handle
,
process
->
process_io
,
ctx
,
x
->
type
,
x
->
addr
,
x
->
value
,
x
->
size
))
ERR
(
"%04x:%04x: Couldn't remove breakpoint at:%p/%x type:%d
\n
"
,
process
->
pid
,
thread
->
tid
,
x
->
addr
,
x
->
size
,
x
->
type
);
list_remove
(
&
x
->
entry
);
HeapFree
(
GetProcessHeap
(),
0
,
x
);
}
static
void
gdbctx_insert_xpoint
(
struct
gdb_context
*
gdbctx
,
struct
dbg_thread
*
thread
,
dbg_ctx_t
*
ctx
,
enum
be_xpoint_type
type
,
void
*
addr
,
int
size
)
{
struct
dbg_process
*
process
=
thread
->
process
;
struct
backend_cpu
*
cpu
=
process
->
be_cpu
;
struct
gdb_xpoint
*
x
;
unsigned
long
value
;
if
(
!
cpu
->
insert_Xpoint
(
process
->
handle
,
process
->
process_io
,
ctx
,
type
,
addr
,
&
value
,
size
))
{
ERR
(
"%04x:%04x: Couldn't insert breakpoint at:%p/%x type:%d
\n
"
,
process
->
pid
,
thread
->
tid
,
addr
,
size
,
type
);
return
;
}
if
(
!
(
x
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
struct
gdb_xpoint
))))
{
ERR
(
"%04x:%04x: Couldn't allocate memory for breakpoint at:%p/%x type:%d
\n
"
,
process
->
pid
,
thread
->
tid
,
addr
,
size
,
type
);
return
;
}
x
->
pid
=
process
->
pid
;
x
->
tid
=
thread
->
tid
;
x
->
type
=
type
;
x
->
addr
=
addr
;
x
->
size
=
size
;
x
->
value
=
value
;
list_add_head
(
&
gdbctx
->
xpoint_list
,
&
x
->
entry
);
}
static
struct
gdb_xpoint
*
gdb_find_xpoint
(
struct
gdb_context
*
gdbctx
,
struct
dbg_thread
*
thread
,
enum
be_xpoint_type
type
,
void
*
addr
,
int
size
)
{
struct
gdb_xpoint
*
x
;
LIST_FOR_EACH_ENTRY
(
x
,
&
gdbctx
->
xpoint_list
,
struct
gdb_xpoint
,
entry
)
{
if
(
thread
&&
(
x
->
pid
!=
thread
->
process
->
pid
||
x
->
tid
!=
thread
->
tid
))
continue
;
if
(
x
->
type
==
type
&&
x
->
addr
==
addr
&&
x
->
size
==
size
)
return
x
;
}
return
NULL
;
}
static
BOOL
tgt_process_gdbproxy_read
(
HANDLE
hProcess
,
const
void
*
addr
,
void
*
buffer
,
SIZE_T
len
,
SIZE_T
*
rlen
)
{
...
...
@@ -775,6 +845,34 @@ static inline void packet_reply_register_hex_to(struct gdb_context* gdbctx, dbg_
* =============================================== *
*/
static
void
packet_reply_status_xpoints
(
struct
gdb_context
*
gdbctx
,
struct
dbg_thread
*
thread
,
dbg_ctx_t
*
ctx
)
{
struct
dbg_process
*
process
=
thread
->
process
;
struct
backend_cpu
*
cpu
=
process
->
be_cpu
;
struct
gdb_xpoint
*
x
;
LIST_FOR_EACH_ENTRY
(
x
,
&
gdbctx
->
xpoint_list
,
struct
gdb_xpoint
,
entry
)
{
if
(
x
->
pid
!=
process
->
pid
||
x
->
tid
!=
thread
->
tid
)
continue
;
if
(
!
cpu
->
is_watchpoint_set
(
ctx
,
x
->
value
))
continue
;
if
(
x
->
type
==
be_xpoint_watch_write
)
{
packet_reply_add
(
gdbctx
,
"watch:"
);
packet_reply_val
(
gdbctx
,
(
unsigned
long
)
x
->
addr
,
sizeof
(
x
->
addr
));
packet_reply_add
(
gdbctx
,
";"
);
}
if
(
x
->
type
==
be_xpoint_watch_read
)
{
packet_reply_add
(
gdbctx
,
"rwatch:"
);
packet_reply_val
(
gdbctx
,
(
unsigned
long
)
x
->
addr
,
sizeof
(
x
->
addr
));
packet_reply_add
(
gdbctx
,
";"
);
}
}
}
static
enum
packet_return
packet_reply_status
(
struct
gdb_context
*
gdbctx
)
{
struct
dbg_process
*
process
=
gdbctx
->
process
;
...
...
@@ -800,6 +898,7 @@ static enum packet_return packet_reply_status(struct gdb_context* gdbctx)
packet_reply_add
(
gdbctx
,
"thread:"
);
packet_reply_val
(
gdbctx
,
gdbctx
->
de
.
dwThreadId
,
4
);
packet_reply_add
(
gdbctx
,
";"
);
packet_reply_status_xpoints
(
gdbctx
,
thread
,
&
ctx
);
for
(
i
=
0
;
i
<
backend
->
gdb_num_regs
;
i
++
)
{
...
...
@@ -924,6 +1023,90 @@ static enum packet_return packet_continue_signal(struct gdb_context* gdbctx)
return
packet_reply_status
(
gdbctx
);
}
static
enum
packet_return
packet_delete_breakpoint
(
struct
gdb_context
*
gdbctx
)
{
struct
dbg_process
*
process
=
gdbctx
->
process
;
struct
dbg_thread
*
thread
;
struct
backend_cpu
*
cpu
;
struct
gdb_xpoint
*
x
;
dbg_ctx_t
ctx
;
char
type
;
void
*
addr
;
int
size
;
if
(
!
process
)
return
packet_error
;
if
(
!
(
cpu
=
process
->
be_cpu
))
return
packet_error
;
if
(
sscanf
(
gdbctx
->
in_packet
,
"%c,%p,%x"
,
&
type
,
&
addr
,
&
size
)
<
3
)
return
packet_error
;
if
(
type
==
'0'
)
return
packet_error
;
LIST_FOR_EACH_ENTRY
(
thread
,
&
process
->
threads
,
struct
dbg_thread
,
entry
)
{
if
(
!
cpu
->
get_context
(
thread
->
handle
,
&
ctx
))
continue
;
if
((
type
==
'1'
)
&&
(
x
=
gdb_find_xpoint
(
gdbctx
,
thread
,
be_xpoint_watch_exec
,
addr
,
size
)))
gdbctx_delete_xpoint
(
gdbctx
,
thread
,
&
ctx
,
x
);
if
((
type
==
'2'
||
type
==
'4'
)
&&
(
x
=
gdb_find_xpoint
(
gdbctx
,
thread
,
be_xpoint_watch_read
,
addr
,
size
)))
gdbctx_delete_xpoint
(
gdbctx
,
thread
,
&
ctx
,
x
);
if
((
type
==
'3'
||
type
==
'4'
)
&&
(
x
=
gdb_find_xpoint
(
gdbctx
,
thread
,
be_xpoint_watch_write
,
addr
,
size
)))
gdbctx_delete_xpoint
(
gdbctx
,
thread
,
&
ctx
,
x
);
cpu
->
set_context
(
thread
->
handle
,
&
ctx
);
}
while
((
type
==
'1'
)
&&
(
x
=
gdb_find_xpoint
(
gdbctx
,
NULL
,
be_xpoint_watch_exec
,
addr
,
size
)))
gdbctx_delete_xpoint
(
gdbctx
,
NULL
,
NULL
,
x
);
while
((
type
==
'2'
||
type
==
'4'
)
&&
(
x
=
gdb_find_xpoint
(
gdbctx
,
NULL
,
be_xpoint_watch_read
,
addr
,
size
)))
gdbctx_delete_xpoint
(
gdbctx
,
NULL
,
NULL
,
x
);
while
((
type
==
'3'
||
type
==
'4'
)
&&
(
x
=
gdb_find_xpoint
(
gdbctx
,
NULL
,
be_xpoint_watch_write
,
addr
,
size
)))
gdbctx_delete_xpoint
(
gdbctx
,
NULL
,
NULL
,
x
);
return
packet_ok
;
}
static
enum
packet_return
packet_insert_breakpoint
(
struct
gdb_context
*
gdbctx
)
{
struct
dbg_process
*
process
=
gdbctx
->
process
;
struct
dbg_thread
*
thread
;
struct
backend_cpu
*
cpu
;
dbg_ctx_t
ctx
;
char
type
;
void
*
addr
;
int
size
;
if
(
!
process
)
return
packet_error
;
if
(
!
(
cpu
=
process
->
be_cpu
))
return
packet_error
;
if
(
memchr
(
gdbctx
->
in_packet
,
';'
,
gdbctx
->
in_packet_len
))
{
FIXME
(
"breakpoint commands not supported
\n
"
);
return
packet_error
;
}
if
(
sscanf
(
gdbctx
->
in_packet
,
"%c,%p,%x"
,
&
type
,
&
addr
,
&
size
)
<
3
)
return
packet_error
;
if
(
type
==
'0'
)
return
packet_error
;
LIST_FOR_EACH_ENTRY
(
thread
,
&
process
->
threads
,
struct
dbg_thread
,
entry
)
{
if
(
!
cpu
->
get_context
(
thread
->
handle
,
&
ctx
))
continue
;
if
(
type
==
'1'
)
gdbctx_insert_xpoint
(
gdbctx
,
thread
,
&
ctx
,
be_xpoint_watch_exec
,
addr
,
size
);
if
(
type
==
'2'
||
type
==
'4'
)
gdbctx_insert_xpoint
(
gdbctx
,
thread
,
&
ctx
,
be_xpoint_watch_read
,
addr
,
size
);
if
(
type
==
'3'
||
type
==
'4'
)
gdbctx_insert_xpoint
(
gdbctx
,
thread
,
&
ctx
,
be_xpoint_watch_write
,
addr
,
size
);
cpu
->
set_context
(
thread
->
handle
,
&
ctx
);
}
return
packet_ok
;
}
static
enum
packet_return
packet_detach
(
struct
gdb_context
*
gdbctx
)
{
detach_debuggee
(
gdbctx
,
FALSE
);
...
...
@@ -1815,6 +1998,8 @@ static struct packet_entry packet_entries[] =
{
's'
,
packet_step
},
{
'T'
,
packet_thread_alive
},
{
'v'
,
packet_verbose
},
{
'z'
,
packet_delete_breakpoint
},
{
'Z'
,
packet_insert_breakpoint
},
};
static
BOOL
extract_packets
(
struct
gdb_context
*
gdbctx
)
...
...
@@ -2069,6 +2254,7 @@ static BOOL gdb_init_context(struct gdb_context* gdbctx, unsigned flags, unsigne
gdbctx
->
exec_tid
=
-
1
;
gdbctx
->
other_tid
=
-
1
;
list_init
(
&
gdbctx
->
xpoint_list
);
gdbctx
->
last_sig
=
0
;
gdbctx
->
in_trap
=
FALSE
;
gdbctx
->
process
=
NULL
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment