Go to the documentation of this file.
   31   : args(args), log(log), gdb_state(
gdb_statet::NOT_CREATED)
 
   60   const auto maybe_address_string = 
get_value(pointer_expr);
 
   80   if(pipe(pipe_input) == -1)
 
   85   if(pipe(pipe_output) == -1)
 
  100     close(pipe_input[1]);
 
  101     close(pipe_output[0]);
 
  103     dup2(pipe_input[0], STDIN_FILENO);
 
  104     dup2(pipe_output[1], STDOUT_FILENO);
 
  105     dup2(pipe_output[1], STDERR_FILENO);
 
  107     dprintf(pipe_output[1], 
"binary name: %s\n", 
args.front().c_str());
 
  109     std::vector<std::string> exec_cmd;
 
  110     exec_cmd.reserve(
args.size() + 3);
 
  111     exec_cmd.push_back(
"gdb");
 
  112     exec_cmd.push_back(
"--interpreter=mi");
 
  113     exec_cmd.push_back(
"--args");
 
  114     exec_cmd.insert(exec_cmd.end(), 
args.begin(), 
args.end());
 
  116     char **exec_cmd_ptr = 
static_cast<char **
>(malloc(
 
  117       sizeof(
char *) * (exec_cmd.size() + 1)));
 
  118     exec_cmd_ptr[exec_cmd.size()] = NULL;
 
  120     for(std::size_t i = 0; i < exec_cmd.size(); i++)
 
  122       exec_cmd_ptr[i] = 
static_cast<char *
>(malloc(
 
  123         sizeof(
char) * (exec_cmd[i].length() + 1)));
 
  124       strcpy(exec_cmd_ptr[i], exec_cmd[i].c_str()); 
 
  127     dprintf(pipe_output[1], 
"Loading gdb...\n");
 
  128     execvp(
"gdb", exec_cmd_ptr);
 
  131     int errno_value = errno;
 
  132     dprintf(pipe_output[1], 
"Starting gdb failed: %s\n", strerror(errno_value));
 
  133     dprintf(pipe_output[1], 
"(gdb) \n");
 
  139     close(pipe_input[0]);
 
  140     close(pipe_output[1]);
 
  176   std::string line(command);
 
  204     const size_t buf_size = 1024;
 
  218         "EOF must have been reached when the error indicator on the stream " 
  219         "is not set and fgets returned NULL");
 
  221         result.empty() || result.back() != 
'\n',
 
  222         "when EOF is reached then either no characters were read or the string" 
  223         " read does not end in a newline");
 
  228     std::string chunk(buf);
 
  229     INVARIANT(!chunk.empty(), 
"chunk cannot be empty when EOF was not reached");
 
  232   } 
while(result.back() != 
'\n');
 
  246   } 
while(line != 
"(gdb) \n");
 
  266   std::string record = 
strip_string(line.substr(line.find(
',') + 1));
 
  282   const std::string command = 
"core " + corefile;
 
  318   if(frame_content.find(
"func=\"malloc\"") != std::string::npos)
 
  342   std::string command(
"-break-insert");
 
  343   command += 
" " + breakpoint;
 
  383   const auto it = record.find(
"reason");
 
  386   const std::string &reason = it->second;
 
  388   if(reason == 
"breakpoint-hit")
 
  393   else if(reason == 
"exited-normally")
 
  400       "gdb stopped for unhandled reason `" + reason + 
"`");
 
  413       "could not create variable for expression `" + expr + 
"`");
 
  422   const auto it = record.find(
"value");
 
  425   const std::string value = it->second;
 
  428     value.back() != 
'"' ||
 
  429       (value.length() >= 2 && value[value.length() - 2] == 
'\\'),
 
  430     "quotes should have been stripped off from value");
 
  431   INVARIANT(value.back() != 
'\n', 
"value should not end in a newline");
 
  447     return pointer_valuet{};
 
  454   const bool b = regex_match(value, result, regex);
 
  456     return pointer_valuet{};
 
  459   const std::string 
string = result[4];
 
  463     const std::size_t len = 
string.length();
 
  467       "pointer-string should be: backslash, quotes, .., backslash, quotes");
 
  470       "pointer-string should be: backslash, quotes, .., backslash, quotes");
 
  473       "pointer-string should be: backslash, quotes, .., backslash, quotes");
 
  475       string[len - 2] == 
'\\',
 
  476       "pointer-string should be: backslash, quotes, .., backslash, quotes");
 
  478       string[len - 1] == 
'"',
 
  479       "pointer-string should be: backslash, quotes, .., backslash, quotes");
 
  481     opt_string = 
string.substr(2, len - 4);
 
  484   return pointer_valuet(result[1], result[2], result[3], opt_string, 
true);
 
  504     std::regex regex(R
"([^ ]+ '([^']+)')"); 
  507     const bool b = regex_match(value, result, regex);
 
  511       return std::string{result[1]};
 
  526   std::size_t depth = 0;
 
  535     if(c == 
'{' || c == 
'[')
 
  539     else if(c == 
'}' || c == 
']')
 
  544     if(depth == 0 && (c == 
',' || i == n - 1))
 
  546       const std::string item =
 
  547         i == n - 1 ? s.substr(start) : s.substr(start, i - start);
 
  555       const std::string key = 
strip_string(item.substr(0, j));
 
  558       const char first = value.front();
 
  559       const char last = value.back();
 
  561       INVARIANT(first == 
'"' || first == 
'{' || first == 
'[', 
"");
 
  562       INVARIANT(first != 
'"' || last == 
'"', 
"");
 
  563       INVARIANT(first != 
'{' || last == 
'}', 
"");
 
  564       INVARIANT(first != 
'[' || last == 
']', 
"");
 
  569         value = value.substr(1, value.length() - 2);
 
  572       auto r = result.insert(std::make_pair(key, value));
 
  595   return R
"((?:)" + regex + R"()?)"; 
  599 gdb_apit::r_or(const std::string ®ex_left, 
const std::string ®ex_right)
 
  601   return R
"((?:)" + regex_left + '|' + regex_right + R
"())"; 
  605   const gdb_output_recordt &record,
 
  606   const std::string &value_name)
 
  608   const auto it = record.find(value_name);
 
  610   const auto value = it->second;
 
  613     value.back() != 
'"' ||
 
  614       (value.length() >= 2 && value[value.length() - 2] == 
'\\'),
 
  615     "quotes should have been stripped off from value");
 
  616   INVARIANT(value.back() != 
'\n', 
"value should not end in a newline");
 
  623   const auto it = stopped_record.find(
"reason");
 
  626   if(it->second != 
"breakpoint-hit")
 
  638   std::string value_eq_quotes = 
"value=\"";
 
  639   auto value_eq_quotes_size = value_eq_quotes.size();
 
  641   auto starting_pos = record_value.find(value_eq_quotes) + value_eq_quotes_size;
 
  642   auto ending_pos = record_value.find(
'\"', starting_pos);
 
  643   auto value_length = ending_pos - starting_pos;
 
  644   return std::string{record_value, starting_pos, value_length};
 
  
 
static std::string r_or(const std::string ®ex_left, const std::string ®ex_right)
 
#define UNREACHABLE
This should be used to mark dead code.
 
bool hit_malloc_breakpoint(const gdb_output_recordt &stopped_record)
Check if the breakpoint we hit is inside a malloc.
 
void collect_malloc_calls()
Intercepts the gdb-analysis at the malloc call-site to add the corresponding information into allocat...
 
static std::string r_opt(const std::string ®ex)
 
size_t query_malloc_size(const std::string &pointer_expr)
Get the exact allocated size for a pointer pointer_expr.
 
Data associated with the value of a pointer, i.e.
 
std::vector< std::string > args
 
#define CHECK_RETURN(CONDITION)
 
std::forward_list< std::string > commandst
 
pointer_valuet get_memory(const std::string &expr)
Get the value of a pointer associated with expr.
 
const irept & find(const irep_idt &name) const
 
static gdb_output_recordt parse_gdb_output_record(const std::string &s)
 
bool most_recent_line_has_tag(const std::string &tag)
 
gdb_apit(const std::vector< std::string > &args, const bool log=false)
Create a gdb_apit object.
 
std::string eval_expr(const std::string &expr)
 
std::size_t safe_string2size_t(const std::string &str, int base)
 
std::string strip_string(const std::string &s)
Remove all whitespace characters from either end of a string.
 
const std::string r_hex_addr
 
bool has_prefix(const std::string &s, const std::string &prefix)
 
#define PRECONDITION(CONDITION)
 
gdb_output_recordt get_most_recent_record(const std::string &tag, const bool must_exist=false)
 
void write_to_gdb(const std::string &command)
 
~gdb_apit()
Terminate the gdb process and close open streams (for reading from and writing to gdb)
 
std::string read_next_line()
 
const commandst & get_command_log()
Return the vector of commands that have been written to gdb so far.
 
const std::string malloc_name
 
std::map< std::string, size_t > allocated_memory
track the allocated size for each malloc call maps hexadecimal address to the number of bytes
 
optionalt< std::string > get_value(const std::string &expr)
Get the memory address pointed to by the given pointer expression.
 
std::string get_register_value(const gdb_output_recordt &record)
Parse the record produced by listing register value.
 
nonstd::optional< T > optionalt
 
bool was_command_accepted()
 
std::string get_value_from_record(const gdb_output_recordt &record, const std::string &value_name)
Locate and return the value for a given name.
 
void create_gdb_process()
Create a new gdb process for analysing the binary indicated by the first element in args
 
const std::string r_string
 
void check_command_accepted()
 
bool run_gdb_to_breakpoint(const std::string &breakpoint)
Run gdb to the given breakpoint.
 
void run_gdb_from_core(const std::string &corefile)
Run gdb with the given core file.
 
unsignedbv_typet size_type()
 
std::string read_most_recent_line()
 
std::map< std::string, std::string > gdb_output_recordt