CBMC
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
invariant.cpp
Go to the documentation of this file.
1/*******************************************************************\
2
3Module:
4
5Author: Martin Brain, martin.brain@diffblue.com
6
7\*******************************************************************/
8
9#include "invariant.h"
10
11#include "freer.h"
12
13#include <memory>
14#include <sstream>
15#include <string>
16
17#include <iostream>
18
19#ifdef _WIN32
20// the ordering of includes is required
21// clang-format off
22#include <iomanip>
23#include <windows.h>
24#include <dbghelp.h>
25// clang-format on
26#endif
27
29
30// Backtraces compiler and C library specific
31// So we should include something explicitly from the C library
32// to check if the C library is glibc.
33#include <assert.h> // IWYU pragma: keep
34#if defined(__GLIBC__) || defined(__APPLE__)
35
36// GCC needs LINKFLAGS="-rdynamic" to give function names in the backtrace
37#include <execinfo.h>
38#include <cxxabi.h>
39
49static bool output_demangled_name(
50 std::ostream &out,
51 const std::string &stack_entry)
52{
53 bool return_value=false;
54
55 std::string working(stack_entry);
56
57 std::string::size_type start=working.rfind('('); // Path may contain '(' !
58 std::string::size_type end=working.find('+', start);
59
60 if(start!=std::string::npos &&
61 end!=std::string::npos &&
62 start+1<=end-1)
63 {
64 std::string::size_type length=end-(start+1);
65 std::string mangled(working.substr(start+1, length));
66
67 int demangle_success=1;
68 std::unique_ptr<char, freert> demangled(
70 mangled.c_str(), nullptr, nullptr, &demangle_success));
71
72 if(demangle_success==0)
73 {
74 out << working.substr(0, start+1)
75 << demangled.get()
76 << working.substr(end);
77 return_value=true;
78 }
79 }
80
81 return return_value;
82}
83#endif
84
85
89 std::ostream &out)
90{
91#if defined(__GLIBC__) || defined(__APPLE__)
92 void * stack[50] = {};
93
94 std::size_t entries=backtrace(stack, sizeof(stack) / sizeof(void *));
95 std::unique_ptr<char*, freert> description(
96 backtrace_symbols(stack, entries));
97
98 for(std::size_t i=0; i<entries; i++)
99 {
100 if(!output_demangled_name(out, description.get()[i]))
101 out << description.get()[i];
102 out << '\n' << std::flush;
103 }
104
105#elif defined(_WIN32)
106
107 void *stack[50];
108 HANDLE process = GetCurrentProcess();
109
110 SymInitialize(process, NULL, TRUE);
111
112 auto number_of_frames =
113 CaptureStackBackTrace(0, sizeof(stack) / sizeof(void *), stack, NULL);
114
115 // Read
116 // https://docs.microsoft.com/en-us/windows/win32/api/dbghelp/ns-dbghelp-symbol_info
117 // for the rationale behind the size of 'symbol'
118 const auto max_name_len = 255;
119 auto symbol = static_cast<SYMBOL_INFO *>(
120 calloc(sizeof SYMBOL_INFO + (max_name_len - 1) * sizeof(TCHAR), 1));
121 symbol->MaxNameLen = max_name_len;
122 symbol->SizeOfStruct = sizeof SYMBOL_INFO;
123
124 for(std::size_t i = 0; i < number_of_frames; i++)
125 {
126 SymFromAddr(process, (DWORD64)(stack[i]), 0, symbol);
127 out << std::setw(3) << i;
128 out << " 0x" << std::hex << std::setw(8) << symbol->Address;
129 out << ' ' << symbol->Name;
130 out << '\n' << std::flush;
131 }
132
133 free(symbol);
134#else
135 out << "Backtraces not supported\n" << std::flush;
136#endif
137}
138
141std::string get_backtrace()
142{
143 std::ostringstream ostr;
145 return ostr.str();
146}
147
150{
151 std::cerr << "--- begin invariant violation report ---\n";
152 std::cerr << reason.what() << '\n';
153 std::cerr << "--- end invariant violation report ---\n";
154}
155
157{
158 std::ostringstream out;
159 out << "Invariant check failed\n"
160 << "File: " << file << ":" << line << " function: " << function << '\n'
161 << "Condition: " << condition << '\n'
162 << "Reason: " << reason << '\n'
163 << "Backtrace:" << '\n'
164 << backtrace << '\n';
165 return out.str();
166}
167
169{
170 std::string s(invariant_failedt::what());
171
172 if(!s.empty() && s.back() != '\n')
173 s += '\n';
174
175 return s + "Diagnostics: " + diagnostics + '\n';
176}
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:562
ait()
Definition ai.h:565
A logic error, augmented with a distinguished field to hold a backtrace.
Definition c_errors.h:28
const int line
Definition c_errors.h:32
const std::string backtrace
Definition c_errors.h:33
const std::string reason
Definition c_errors.h:35
const std::string condition
Definition c_errors.h:34
virtual std::string what() const noexcept
const std::string function
Definition c_errors.h:31
const std::string file
Definition c_errors.h:30
virtual std::string what() const noexcept
std::string get_backtrace()
Returns a backtrace.
void report_exception_to_stderr(const invariant_failedt &reason)
Dump exception report to stderr.
void print_backtrace(std::ostream &out)
Prints a back trace to 'out'.
Definition invariant.cpp:88
bool cbmc_invariants_should_throw
Set this to true to cause invariants to throw a C++ exception rather than abort the program.
Definition invariant.cpp:28
void * calloc(__CPROVER_size_t nmemb, __CPROVER_size_t size)
Definition stdlib.c:146
void free(void *ptr)
Definition stdlib.c:317