1 #include <cstdlib>
2 #include <node.h>
3 #include <v8.h>
4 #include <unistd.h>
5 #include <sys/syscall.h>
6 #include <errno.h>
7
8 using namespace v8;
9
10 #if NODE_MAJOR_VERSION == 0
11 #define ARRAY_BUFFER_DATA_OFFSET 23
12 #else
13 #define ARRAY_BUFFER_DATA_OFFSET 31
14 #endif
15
toNative(Local<Value> value)16 intptr_t toNative(Local<Value> value) {
17 if (value.IsEmpty()) {
18 return 0;
19 }
20 if (value->IsArrayBufferView()) {
21 Local<ArrayBufferView> view = Local<ArrayBufferView>::Cast(value);
22 return *reinterpret_cast<intptr_t*>(*reinterpret_cast<char**>(*view->Buffer()) + ARRAY_BUFFER_DATA_OFFSET) + view->ByteOffset(); // ugly hack, because of https://codereview.chromium.org/25221002
23 }
24 if (value->IsArray()) {
25 Local<Array> array = Local<Array>::Cast(value);
26 intptr_t* native = reinterpret_cast<intptr_t*>(malloc(array->Length() * sizeof(intptr_t))); // TODO memory leak
27 for (uint32_t i = 0; i < array->Length(); i++) {
28 native[i] = toNative(array->Get(i));
29 }
30 return reinterpret_cast<intptr_t>(native);
31 }
32 return static_cast<intptr_t>(static_cast<int32_t>(value->ToInteger()->Value()));
33 }
34
Syscall(const FunctionCallbackInfo<Value> & info)35 void Syscall(const FunctionCallbackInfo<Value>& info) {
36 int trap = info[0]->ToInteger()->Value();
37 int r1 = 0, r2 = 0;
38 switch (trap) {
39 case SYS_fork:
40 r1 = fork();
41 break;
42 case SYS_pipe:
43 int fd[2];
44 r1 = pipe(fd);
45 if (r1 == 0) {
46 r1 = fd[0];
47 r2 = fd[1];
48 }
49 break;
50 default:
51 r1 = syscall(
52 trap,
53 toNative(info[1]),
54 toNative(info[2]),
55 toNative(info[3])
56 );
57 break;
58 }
59 int err = 0;
60 if (r1 < 0) {
61 err = errno;
62 }
63 Isolate* isolate = info.GetIsolate();
64 Local<Array> res = Array::New(isolate, 3);
65 res->Set(0, Integer::New(isolate, r1));
66 res->Set(1, Integer::New(isolate, r2));
67 res->Set(2, Integer::New(isolate, err));
68 info.GetReturnValue().Set(res);
69 }
70
Syscall6(const FunctionCallbackInfo<Value> & info)71 void Syscall6(const FunctionCallbackInfo<Value>& info) {
72 int r = syscall(
73 info[0]->ToInteger()->Value(),
74 toNative(info[1]),
75 toNative(info[2]),
76 toNative(info[3]),
77 toNative(info[4]),
78 toNative(info[5]),
79 toNative(info[6])
80 );
81 int err = 0;
82 if (r < 0) {
83 err = errno;
84 }
85 Isolate* isolate = info.GetIsolate();
86 Local<Array> res = Array::New(isolate, 3);
87 res->Set(0, Integer::New(isolate, r));
88 res->Set(1, Integer::New(isolate, 0));
89 res->Set(2, Integer::New(isolate, err));
90 info.GetReturnValue().Set(res);
91 }
92
init(Handle<Object> target)93 void init(Handle<Object> target) {
94 NODE_SET_METHOD(target, "Syscall", Syscall);
95 NODE_SET_METHOD(target, "Syscall6", Syscall6);
96 }
97
98 NODE_MODULE(syscall, init);
99