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:
parent
40bd28b921
commit
93f4ee40a0
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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]};
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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")
|
||||
|
|
Loading…
Reference in New Issue