Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

dead-instrumenter

Package Overview
Dependencies
Maintainers
1
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

dead-instrumenter

A C/C++ code instrumenter used in DEAD

  • 0.3.3
  • PyPI
  • Socket score

Maintainers
1

dead-instrument is the instrumenter used in DEAD.

It inserts markers (as function calls) in C or C++ source code to enable differential testing:

  1. Instrument a program.
  2. Compile it with two or more compilers (or compiler versions, or optimization levels, etc).
  3. For each output: the markers whose corresponding calls are still present in the generated assembly are alive, the remaining are dead.
  4. Differential testing: compare the sets of alive and dead markers across outputs.

There are two kinds of markers supported:

  • DCE (Dead Code Elimination) Markers
  • VR (Value Range) Markers

A DCEMarker tests if a compiler dead code eliminates a piece of code (basic block). For example,

if (Cond){
  DCEMarker0_();
  STMT0;
  STMT1;
  //...
}

If call DCEMarker0_(); is not present in the generated assembly code then the compiler determined that Cond must always be false and therefore the body of this if statement is dead.

A VRMarker tests if a compiler can determine subsets of the value ranges of variables, for example:

if (a <= C)
    VRMarker0_();

If call VRMarker0_(); is not present in the generated assembly code then the compiler determined that a's value is always a > C. Currently only integer variables are instrumented.

To build just the clang tool

Prerequisites: cmake, make, clang/llvm 13/14.

mkdir build
cd build
cmake .. 
cmake --build . [--parallel]
cmake --install . --prefix=/where/to/install/
Usage
cat test.c
int foo(int a) {
    if (a == 0)
        return 1;
    else {
        a = 5;
    }

    return a;
}


dead-instrument test.c --


cat test.c | clang-format
#if defined DisableDCEMarker0_
#define DCEMARKERMACRO0_ ;
#elif defined UnreachableDCEMarker0_
#define DCEMARKERMACRO0_ __builtin_unreachable();
#else
#define DCEMARKERMACRO0_ DCEMarker0_();
void DCEMarker0_(void);
#endif
#if defined DisableDCEMarker1_
#define DCEMARKERMACRO1_ ;
#elif defined UnreachableDCEMarker1_
#define DCEMARKERMACRO1_ __builtin_unreachable();
#else
#define DCEMARKERMACRO1_ DCEMarker1_();
void DCEMarker1_(void);
#endif
int foo(int a) {
  if (a == 0)
  {
    DCEMARKERMACRO1_
    return 1;
  }
  else {
    DCEMARKERMACRO0_
    a = 5;
  }

  return a;
}

Individual markers can be disabled or turned into unreachables (useful for helping the compiler optimize parts known to be dead):

gcc -E -P -DDisableDCEMarker0_ -DUnreachableDCEMarker1_ test.c | clang-format
int foo(int a) {
  if (a == 0) {
    __builtin_unreachable();
    return 1;
  } else {
    ;
    a = 5;
  }
  return a;
}

Passing --ignore-functions-with-macros to dead-instrument will cause it to ignore any functions that contain macro expansions.

Value range markers can be emitted instead by using --mode=vr:

cat test.c
int foo(int a) {
  if (a == 0)
    return 1;
  return 0;
}

dead-instrument --mode=vr test.c --

cat test.c | clang-format 
#if defined DisableVRMarkerLE0_
#define VRMARKERMACROLE0_(VAR)
#elif defined UnreachableVRMarkerLE0_
#define VRMARKERMACROLE0_(VAR)         \
  if ((VAR) <= VRMarkerConstantLE0_)   \
    __builtin_unreachable();
#else
#define VRMARKERMACROLE0_(VAR)         \
  if ((VAR) <= VRMarkerConstantLE0_)   \
    VRMarkerLE0_();
void VRMarkerLE0_(void);
#endif
#ifndef VRMarkerConstantLE0_
#define VRMarkerConstantLE0_ 0
#endif
#if defined DisableVRMarkerGE0_
#define VRMARKERMACROGE0_(VAR)
#elif defined UnreachableVRMarkerGE0_
#define VRMARKERMACROGE0_(VAR)         \
  if ((VAR) >= VRMarkerConstantGE0_)   \
    __builtin_unreachable();
#else
#define VRMARKERMACROGE0_(VAR)         \
  if ((VAR) >= VRMarkerConstantGE0_)   \
    VRMarkerGE0_();
void VRMarkerGE0_(void);
#endif
#ifndef VRMarkerConstantGE0_
#define VRMarkerConstantGE0_ 0
#endif
int foo(int a) {
  VRMARKERMACROLE0_(a)
  VRMARKERMACROGE0_(a)
  if (a == 0)
    return 1;
  return 0;
}

The ranges that each marker test can be adjucted via macros and individual markers can be disabled or turned into unreachables:

gcc -E -P -DDisableVRMarkerLE0_ -DVRMarkerConstantGE0_=8 test.c | clang-format
void VRMarkerGE0_(void);
int foo(int a) {

  if ((a) >= 8)
    VRMarkerGE0_();
  if (a == 0)
    return 1;
  return 0;
}
Python wrapper

pip install dead-instrumenter

To use the instrumenter in python import from dead_instrumenter.instrumenter import instrument_program: instrument_program(program: diopter.SourceProgram, ignore_functions_with_macros: bool) -> InstrumentedProgram.

Building the python wrapper
Local build
./build_python_wheel_local.sh #this will build the current branch
pip install .
Docker based build
docker run --rm -e REVISION=REV -v `pwd`:/io theodort/manylinux-with-llvm:latest /io/build_python_wheel_docker.sh

This will build multiple wheels for REV with multiple python versions. The output is stored in the wheelhouse directory. The docker image is based on https://github.com/thetheodor/manylinux-with-llvm.

FAQs


Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc