Optionalize the results of querying gdb

Not all queried values are sensible if we ask past allocated
memory (malloc_usable_size doesn't return exact values).
This commit is contained in:
Petr Bauch 2019-05-20 11:03:47 +01:00
parent 40bd28b921
commit 93f4ee40a0
4 changed files with 85 additions and 28 deletions

View File

@ -325,6 +325,8 @@ exprt gdb_value_extractort::get_pointer_value(
std::string c_expr = c_converter.convert(expr);
const pointer_valuet value = gdb_api.get_memory(c_expr);
if(!value.valid)
return zero_expr;
const auto memory_location = value.address;
@ -395,26 +397,53 @@ exprt gdb_value_extractort::get_expr_value(
{
INVARIANT(zero_expr.is_constant(), "zero initializer is a constant");
return from_integer(string2integer(get_gdb_value(expr)), expr.type());
std::string c_expr = c_converter.convert(expr);
const auto maybe_value = gdb_api.get_value(c_expr);
if(!maybe_value.has_value())
return zero_expr;
const std::string value = *maybe_value;
const mp_integer int_rep = string2integer(value);
return from_integer(int_rep, type);
}
else if(is_c_char_type(type))
{
INVARIANT(zero_expr.is_constant(), "zero initializer is a constant");
return zero_expr; // currently left at 0
// check the char-value and return as bitvector-type value
std::string c_expr = c_converter.convert(expr);
const auto maybe_value = gdb_api.get_value(c_expr);
if(!maybe_value.has_value() || maybe_value->empty())
return zero_expr;
const std::string value = *maybe_value;
const mp_integer int_rep = value[0];
return from_integer(int_rep, type);
}
else if(type.id() == ID_c_bool)
{
INVARIANT(zero_expr.is_constant(), "zero initializer is a constant");
return from_c_boolean_value(id2boolean(get_gdb_value(expr)), type);
std::string c_expr = c_converter.convert(expr);
const auto maybe_value = gdb_api.get_value(c_expr);
if(!maybe_value.has_value())
return zero_expr;
const std::string value = *maybe_value;
return from_c_boolean_value(id2boolean(value), type);
}
else if(type.id() == ID_c_enum)
{
INVARIANT(zero_expr.is_constant(), "zero initializer is a constant");
return convert_member_name_to_enum_value(
get_gdb_value(expr), to_c_enum_type(type));
std::string c_expr = c_converter.convert(expr);
const auto maybe_value = gdb_api.get_value(c_expr);
if(!maybe_value.has_value())
return zero_expr;
const std::string value = *maybe_value;
return convert_member_name_to_enum_value(value, to_c_enum_type(type));
}
else if(type.id() == ID_struct_tag)
{
@ -503,5 +532,8 @@ void gdb_value_extractort::process_outstanding_assignments()
std::string gdb_value_extractort::get_gdb_value(const exprt &expr)
{
return gdb_api.get_value(c_converter.convert(expr));
std::string c_expr = c_converter.convert(expr);
const auto maybe_value = gdb_api.get_value(c_expr);
CHECK_RETURN(maybe_value.has_value());
return *maybe_value;
}

View File

@ -377,14 +377,23 @@ gdb_apit::pointer_valuet gdb_apit::get_memory(const std::string &expr)
{
PRECONDITION(gdb_state == gdb_statet::STOPPED);
std::string value = eval_expr(expr);
std::string value;
try
{
value = eval_expr(expr);
}
catch(gdb_interaction_exceptiont &e)
{
return pointer_valuet{};
}
std::regex regex(
r_hex_addr + r_opt(' ' + r_id) + r_opt(' ' + r_or(r_char, r_string)));
std::smatch result;
const bool b = regex_match(value, result, regex);
CHECK_RETURN(b);
if(!b)
return pointer_valuet{};
optionalt<std::string> opt_string;
const std::string string = result[4];
@ -412,14 +421,22 @@ gdb_apit::pointer_valuet gdb_apit::get_memory(const std::string &expr)
opt_string = string.substr(2, len - 4);
}
return pointer_valuet(result[1], result[2], result[3], opt_string);
return pointer_valuet(result[1], result[2], result[3], opt_string, true);
}
std::string gdb_apit::get_value(const std::string &expr)
optionalt<std::string> gdb_apit::get_value(const std::string &expr)
{
PRECONDITION(gdb_state == gdb_statet::STOPPED);
const std::string value = eval_expr(expr);
std::string value;
try
{
value = eval_expr(expr);
}
catch(gdb_interaction_exceptiont &e)
{
return {};
}
// Get char value
{
@ -431,7 +448,7 @@ std::string gdb_apit::get_value(const std::string &expr)
if(b)
{
return result[1];
return std::string{result[1]};
}
}

View File

@ -68,13 +68,17 @@ public:
struct pointer_valuet
{
pointer_valuet() = delete;
pointer_valuet(
const std::string &address,
const std::string &pointee,
const std::string &character,
const optionalt<std::string> &string)
: address(address), pointee(pointee), character(character), string(string)
const std::string &address = "",
const std::string &pointee = "",
const std::string &character = "",
const optionalt<std::string> &string = nullopt,
const bool valid = false)
: address(address),
pointee(pointee),
character(character),
string(string),
valid(valid)
{
}
@ -88,6 +92,8 @@ public:
return std::any_of(
pointee.begin(), pointee.end(), [](char c) { return c == '+'; });
}
bool valid;
};
/// Get the allocated size estimate for a pointer by evaluating
@ -115,17 +121,12 @@ public:
/// \param corefile: core dump
void run_gdb_from_core(const std::string &corefile);
/// Get value of the given value expression
/// \param expr: an expression of non-pointer type or pointer to char
/// \return value of the expression; if the expression is of type pointer to
/// char and represents a string, the string value is returned; otherwise
/// the value is returned just as it is printed by gdb
std::string get_value(const std::string &expr);
/// Get the memory address pointed to by the given pointer expression
/// \param expr: an expression of pointer type (e.g., `&x` with `x` being of
/// type `int` or `p` with `p` being of type `int *`)
/// \return memory address in hex format
optionalt<std::string> get_value(const std::string &expr);
pointer_valuet get_memory(const std::string &expr);
/// Return the vector of commands that have been written to gdb so far

View File

@ -167,9 +167,16 @@ TEST_CASE("gdb api test", "[core][memory-analyzer]")
const bool r = gdb_api.run_gdb_to_breakpoint("checkpoint");
REQUIRE(r);
REQUIRE(gdb_api.get_value("x") == "8");
REQUIRE(gdb_api.get_value("y") == "2.5");
REQUIRE(gdb_api.get_value("z") == "c");
const auto &x_value = gdb_api.get_value("x");
const auto &y_value = gdb_api.get_value("y");
const auto &z_value = gdb_api.get_value("z");
REQUIRE(x_value.has_value());
REQUIRE(*x_value == "8");
REQUIRE(y_value.has_value());
REQUIRE(*y_value == "2.5");
REQUIRE(z_value.has_value());
REQUIRE(*z_value == "c");
}
SECTION("query pointers")