Skip to content

Adding support for external C functions that have integer (or empty) args and/or returns - #2363

Merged
bors merged 1 commit into
rust-lang:masterfrom
emarteca:int-function-args-returns
Aug 26, 2022
Merged

bors merged 1 commit into
rust-lang:masterfrom
emarteca:int-function-args-returns

Conversation

@emarteca

@emarteca emarteca commented Jul 12, 2022 •

Copy link
Copy Markdown

Starts addressing @#11

Implementation

Adding support for calling external C functions that have any number of integer arguments (types of integers: i8, i16, i32, i64, u8, u16, u32, u64) and an integer return type (or void).
As suggested in @#11, the libffi crate is used to dispatch the calls to external C functions.

Modifications

Main modifications are to:

  • helper.rs : adding a function call_and_add_external_c_fct_to_context to read the code pointer to the external C function, dispatch the call, and save the return in MIRI internal memory. Handles all conversions between MIRI and C values (using some macros, also defined in this file).
  • foreign_items.rs : handles the calling of call_and_add_external_c_fct_to_context in helper.rs when a foreign item is encountered. Also adds some structs to model C representations of arguments, and the signature of the external C call.

Testing

Adds tests for the following external functions which are now supported:

  • int tests:
    • adds 2 to a provided int (no type of int specified, so autocasts)
    • takes the sum of its 12 arguments (tests stack spill)
    • adds 3 to a 16 bit int
    • adds an i16 to an i64
    • returns -10 as an unsigned int
  • void tests
    • void function that prints from C

Code review

The code in this PR was reviewed by @maurer on another fork -- thanks!

@RalfJung

RalfJung commented Jul 12, 2022 •

Copy link
Copy Markdown
Member

Wow, that's amazing, thanks a ton. :)
(And hello from Cambridge, I'm just across the Charles from Northeastern ;)

One high-level comment based just on the PR summary: I think it'd be better to put this new functionality into new file(s) dedicated to C FFI support. That should help things be more structured.

@LegNeato

Copy link
Copy Markdown
Contributor

This is awesome! It would be nice to have this support as optional / gated...similar to how miri has an option for isolation, it is useful to assert that no c code is called (if you take the extreme view that C = UB 😄 ) .

@oli-obk oli-obk left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This is really cool!

Comment thread src/eval.rs Resolved
Comment thread src/helpers.rs Resolved
Comment thread src/helpers.rs Resolved
Comment thread src/helpers.rs Resolved
Comment thread src/helpers.rs Resolved
Comment thread src/helpers.rs Resolved
Comment thread src/shims/foreign_items.rs Resolved
Comment thread src/shims/foreign_items.rs Resolved
Comment thread tests/compiletest.rs Resolved
Comment thread tests/pass/external_C/int_c_tests.rs Resolved
@RalfJung

Copy link
Copy Markdown
Member

This is awesome! It would be nice to have this support as optional / gated...similar to how miri has an option for isolation, it is useful to assert that no c code is called (if you take the extreme view that C = UB smile ) .

Oh definitely, this should be off-by-default.

@emarteca

Copy link
Copy Markdown
Author

Hey guys, thanks for the quick and thorough review! And hello fellow Boston squad :)
I'll go through these changes and push an updated version of the code soon.

@emarteca
emarteca requested a review from oli-obk July 14, 2022 01:13
@emarteca

Copy link
Copy Markdown
Author

Hey all -- thanks again for the feedback! I've just pushed an updated version of the code, with the main changes being:

  • removed macros: instead now just matching on the pattern and dispatching directly (and similarly for the other macro)
  • modified some of the error handling logic in a few cases as requested by @oli-obk
  • moved all the C FFI supporting functionality into its own file c_ffi_support.rs as requested by @RalfJung
  • updated comment style as requested by @oli-obk

I did not fix Oli's comment about supporting the external C tests only on certain platforms as I'm not sure how best to do this.

@oli-obk oli-obk left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think we'll limit everything to linux for now and then look into expanding the support (and CI coverage) to other platforms in separate PRs. Please set it up so that the shared object is only built on linux for now

Comment thread src/machine.rs Resolved
Comment thread src/machine.rs Resolved
Comment thread src/shims/foreign_items.rs Resolved
@emarteca
emarteca requested review from RalfJung and oli-obk July 14, 2022 22:54
@RalfJung

Copy link
Copy Markdown
Member

It would be great if you could resolve those conflicts by doing a rebase over latest master, so that CI can run on this PR.

Comment thread tests/fail/external_C/bad_args.rs Resolved
@emarteca
emarteca requested a review from oli-obk July 16, 2022 00:51
@emarteca

Copy link
Copy Markdown
Author

It would be great if you could resolve those conflicts by doing a rebase over latest master, so that CI can run on this PR.

It looks like the linux build is failing because the install is trying to download a new dependency abort_on_panic but it's supposed to be in offline mode -- if this is the issue, I'm not sure how to add new dependencies to the CI build.

Error message from CI build log:

./miri install
  Installing miri v0.1.0 (/home/runner/work/miri/miri)
error: failed to compile `miri v0.1.0 (/home/runner/work/miri/miri)`, intermediate artifacts can be found at `/home/runner/work/miri/miri/target`
Caused by:
  failed to download `abort_on_panic v2.0.0`
Caused by:
  attempting to make an HTTP request, but --offline was specified

abort_on_panic is a dependency of libffi: see in Cargo.lock

Comment thread src/c_ffi_support.rs Resolved
@oli-obk

oli-obk commented Jul 16, 2022

Copy link
Copy Markdown
Contributor

It looks like the linux build is failing because the install is trying to download a new dependency abort_on_panic but it's supposed to be in offline mode -- if this is the issue, I'm not sure how to add new dependencies to the CI build.

I think it has been so long since we added a dependency to miri itself, we've since made CI broken in case we do.

@RalfJung I guess we should remove the --offline from the install command and require ppl to pass it themselves if needed?

@RalfJung

Copy link
Copy Markdown
Member

I guess we should remove the --offline from the install command and require ppl to pass it themselves if needed?

I think I added it because at the time I used ./miri install a lot and was annoyed that it spent so much time querying the registry for yanked packages. But maybe that got better, so, yeah, feel free to remove the flag.

@oli-obk

oli-obk commented Jul 16, 2022

Copy link
Copy Markdown
Contributor

Our test suite needs a new feature: //@only-on-host before this can work. I'll add it first thing tomorrow

@emarteca

Copy link
Copy Markdown
Author

Our test suite needs a new feature: //@only-on-host before this can work. I'll add it first thing tomorrow

Thank you! :) 🙏

@RalfJung

RalfJung commented Jul 17, 2022 •

Copy link
Copy Markdown
Member

@oli-obk Can you also make the --offline change part of that PR? Would be good to leave "global infrastructure changes" out of this already large PR.

@bors

bors commented Jul 17, 2022

Copy link
Copy Markdown
Contributor

☔ The latest upstream changes (presumably #2377) made this pull request unmergeable. Please resolve the merge conflicts.

@oli-obk

oli-obk commented Jul 17, 2022

Copy link
Copy Markdown
Contributor

OK, after a rebase everything should work now

@oli-obk oli-obk left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Please rebase instead of merge

@bors

bors commented Jul 18, 2022

Copy link
Copy Markdown
Contributor

☔ The latest upstream changes (presumably #2382) made this pull request unmergeable. Please resolve the merge conflicts.

@emarteca
emarteca force-pushed the int-function-args-returns branch from 3c8fff0 to c5e5754 Compare July 18, 2022 20:41

@RalfJung RalfJung left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I am quite excited by this, but do have a bunch of comments. :)

Comment thread miri Resolved
Comment thread src/bin/miri.rs Resolved
Comment thread src/c_ffi_support.rs Resolved
Comment thread src/c_ffi_support.rs Resolved
Comment thread src/c_ffi_support.rs Resolved
Comment thread tests/external_C/test.c Resolved
Comment thread tests/external_C/test.c Resolved
Comment thread tests/pass/external_C/print_from_c.rs Resolved
Comment thread src/lib.rs Resolved
Comment thread src/shims/foreign_items.rs Resolved
Comment thread src/shims/ffi_support.rs Outdated
// Check if host target == the session target.
// This check needs to happen _after_ we check if the shared object file does not
// export the function: we don't want to throw an error if we are just going to use
// one of the shims.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I disagree. In fact I think the check should be somewhere way earlier, during initiailization. Passing this flag at all for cross-interpretation is an error.

Also throw_ub is definitely wrong here. UB is when the Abstract Machine says you did something wrong. This here is just a misconfiguration of the user, similar to setting -Zmiri-preemption-rate=notafloat.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Ah ok, sounds good.

Comment thread src/machine.rs
preemption_rate: config.preemption_rate,
report_progress: config.report_progress,
since_progress_report: 0,
external_so_lib: config.external_so_file.as_ref().map(|lib_file_path| {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think this is the right spot to error if host != target.

@bors

bors commented Aug 22, 2022

Copy link
Copy Markdown
Contributor

☔ The latest upstream changes (presumably #2441) made this pull request unmergeable. Please resolve the merge conflicts.

@emarteca
emarteca requested a review from oli-obk August 24, 2022 22:18

@oli-obk oli-obk left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

should probably squash commits again after addressing these.

I'm checking out your branch locally now to see if it actually works in x.py

Comment thread src/eval.rs Resolved
Comment thread src/shims/ffi_support.rs Resolved
Comment thread src/shims/ffi_support.rs

#[derive(Debug, Clone)]
/// Enum of supported arguments to external C functions.
pub enum CArg {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should probably document why this intermediate enum is used instead of directly invoking ffi::args and using libffi::high::Arg immediately

@oli-obk

oli-obk commented Aug 25, 2022

Copy link
Copy Markdown
Contributor

I'm checking out your branch locally now to see if it actually works in x.py

All the tests pass! So I guess after my nits, rebase to eliminate any merge commits and squash the other commits.

@bors

bors commented Aug 25, 2022

Copy link
Copy Markdown
Contributor

☔ The latest upstream changes (presumably #2448) made this pull request unmergeable. Please resolve the merge conflicts.

@emarteca
emarteca force-pushed the int-function-args-returns branch from dfdb158 to 88a7882 Compare August 26, 2022 00:55
@emarteca
emarteca requested a review from oli-obk August 26, 2022 00:56
@oli-obk

oli-obk commented Aug 26, 2022

Copy link
Copy Markdown
Contributor

@bors r+

@bors

bors commented Aug 26, 2022

Copy link
Copy Markdown
Contributor

📌 Commit 88a7882 has been approved by oli-obk

It is now in the queue for this repository.

@bors

bors commented Aug 26, 2022

Copy link
Copy Markdown
Contributor

⌛ Testing commit 88a7882 with merge 6418501...

@bors

bors commented Aug 26, 2022

Copy link
Copy Markdown
Contributor

☀️ Test successful - checks-actions
Approved by: oli-obk
Pushing 6418501 to master...

@bors
bors merged commit 6418501 into rust-lang:master Aug 26, 2022
Comment thread .gitignore
Comment on lines +12 to +18
<<<<<<< HEAD
=======
<<<<<<< HEAD
tests/extern-so/libtestlib.so
=======
>>>>>>> master
>>>>>>> 58ba05a0 (C FFI support for functions with int args and returns)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Is this a merge conflict issue?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

yea, I created a fix PR for this

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

oh no -- good catch and thanks for fixing it!

@oli-obk oli-obk mentioned this pull request Aug 26, 2022
bors added a commit that referenced this pull request Aug 26, 2022
Comment thread src/machine.rs
since_progress_report: 0,
external_so_lib: config.external_so_file.as_ref().map(|lib_file_path| {
// Check if host target == the session target.
if option_env!("TARGET") == Some(target_triple) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

So we panic if they are equal? How does that make sense?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is hiding a bug, the comparison doesn't actually work right now.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Fixed by #2511

@RalfJung

Copy link
Copy Markdown
Member

Unless we can quickly find a solution for this licensing issue, we might have to revert this PR (or disable some of its code, at least) in order to be able to update Miri in rustc. :/

@emarteca

emarteca commented Sep 1, 2022 •

Copy link
Copy Markdown
Author

Unless we can quickly find a solution for this licensing issue, we might have to revert this PR (or disable some of its code, at least) in order to be able to update Miri in rustc. :/

Oh yikes 😢
If this turns into a huge problem I guess I can try rebuilding this using a different crate than libffi (that is the dependency that introduces the dependency that's causing this issue).

@saethlin

saethlin commented Sep 1, 2022

Copy link
Copy Markdown
Member

Have we reached out to libffi about this? Maybe there's something easy that can be done on their end?

@RalfJung

RalfJung commented Sep 1, 2022

Copy link
Copy Markdown
Member

Yeah I am trying that: libffi-rs/libffi-rs#58.

@emarteca what alternatives to libffi are there?

@emarteca

emarteca commented Sep 1, 2022

Copy link
Copy Markdown
Author

Yeah I am trying that: tov/libffi-rs#58.

@emarteca what alternatives to libffi are there?

Hmm, libffi is apparently higher level bindings for libffi-sys, which doesn't depend on abort_on_panic, so we could potentially try using libffi-sys directly

@RalfJung

RalfJung commented Sep 1, 2022

Copy link
Copy Markdown
Member

Honestly it seems easier to fork libffi and remove their use of abort_on_panic.

@RalfJung

RalfJung commented Sep 1, 2022

Copy link
Copy Markdown
Member

But I hope libffi-rs/libffi-rs#58 won't take too long so we can avoid any such drastic steps. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-author Status: Waiting for the PR author to address review comments

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants