Open jordr opened 4 years ago
This seems to work well:
Keeper.cpp@generateSkippedTargets
for(klee::SpecialFunctionHandler::const_iterator sf = klee::SpecialFunctionHandler::begin(), se = klee::SpecialFunctionHandler::end(); sf != se; ++sf) {
if(strcmp(funClass.key.c_str(), sf->name) == 0) {
klee::klee_warning("Special function scanned: '%s', doesNotReturn=%d, hasReturnValue=%d", sf->name, sf->doesNotReturn, sf->hasReturnValue);
}
}
$ chopit.py -f=insertion_sort,insert_ordered,test,__user_main,main,malloc,bubble_sort --inline=memcpy sort.b
[4814d3] KLEE: WARNING: Special function scanned: 'free', doesNotReturn=0, hasReturnValue=0
[4814d3] KLEE: WARNING: Special function scanned: '__assert_fail', doesNotReturn=1, hasReturnValue=0
[4814d3] KLEE: WARNING: Special function scanned: 'exit', doesNotReturn=1, hasReturnValue=0
[4814d3] KLEE: WARNING: Special function scanned: 'klee_make_symbolic', doesNotReturn=0, hasReturnValue=0
[4814d3] KLEE: WARNING: Special function scanned: 'abort', doesNotReturn=1, hasReturnValue=0
[4814d3] KLEE: WARNING: Special function scanned: 'malloc', doesNotReturn=0, hasReturnValue=1
In bc
:
Name | DoesNotReturn | HasReturnValue |
---|---|---|
klee_prefer_cex | 0 | 0 |
klee_check_memory_access | 0 | 0 |
klee_get_valuel | 0 | 1 |
malloc | 0 | 1 |
klee_assume | 0 | 0 |
klee_report_error | 1 | 0 |
klee_warning | 0 | 0 |
free | 0 | 0 |
realloc | 0 | 1 |
klee_warning_once | 0 | 0 |
klee_posix_prefer_cex | 0 | 0 |
klee_mark_global | 0 | 0 |
klee_is_symbolic | 0 | 1 |
klee_make_symbolic | 0 | 0 |
abort | 1 | 0 |
__assert_fail | 1 | 0 |
exit | 1 | 0 |
klee_get_errno | 0 | 1 |
This should probably be used to preserve functions that do not return (and we should preserve klee functions too?). However, this does not solve the problem of custom DNR functions such as yy_fatal_error
.
List of all recognized DNR functions:
addDNR("__assert_rtn", handleAssertFail),
addDNR("__assert_fail", handleAssertFail),
addDNR("_assert", handleAssert),
addDNR("abort", handleAbort),
addDNR("_exit", handleExit),
{ "exit", &SpecialFunctionHandler::handleExit, true, false, true },
addDNR("klee_abort", handleAbort),
addDNR("klee_silent_exit", handleSilentExit),
addDNR("klee_report_error", handleReportError),
Special functions are fixed, but we need to do some additional work to detect DNR functions from the LLVM bytecode + some analysis because we may want to keep may-DNR functions
How?
This can be manually fixed by adding
yy_fatal_error
to the list of kept functionsWhy?
The function
yy_fatal_error
looks like:It is called from here:
The issue seems to be that KLEE does not tolerate an
unreachable
with no!dbg
argument.Proposed fix
Scan all functions to detect those that must end with an
unreachable
instruction. Detect them as "exception" functions and keep them?