Skip to content

Instantly share code, notes, and snippets.

@udzura
Created April 4, 2017 06:17
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save udzura/008cc216f6dd48f603adc0526ec41111 to your computer and use it in GitHub Desktop.
mruby src code for LD_PRELOAD object
#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdint.h>
#include <time.h>
#include <mruby.h>
#include <mruby/class.h>
#include <mruby/data.h>
#include <mruby/error.h>
#include <mruby/gc.h>
#include <mruby/irep.h>
struct mrb_simulacre_super_func_table {
int (*clock_gettime)(clockid_t, struct timespec *);
clockid_t clock_gettime_arg1;
struct timespec *clock_gettime_arg2;
};
static mrb_value mrb_simulacre_super(mrb_state *mrb, mrb_value self)
{
struct mrb_simulacre_super_func_table *table;
if (mrb->ud == NULL) {
mrb_raise(mrb, E_RUNTIME_ERROR, "userdata not set");
}
table = (struct mrb_simulacre_super_func_table *)mrb->ud;
table->clock_gettime(table->clock_gettime_arg1, table->clock_gettime_arg2);
return mrb_true_value();
}
static mrb_value mrb_timespec_register(mrb_state *mrb, mrb_value tsrb, struct timespec *tp)
{
void *data = DATA_PTR(tsrb);
if (data) {
mrb_raise(mrb, E_RUNTIME_ERROR, "Register data failed");
}
DATA_PTR(tsrb) = tp;
return tsrb;
}
static struct timespec *mrb_timespec_unregister(mrb_state *mrb, mrb_value tsrb)
{
struct timespec *tp = DATA_PTR(tsrb);
DATA_PTR(tsrb) = NULL;
return tp;
}
static mrb_value mrb_timespec_get_sec(mrb_state *mrb, mrb_value self)
{
struct timespec *tp = DATA_PTR(self);
if (!tp) {
mrb_raise(mrb, E_RUNTIME_ERROR, "Core data not yet set");
}
return mrb_fixnum_value(tp->tv_sec);
}
static mrb_value mrb_timespec_set_sec(mrb_state *mrb, mrb_value self)
{
struct timespec *tp = DATA_PTR(self);
if (!tp) {
mrb_raise(mrb, E_RUNTIME_ERROR, "Core data not yet set");
}
mrb_int newsec;
mrb_get_args(mrb, "i", &newsec);
tp->tv_sec = newsec;
return mrb_fixnum_value(tp->tv_sec);
}
/* ...Doing same for tv_nsec */
/* #include "rblibs.c" or... */
/* dumped in little endian order.
use `mrbc -E` option for big endian CPU. */
#include <stdint.h>
extern const uint8_t libs[];
const uint8_t
#if defined __GNUC__
__attribute__((aligned(4)))
#elif defined _MSC_VER
__declspec(align(4))
#endif
libs[] = {
0x45, 0x54, 0x49, 0x52, 0x30, 0x30, 0x30, 0x33, 0x25, 0xf6, 0x00, 0x00, 0x01, 0x84, 0x4d, 0x41, 0x54, 0x5a,
0x30, 0x30, 0x30, 0x30, 0x49, 0x52, 0x45, 0x50, 0x00, 0x00, 0x01, 0x42, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00,
0x00, 0x51, 0x00, 0x01, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x80, 0x00, 0x44, 0x00,
0x80, 0x00, 0x45, 0x00, 0x80, 0x00, 0x05, 0x00, 0x80, 0x00, 0x05, 0x00, 0x00, 0x01, 0x43, 0x40, 0x80, 0x00,
0xc5, 0x00, 0x80, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x09,
0x53, 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x63, 0x72, 0x65, 0x00, 0x00, 0x08, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x70,
0x65, 0x63, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00,
0x00, 0x00, 0x06, 0x00, 0x80, 0x00, 0x47, 0x40, 0x80, 0x00, 0xc0, 0x00, 0x00, 0x01, 0x46, 0x00, 0x80, 0x00,
0x04, 0x00, 0x80, 0x00, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0d,
0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x67, 0x65, 0x74, 0x74, 0x69, 0x6d, 0x65, 0x00, 0x00, 0x00, 0x00, 0x89,
0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x26, 0x00, 0x00, 0x04, 0x06, 0x00,
0x00, 0x02, 0x83, 0x00, 0xc0, 0x02, 0xa0, 0x00, 0x00, 0x02, 0x83, 0xff, 0xbf, 0x02, 0xb2, 0x40, 0x00, 0x02,
0x99, 0x01, 0x40, 0x02, 0x11, 0x01, 0x00, 0x02, 0x20, 0xc0, 0x00, 0x02, 0x17, 0x03, 0x40, 0x00, 0x06, 0x00,
0x00, 0x02, 0x83, 0x87, 0xd3, 0x02, 0xa0, 0x00, 0x00, 0x02, 0x01, 0x80, 0x80, 0x02, 0x01, 0x00, 0x01, 0x03,
0xa0, 0x00, 0x81, 0x02, 0x07, 0x00, 0x00, 0x02, 0x29, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x05, 0x00, 0x04, 0x72, 0x61, 0x6e, 0x64, 0x00, 0x00, 0x02, 0x3d, 0x3d, 0x00, 0x00, 0x09, 0x53, 0x69,
0x6d, 0x75, 0x6c, 0x61, 0x63, 0x72, 0x65, 0x00, 0x00, 0x05, 0x73, 0x75, 0x70, 0x65, 0x72, 0x00, 0x00, 0x04,
0x73, 0x65, 0x63, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x80, 0x00, 0x29, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x4c, 0x56, 0x41, 0x52, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x02, 0x00, 0x06, 0x63, 0x6c,
0x6b, 0x5f, 0x69, 0x64, 0x00, 0x02, 0x74, 0x73, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0xff, 0xff,
0x00, 0x00, 0x45, 0x4e, 0x44, 0x00, 0x00, 0x00, 0x00, 0x08,
};
static void mrb_simulacre_load_libs(mrb_state *mrb)
{
mrb_load_irep(mrb, libs);
struct RClass *sim = mrb_module_get(mrb, "Simulacre");
mrb_define_module_function(mrb, sim, "super", mrb_simulacre_super, MRB_ARGS_ANY());
struct RClass *ts = mrb_class_get(mrb, "Timespec");
mrb_define_method(mrb, ts, "sec", mrb_timespec_get_sec, MRB_ARGS_NONE());
mrb_define_method(mrb, ts, "sec=", mrb_timespec_set_sec, MRB_ARGS_REQ(1));
}
int clock_gettime(clockid_t clk_id, struct timespec *tp)
{
struct mrb_simulacre_super_func_table table;
int (*super)(clockid_t, struct timespec *);
super = dlsym(RTLD_NEXT, "clock_gettime");
table.clock_gettime = super;
table.clock_gettime_arg1 = clk_id;
table.clock_gettime_arg2 = tp;
mrb_state *mrb = mrb_open();
mrb->ud = (void *)(&table);
mrb_simulacre_load_libs(mrb);
int ai = mrb_gc_arena_save(mrb);
mrb_value mrb_clk_id = mrb_fixnum_value((int)clk_id);
mrb_value mrb_tp = mrb_obj_new(mrb, mrb_class_get(mrb, "Timespec"), 0, NULL);
tp->tv_sec = 0;
tp->tv_nsec = 0;
mrb_timespec_register(mrb, mrb_tp, tp);
mrb_value klass = mrb_obj_value(mrb_module_get(mrb, "Simulacre"));
mrb_value ret = mrb_funcall(mrb, klass, "clock_gettime", 2, mrb_clk_id, mrb_tp);
tp = mrb_timespec_unregister(mrb, mrb_tp);
mrb_gc_arena_restore(mrb, ai);
int code = 0;
if (mrb_nil_p(ret)) {
code = -1;
}
mrb->ud = NULL;
mrb_close(mrb);
return code;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment