Skip to content

hidva/clayout

master
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Code

Latest commit

 

Git stats

Files

Permalink
Failed to load latest commit information.
Type
Name
Latest commit message
Commit time
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

clayout, translate C++/Rust type into C type with the same memory layout. Generally, clayout is used together with bpftrace.

clayout is developed on ddbug. THANKS FOR ddbug!

Usage

Imagine a scenario where you want to use bpftrace to track the value of S::x during the running of the following program.

#include <stdio.h>
#include <unistd.h>

struct X {
  virtual ~X() {}

  int x1;
};

struct S : public X {
  S() : x(0) {}

  S(const S &other) : x(other.x) {}

  S f(int y, int z) {
    printf("output from a.out: this.x=%d y=%d z=%d\n", x, y, z);
    x += (y + z);
    return *this;
  }

  int x;
};

int main(int argc, char **argv) {
  S s;
  int i = 0;
  while (1) {
    s.f(i, i);
    ++i;
    sleep(1);
    // break;
  }
  return 0;
}

clayout can translate S into a C structure with the same memory layout:

# clayout will generate struct.h, struct.c
$ clayout -i ${binary path} -o struct S
// struct.h
// Generated by hidva/clayout! 大吉大利!
#pragma once
#include <linux/types.h>
struct HidvaStruct2 {
  void** __mem1;
  int x1;
} __attribute__((__packed__));


struct S {
  struct HidvaStruct2 __parent0;
  int x;
} __attribute__((__packed__));

So you can easily write the following bpftrace script:

#include "struct.h"

u:/apsara/zhanyi.ww/tmp/bphtrace/x/trace:_ZN1S1fEii {
  printf("output from bpftrace: ret=%p this.x=%d y=%d z=%d\n", (int32*)arg0, ((struct S*)arg1)->x, arg2, arg3)
}
$ bpftrace  -c ./trace t.bt
Attaching 1 probe...
output from a.out: this.x=0 y=0 z=0
output from bpftrace: ret=0x7ffff3044610 this.x=0 y=0 z=0
output from a.out: this.x=0 y=1 z=1
output from bpftrace: ret=0x7ffff3044610 this.x=0 y=1 z=1

Please note that you may intuitively think that the layout of S is as follows:

struct X {
  void** __mem1;
  int x1;
}

struct S {
  struct X __parent0;
  int x;
}

But actually it is wrong! S::x will reuse the padding part of X in C++!

multi input

clayout supports multiple input files, and type references across files.

// x.h
struct X {
  virtual ~X();

  int x1;
};

struct S : public X {
  S();

  S(const S &other);

  S f(int y, int z);

  int x;
};

// X.cc
#include <stdio.h>
#include "x.h"

X::~X() {}

S::S(): x(0) {}

S::S(const S &other) : x(other.x) {}

S S::f(int y, int z) {
  printf("output from a.out: this.x=%d y=%d z=%d\n", x, y, z);
  x += (y + z);
  return *this;
}

// trace.cc
#include <unistd.h>
#include "x.h"

int main(int argc, char **argv) {
  S s;
  int i = 0;
  while (1) {
    s.f(i, i);
    ++i;
    sleep(1);
  }
  return 0;
}
$ clang++ -fPIC -shared -g -O0 X.cc -o libzh_x.so
$ clang++ -g -O0 trace.cc -o trace -L. -lzh_x

Because of -fstandalone-debug, the trace binary file does not contain any debugging information of X:

$ readelf --debug-dump=info trace
 <1><fc>: Abbrev Number: 13 (DW_TAG_structure_type)
    <fd>   DW_AT_name        : X
    <ff>   DW_AT_declaration : 1

Because there is no debugging information of X in the trace binary file, a placeholder __u8 __unknown_type1[12] is used.

$ clayout -i trace -o output S
// output.h
// Generated by hidva/clayout! 大吉大利!
#pragma once
#include <linux/types.h>

struct S {
  __u8 __unknown_type1[12];
  int x;
} __attribute__((__packed__));

We can use multi input file to get the detail of X:

$ clayout -i trace -i libzh_x.so -o output S
// output.h
// Generated by hidva/clayout! 大吉大利!
#pragma once
#include <linux/types.h>
struct HidvaStruct2 {
  void** __mem1;
  int x1;
} __attribute__((__packed__));


struct S {
  struct HidvaStruct2 __parent0;
  int x;
} __attribute__((__packed__));

About

Translate C++/Rust type into C type with the same memory layout

Topics

Resources

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published