Created
April 4, 2017 06:17
Star
You must be signed in to star a gist
mruby src code for LD_PRELOAD object
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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