-
Notifications
You must be signed in to change notification settings - Fork 273
GDB API [blocks: #4261] #3983
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
GDB API [blocks: #4261] #3983
Conversation
+1 looking back at the original patch set, connecting using the remote protocol was one of the things I requested. Glad to hear this is moving again. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This sort of interactive child process management is prone to deadlock whenever gdb
might start writing output (for example, an error message) before you're done writing input, and the pipe buffers are small enough that its write op blocks. Therefore usually you should use poll
or similar to check for this circumstance and buffer any output it starts producing before your input command is complete.
src/memory-analyzer/gdb_api.cpp
Outdated
|
||
dprintf(pipe_output[1], "binary name: %s\n", binary); | ||
|
||
char *arg[] = {const_cast<char *>("gdb"), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
? Surely this is a char *const []
as required by execvp
and these const casts should go away?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
unit/memory-analyzer/gdb_api.cpp
Outdated
|
||
#include <testing-utils/use_catch.h> | ||
|
||
#ifdef __linux__ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Anything Unix-y I'd have thought? Are you doing anything tricky enough that Cygwin wouldn't support it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, changed to allow various Unices.
src/memory-analyzer/gdb_api.cpp
Outdated
|
||
/// Termiante the gdb process and close open streams (for reading from and | ||
/// writing to gdb) | ||
void gdb_apit::terminate_gdb_process() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do this in a destructor to raise the chances of cleaning up your child on exception?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
@smowton I'm not sure if that's an issue here. So we only write a command to gdb when we have read the |
78add3d
to
464f292
Compare
23642a0
to
d5b99d2
Compare
@@ -0,0 +1,153 @@ | |||
/*******************************************************************\ | |||
|
|||
Module: GDB Machine Interface API unit tests |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it really worth having a unit test here? It might be better to just run this in regression/
as an integration test? There isn't a whole lot to the API, and the unit test is fairly close to being a shell script written in C++?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The back and forth interaction with gdb
is actually quite complicated. I feel like there definitely need to be unit tests to check that the API does this correctly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, fine with me. I was just wondering whether doing this as a unit test just made things more complicated than necessary.
src/memory-analyzer/gdb_api.cpp
Outdated
/// \file | ||
/// Low-level interface to gdb | ||
|
||
#ifdef __linux__ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Which part of this code is really Linux-specific? If any at all? Even when we might never be able to run a gdb
binary on Visual Studio, it's good to know that at least the code compiles and can be re-used/adapted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, changed to allow various Unices. We need the fork()
call from unistd.h
.
src/memory-analyzer/gdb_api.cpp
Outdated
/// variable `binary` | ||
void gdb_apit::create_gdb_process() | ||
{ | ||
PRECONDITION(gdb_state == gdb_statet::NOT_CREATED); std::cout << "GDB Here 0" << std::endl; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess this needs some cleanup :-) You might as well use a debug()
mstreamt
, possibly with a separate debug logger so that you can use, e.g., a stream-based message handler that puts all the debug output on stderr
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah yes I just added this as I'm debugging some CI issues. This will be removed later.
11cfbd2
to
8088eb0
Compare
Applying CBMC on large code bases requires sometimes to model a test environment. Running a program until a certain point and let it crash, allows to analyze the memory state at this point in time. In continuation, the memory state might be reconstructed as base for the test environment model. By using gdb to analyze the core dump, I don't have to take care of reading and interpreting the core dump myself.
When using the gdb machine interface (option --interpreter=mi), gdb outputs results (such as that of printing a value) as records which are comma-separated lists of key=value pairs. This adds a method parse_gdb_output_record() to parse such records into a std::map.
This switches gdb_apit to use streams to communicate with the gdb subprocess instead of using pipes/file descriptors directly.
This changes gdb_apit to use the gdb machine interface (mi) instead of the gdb command line user interface to communicate with gdb.
We require the Unix fork() system call (in unistd.h)
This enables the gdb api unit tests (in memory-analyzer/gdb_api.cpp) and adapts them to include use_catch.h instead of catch.hpp.
This adds new unit tests for gdb_apit. The tests compile a test file test.c and then run gdb on it (via gdb_apit).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✔️
Passed Diffblue compatibility checks (cbmc commit: fa2ed7b).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/104995261
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✔️
Passed Diffblue compatibility checks (cbmc commit: d803bde).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/104996155
This adds an API to run a program with gdb up to some breakpoint and then query the values of expressions. It is a partial rewrite of @mmuesly's gdb API (part of #2649). It now uses the gdb machine interface instead of the gdb user interface.