facebookexperimental / MIRAI

Rust mid-level IR Abstract Interpreter

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

`libc::sysctlbyname` doesn't show up in call graph output

cdstanford opened this issue · comments

Issue

Hi, thank you for providing access to this excellent tool! In the following minimal example, libc::sysconf shows up in the call graph output, but libc::sysctlbyname doesn't. I haven't been able to track down why:

use core::ffi::CStr;
use core::ptr;

fn main() {
    unsafe {
        libc::sysconf(57);
        let hw_physicalcpu = CStr::from_bytes_with_nul(b"hw.physicalcpu\0").unwrap();
        libc::sysctlbyname(
            hw_physicalcpu.as_ptr(),
            ptr::null_mut(),
            ptr::null_mut(),
            ptr::null_mut(),
            0,
        );
    }
}

Here's the config.json file we're using to generate the call graph:

{
    "call_sites_output_path": "call_sites.json",
    "dot_output_path": "graph.dot",
    "reductions": [],
    "included_crates": [],
    "datalog_config": {
        "ddlog_output_path": "graph.dat",
        "type_map_output_path": "types.json",
        "datalog_backend": "DifferentialDatalog"
    }
}

Steps to Reproduce

  • Run cargo init in a new folder, then replace the main.rs file with the above code.
  • Add the config.json file to this folder
  • Set MIRAI_FLAGS to f"--call_graph_config config.json"
  • Then run cargo mirai and inspect the output graph.dot

Expected Behavior

In the graph.dot output (and call_sites.json as well), I expect to see a main function with call graph edges to both libc::sysconf and libc::sysctlbyname (as well as another edge, to CStr::from_bytes_with_nul).

Actual Results

Here's the call graph that is generated. It contains two of the expected edges, but libc::sysctlbyname is missing:

graph

And here's the raw graph.dot file:

digraph {
    0 [ label = "\"num_cpus_minimal::main\"" ]
    1 [ label = "\"libc::unix::{extern#1}::sysconf\"" ]
    2 [ label = "\"core::ffi::c_str::{impl#5}::from_bytes_with_nul\"" ]
    0 -> 1 [ ]
    0 -> 2 [ ]
}

I also took a look at call_sites.json, which contains an entry for libc.unix.foreign_1.sysconf, but nothing for sysctlbyname.

Environment

This is (possibly) MacOS specific code; I've only tested it on a mac (MacOS Monterey M1). But I think the libc function calls should show up regardless.

Rust version (rustc --version): rustc 1.64.0 (a55dd71d5 2022-09-19)

Possible explanations

I thought this might be due to code inlining, but I made a quick test file with #[inline(always)] and #[inline(never)] annotations, and both types of function calls show up.
It occurs to me that the syscall could be being optimized out prior to the MIR level, but that seems unlikely for this case.

Thank you and really appreciate any help that you can provide to diagnose this!

@hermanventer Thank you for responding and fixing this, much appreciated! We'll check out the latest commit.