Skip to content

Lazy methods: allow driver program to provide stubs #2124

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

smowton
Copy link
Contributor

@smowton smowton commented Apr 26, 2018

This adds a mechanism for asking languaget instances to produce functions they have not advertised.
DeepTest currently uses it to supply stub function bodies (jbmc replaces the calls, but this results
in a less-useful trace, as it lacks FUNCTION_CALL steps for stubbed functions).

@tautschnig
Copy link
Collaborator

Please check with #1272. Apparently there are N ways of marking something as do-not-display. Let's please not add approach N+1. The concept of "fallback functions" muddles the semantics of goto programs for the benefit of the user interface. At least that's my understanding of this matter...

@smowton
Copy link
Contributor Author

smowton commented Apr 27, 2018

This isn't about hiding symbols or GOTO functions, it's about providing bodies for functions that we don't have source code for.

Example:

class A {
  public int afield;

  static void f() {
    A a = Opaque.getA();
  }
}

If we don't have Opaque.class available, then jbmc currently replaces the callsite (using convert_nondet), so we get a program like:

f:
  A a;
  a = ALLOCATE(sizeof(A));
  a->afield = NONDET(int);

DeepTest on the other hand retains the call, but uses a custom derivative of java_bytecode_languaget that provides a body for the callee, so instead we get:

f:
  A a;
  a = Opaque.getA();

Opaque.getA():
  A ret = ALLOCATE(sizeof(A));
  ret->afield = NONDET(int);
  return ret;

That's more useful than JBMC's approach (I think JBMC should switch to using this method), as it (a) clarifies where the nondet init sequence came from (a call to stub Opaque.getA()), and (b) results in a trace containing FUNCTION_CALL and FUNCTION_RETURN steps for Opaque.getA(), which helps identify stub calls.

In order to do this, lazy_goto_modelt needs to know which languaget to ask to provide the body for Opaque.getA. The usual method of asking each languaget what methods it can provide doesn't work, as we actually don't have bytecode for Opaque.getA, but nontheless we can provide a definition if no other languaget is offering one. Hence we need some way to ask for the method body, even though it isn't a "claimed" method.

@tautschnig
Copy link
Collaborator

Thanks a lot for the elaboration, but can we please have a comprehensive and agreed solution to address #1948, #1949, #2070, #1317, #1585, #1566 (and there might be more)? And of course right now, thanks to @hannes-steffenhagen-diffblue's work, we already have --generate-function-body in the public code base.

Maybe this PR is part of a bigger plan, but if so it would really help to sketch this out to make sure there isn't further fragmentation.

@smowton
Copy link
Contributor Author

smowton commented Apr 27, 2018

Hmmm, okay, to cooperate better with these goto-instrument-oriented function generators / replacers we could instead ask the driver program what to do in this circumstance -- i.e., none of the language frontends could furnish a body for this front-end, so does the driver program want to have a go at providing a GOTO program somehow? Then it would use one of @hannes-steffenhagen-diffblue's passes, or for Java we'd do the nondet-object-graph thing. I can have a go at this solution next week.

@smowton smowton force-pushed the smowton/feature/fallback-function-provider branch from e25524e to ed58067 Compare May 1, 2018 08:11
@smowton smowton requested review from cesaro and mgudemann as code owners May 1, 2018 08:11
@smowton
Copy link
Contributor Author

smowton commented May 1, 2018

@tautschnig pushed an alternative implementation. I think this should satisfy everyone's needs (when using the lazy loading framework): it gives the driver program a chance to provide a body before language_filest (e.g. to replace bodies we could provide, as in @polgreen's block-function patch), but it can also opt to only provide missing functions (the stub use-case).

I'm checking with @peterschrammel whether we can open-source DeepTest's stub generation code; if so I plan to submit a followup PR to get jbmc using this mechanism to provide stubs.

Copy link
Collaborator

@tautschnig tautschnig left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this proposal is good, because it keeps the lazy behaviour contained rather than spreading it across multiple classes and APIs.

Yet I struggle to fully evaluate it (thus sticking with "Comment" rather than "Approve") as there are no regression tests (there may be tests exercising the new code paths already present in the test suite, but no test has observably different behaviour).

@@ -110,6 +129,7 @@ class lazy_goto_modelt : public abstract_goto_modelt
const goto_functionst::goto_functiont &get_goto_function(const irep_idt &id)
override
{

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unintended change?

@smowton smowton force-pushed the smowton/feature/fallback-function-provider branch from ed58067 to 5dc0093 Compare May 1, 2018 08:27
@smowton
Copy link
Contributor Author

smowton commented May 1, 2018

If I get an ok to open a file of deeptest's code I will make jbmc a user of this code, then hopefully its existing tests will suffice to show this is working as intended.

@smowton smowton force-pushed the smowton/feature/fallback-function-provider branch from 5dc0093 to 26355b1 Compare May 1, 2018 08:38
@tautschnig
Copy link
Collaborator

I, for one, am ok for the moment if you tell me that there are tests elsewhere that show this makes a difference and works as intended. Not great, but if you put that note in the commit message then you're committing to it ;-)

Elsewhere it was said that there are current issues in tests elsewhere, so you might, however, have to hold off on this anyway.

@smowton smowton changed the title Language files: add support for a generic fallback provider Lazy methods: allow driver program to provide stubs May 1, 2018
@smowton smowton force-pushed the smowton/feature/fallback-function-provider branch from 26355b1 to 944c4bc Compare May 1, 2018 13:10
@smowton
Copy link
Contributor Author

smowton commented May 2, 2018

This should be tested with Deeptest once it can build with mainline cbmc again.

@smowton smowton requested a review from thk123 as a code owner May 2, 2018 11:33
@smowton
Copy link
Contributor Author

smowton commented May 2, 2018

@tautschnig @thk123 I've obtained permission from @peterschrammel to open a simple version of Deeptest's stub generator and added a commit to use it in jbmc.

The new stub generator, java_bytecode/simple_method_stubbing.h/cpp, has much reduced features compared to Deeptest's version, but is comparable to convert_nondet, which used to provide similar behaviour for jbmc.

If this works this will serve as a template for how Deeptest can integrate its own stub generator with lazy_goto_modelt.

@smowton smowton force-pushed the smowton/feature/fallback-function-provider branch 4 times, most recently from 6d1bce1 to 0ce1064 Compare May 9, 2018 15:07
@smowton
Copy link
Contributor Author

smowton commented May 9, 2018

Copy link
Collaborator

@tautschnig tautschnig left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Various, mostly stylistic notes.

#define CPROVER_JAVA_BYTECODE_SIMPLE_METHOD_STUBBING_H

#include <util/symbol_table_base.h>
#include <java_bytecode/java_bytecode_language.h>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Forward declarations would suffice.

{
code_blockt new_instructions;
const code_typet &required_type = to_code_type(symbol.type);
namespacet ns(symbol_table);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is that actually used in this method?

#include <util/namespace.h>
#include <util/prefix.h>
#include <util/fresh_symbol.h>
#include <util/invariant_utils.h>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit pick: lexicographic sorting.


#include <util/std_expr.h>
#include <util/std_code.h>
#include <util/pointer_offset_size.h>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this needed/used?

#include <util/std_code.h>
#include <util/pointer_offset_size.h>
#include <util/namespace.h>
#include <util/prefix.h>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems unused.

synthesized_source_location,
ID_java,
symbol_table);
init_symbol.type = this_type;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems unnecessary?!

synthesized_source_location,
ID_java,
symbol_table);
to_return_symbol.type = required_return_type;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems unnecessary?!

if(sym.value.id()!=ID_nil)
return;
if(sym.type.id()!=ID_code)
return;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit pick: the use of && would make this code more concise and would express what is the condition instead of saying when not to do this. Like this:
if(!sym.is_type && sym.value.id() == ID_nil && sym.type.id() == ID_code) create_method_stub(...); (while moving the two sym.name to the top to clearly mark the exceptional case.

void java_simple_method_stubst::check_method_stub(
const irep_idt &symname)
{
const symbolt &sym=*symbol_table.lookup(symname);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a newly added file, so should be made clang-format correct.

@tautschnig tautschnig assigned smowton and unassigned tautschnig May 14, 2018
This provides a hook for the driver program to either replace a method outright, or to provide a
stub implementation when a function body cannot be provided by the language frontend (language_filest).
@smowton smowton force-pushed the smowton/feature/fallback-function-provider branch from 0ce1064 to 7c7c64d Compare May 14, 2018 15:26
@smowton
Copy link
Contributor Author

smowton commented May 14, 2018

@tautschnig all changes applied.

#include <util/irep.h>

class message_handlert;
class object_factory_parameterst;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some compilers insist that this should be a struct and thus make the Travis build fail.

@tautschnig
Copy link
Collaborator

clang-format has a lot to criticise - I'd suggest to make newly added code clang-format-clean.

smowton added 2 commits May 15, 2018 12:10
This generates simple stub bodies using the same method as convert_nondet, but creates
the stubs out-of-line rather than inline. That adds support for nondet constructors, which
jbmc previously ignored.
This uses lazy_goto_modelt's support for driver programs supplying method replacements
to provide stub implementations of methods whose code is unavailable.
@smowton smowton force-pushed the smowton/feature/fallback-function-provider branch from 7c7c64d to cd04e70 Compare May 15, 2018 11:11
@smowton
Copy link
Contributor Author

smowton commented May 15, 2018

Fixed the compile bug. My local clang-format (LLVM 6.0) appears to disagree with the version running on Travis (LLVM 3.7), so I'm inclined to ignore them both.

@smowton smowton merged commit 8941567 into diffblue:develop May 15, 2018
NathanJPhillips pushed a commit to NathanJPhillips/cbmc that referenced this pull request Aug 22, 2018
31ef182 Merge pull request diffblue#2208 from diffblue/cleanout-goto-programs
0e84d3e Merge pull request diffblue#2195 from smowton/smowton/feature/smarter-reachability-slicer
c801126 Merge pull request diffblue#2209 from diffblue/travis-no-osx-g++
3487bf7 Reachability slicer: mark reachable code more precisely
85e8451 Merge pull request diffblue#2066 from tautschnig/bv-endianness
5e5eafb Merge pull request diffblue#2191 from smowton/smowton/feature/java-fatal-assertions
8a68ab8 remove g++ build on OS X; this is identical to the clang++ build
48e5b25 Amend faulty long-string test
3f718ba Java: make null-pointer and similar checks fatal
821eb1d remove basic_blocks and goto_program_irep
d87c2db Merge pull request diffblue#2203 from diffblue/typed-lookup
d77dea3 strongly type the lookup() methods in namespacet
2382f27 Merge pull request diffblue#2193 from martin-cs/feature/correct-instruction-documentation
c314272 Merge pull request diffblue#2181 from diffblue/format-expr-constants
514a0a5 Merge pull request diffblue#2167 from diffblue/parse_unwindset_options
0102452 move escape(s) to string_utils
f1b6174 use unwindsett in goto-instrument
dcc907a introduce unwindsett for unwinding limits
10aeae8 format_expr now does index, c_bool constants, string constants
92b92d6 Correct the documentation of ASSERT : it does not alter control flow.
a11add8 Expand the documentation of the goto-program instructions.
a06503b Merge pull request diffblue#2197 from tautschnig/fix-help
05e4bc3 Remove stray whitespace previously demanded by clang-format
3261f4d Fix help output of --generate-function-body-options
7c67b23 Merge pull request diffblue#2110 from tautschnig/type-mismatch-exception
18fb262 Merge pull request diffblue#2025 from tautschnig/stack-depth-fix
9191b6a Merge pull request diffblue#2199 from tautschnig/simplifier-typing
f99e631 Merge pull request diffblue#2198 from tautschnig/fix-test-desc
1a79a11 stack depth instrumentation: __CPROVER_initialize may be empty
a7690ba Merge pull request diffblue#2185 from smowton/smowton/fix/tolerate-ts18661-types
fc02e8f Restore returns before writing the simplified binary
49333eb Make restore_returns handle simplified programs
46f7987 Fix perl regular expressioons in regression test descriptions
9fe432b Merge pull request diffblue#1899 from danpoe/sharing-map-catch-unit-tests
9cc6aae Merge pull request diffblue#2081 from hannes-steffenhagen-diffblue/floating_point_simplificiation
da19abe Tolerate TS 18661 (_Float32 et al) types
a055454 Try all rounding modes when domain is unknown
5f7bc15 Add float support to constant propagator domain
3dc2244 Move adjust_float_expressions to goto-programs
06d8bea Merge pull request diffblue#2187 from diffblue/move-convert-nondet
6d8c3fa Merge pull request diffblue#2189 from thk123/bugfix/json-parser-restart
2ad157f Merge pull request diffblue#2186 from smowton/smowton/fix/call-graph-uninit-field
cd54ad7 Corrected state persistence in the json parser
4447be0 Fix uninitialised collect_callsites field in call_grapht
ead0aa3 Merge pull request diffblue#2188 from smowton/smowton/fix/init-string-types-without-refine-strings
57988fc Fix String type initialisation when --refine-strings is not active
6a76aff Move convert_nondet to java_bytecode
ac6eb21 Merge pull request diffblue#1858 from danpoe/dependence-graph-fix
10b8b09 Merge pull request diffblue#2011 from thomasspriggs/final_classes
a154593 Merge pull request diffblue#2087 from danpoe/feature/small-map
7002909 More dependence graph tests
66263ea Make dependence graph merge() return true when abstract state changes
3aa6dca Control dependency computation fix
a408423 Simplified state merging in the dependence graph
0315816 Merge pull request diffblue#2180 from thomasspriggs/json_id2string
8941567 Merge pull request diffblue#2124 from smowton/smowton/feature/fallback-function-provider
cd04e70 JBMC: use simple method stubbing pass
a6b2cda Add Java simple method stubbing pass
ec1127c Lazy goto model: hook for driver program to replace or stub functions
b6a4382 Remove `id2string` from inside calls to the `json_stringt` constructor.
b673ebb Add storage of final modifier status of java classes in `java_class_typet`.
a2ad909 Small map
808dade Provide suitable diagnostics for equality-without-matching-types
89cf6fe Throw appropriate exceptions when converting constraints
2ae66c2 Produce a proper error message when catching a std::runtime_error at top level
e7b3ade Workaround for Visual Studio loss of CV qualifier bug
1f661f5 Move sharing map and sharing node unit tests to util
47463a3 Use std::size_t instead of unsigned in the sharing map
3e22217 Sharing map documentation
e54f740 Fix sharing map compiler warnings
bcc489c Move sharing map unit tests to catch
34114b8 Use a specialised endianness map for flattening

git-subtree-dir: cbmc
git-subtree-split: 31ef182
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants