diff --git a/src/memory-analyzer/analyze_symbol.cpp b/src/memory-analyzer/analyze_symbol.cpp index 7e73e7905f..9cfeeae4d6 100644 --- a/src/memory-analyzer/analyze_symbol.cpp +++ b/src/memory-analyzer/analyze_symbol.cpp @@ -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; } diff --git a/src/memory-analyzer/gdb_api.cpp b/src/memory-analyzer/gdb_api.cpp index 3b001a0196..470ae9c020 100644 --- a/src/memory-analyzer/gdb_api.cpp +++ b/src/memory-analyzer/gdb_api.cpp @@ -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 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 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]}; } } diff --git a/src/memory-analyzer/gdb_api.h b/src/memory-analyzer/gdb_api.h index 05f7991370..ad86e44ffb 100644 --- a/src/memory-analyzer/gdb_api.h +++ b/src/memory-analyzer/gdb_api.h @@ -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 &string) - : address(address), pointee(pointee), character(character), string(string) + const std::string &address = "", + const std::string &pointee = "", + const std::string &character = "", + const optionalt &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 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 diff --git a/unit/memory-analyzer/gdb_api.cpp b/unit/memory-analyzer/gdb_api.cpp index 25022371d2..f8cfcd38ce 100644 --- a/unit/memory-analyzer/gdb_api.cpp +++ b/unit/memory-analyzer/gdb_api.cpp @@ -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")