Skip to content

Commit dec39d5

Browse files
committed
Add method to parse gdb output records
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.
1 parent 4db96d4 commit dec39d5

File tree

2 files changed

+69
-2
lines changed

2 files changed

+69
-2
lines changed

src/memory-analyzer/gdb_api.cpp

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@
99
#include "gdb_api.h"
1010
#include <goto-programs/goto_model.h>
1111

12-
gdb_apit::gdb_apit(const char *arg)
13-
: binary_name(arg), buffer_position(0), last_read_size(0)
12+
#include <util/string_utils.h>
13+
14+
gdb_apit::gdb_apit(const char *arg) : binary_name(arg)
1415
{
1516
memset(buffer, 0, MAX_READ_SIZE_GDB_BUFFER);
1617
}
@@ -263,4 +264,67 @@ std::string gdb_apit::extract_value(const std::string &line)
263264
throw gdb_interaction_exceptiont("Cannot extract value from this: " + line);
264265
}
265266

267+
gdb_apit::gdb_output_recordt
268+
gdb_apit::parse_gdb_output_record(const std::string &s)
269+
{
270+
PRECONDITION(s.back() != '\n');
271+
272+
gdb_output_recordt result;
273+
274+
unsigned depth = 0;
275+
std::string::size_type start = 0;
276+
277+
const std::string::size_type n = s.length();
278+
279+
for(std::string::size_type i = 0; i < n; i++)
280+
{
281+
const char c = s[i];
282+
283+
if(c == '{' || c == '[')
284+
{
285+
depth++;
286+
}
287+
else if(c == '}' || c == ']')
288+
{
289+
depth--;
290+
}
291+
292+
if(depth == 0 && (c == ',' || i == n - 1))
293+
{
294+
const std::string item =
295+
i == n - 1 ? s.substr(start) : s.substr(start, i - start);
296+
297+
// Split on first `=`
298+
std::string::size_type j = item.find('=');
299+
CHECK_RETURN(j != std::string::npos);
300+
CHECK_RETURN(j > 0);
301+
CHECK_RETURN(j < s.length());
302+
303+
const std::string key = strip_string(item.substr(0, j));
304+
std::string value = strip_string(item.substr(j + 1));
305+
306+
const char first = value.front();
307+
const char last = value.back();
308+
309+
INVARIANT(first == '"' || first == '{' || first == '[', "");
310+
INVARIANT(first != '"' || last == '"', "");
311+
INVARIANT(first != '{' || last == '}', "");
312+
INVARIANT(first != '[' || last == ']', "");
313+
314+
// Remove enclosing `"` for primitive values
315+
if(first == '"')
316+
{
317+
value = value.substr(1, value.length() - 2);
318+
}
319+
320+
auto r = result.insert(std::make_pair(key, value));
321+
CHECK_RETURN(r.second);
322+
323+
start = i + 1;
324+
}
325+
}
326+
327+
return result;
328+
}
329+
266330
#endif

src/memory-analyzer/gdb_api.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ class gdb_apit
4646

4747
static std::string extract_value(const std::string &line);
4848
static std::string extract_memory(const std::string &line);
49+
50+
typedef std::map<std::string, std::string> gdb_output_recordt;
51+
static gdb_output_recordt parse_gdb_output_record(const std::string &s);
4952
};
5053

5154
class gdb_interaction_exceptiont : public std::exception

0 commit comments

Comments
 (0)