3 #define DONT_INCLUDE_SYSCALL_NAMES 1
13 # include <spawn.h> // posix_spawn
18 #define DEBUG(str, x...) Debug(str, x)
20 #define DEBUG(...) do{}while(0)
23 #define assert(cnd) do{ \
25 fprintf(stderr, "%s:%i - assert failed - " #cnd"\n", __FILE__, __LINE__);\
37 FILE *gaSyscall_LocalFPs[MAX_FPS];
40 const char *ReadEntry(tRequestValue *Dest, void *DataDest, void **PtrDest, const char *ArgTypes, va_list *Args)
44 int direction = 0; // 0: Invalid, 1: Out, 2: In, 3: Out
49 while(*ArgTypes && *ArgTypes == ' ') ArgTypes ++;
50 if( *ArgTypes == '\0' ) return ArgTypes;
52 // DEBUG("ArgTypes = '%s'", ArgTypes);
57 default: // Defaults to output
58 case '>': direction = 1; break;
59 case '<': direction = 2; break;
60 case '?': direction = 3; break;
65 while(*ArgTypes && *ArgTypes == ' ') ArgTypes ++;
66 if( *ArgTypes == '\0' ) return ArgTypes;
74 if( direction != 1 ) {
75 Warning("ReadEntry: Recieving an integer is not defined");
79 val32 = va_arg(*Args, uint32_t);
81 Dest->Type = ARG_TYPE_INT32;
82 Dest->Length = sizeof(uint32_t);
86 *(uint32_t*)DataDest = val32;
91 if( direction != 1 ) {
92 fprintf(stderr, "ReadEntry: Recieving an integer is not defined\n");
96 val64 = va_arg(*Args, uint64_t);
98 Dest->Type = ARG_TYPE_INT64;
99 Dest->Length = sizeof(uint64_t);
102 *(uint64_t*)DataDest = val64;
106 // Input string makes no sense!
107 if( direction != 1 ) {
108 fprintf(stderr, "ReadEntry: Recieving a string is not defined\n");
112 str = va_arg(*Args, char*);
114 Dest->Type = ARG_TYPE_STRING;
115 Dest->Length = strlen(str) + 1;
120 memcpy(DataDest, str, Dest->Length);
123 // Data (special handling)
125 len = va_arg(*Args, size_t);
126 str = va_arg(*Args, char*);
128 // Save the pointer for later
129 if( PtrDest ) *PtrDest = str;
131 // Create parameter block
132 Dest->Type = ARG_TYPE_DATA;
133 Dest->Length = str ? len : 0;
136 Dest->Flags |= ARG_FLAG_RETURN;
141 if( DataDest && str )
142 memcpy(DataDest, str, len);
145 Dest->Flags |= ARG_FLAG_ZEROED;
159 * Whitespace is ignored
160 * >i: Input Integer (32-bits)
161 * >I: Input Long Integer (64-bits)
163 * >d: Input Buffer (Preceded by valid size)
164 * <I: Output long integer
165 * <d: Output Buffer (Preceded by valid size)
166 * ?d: Bi-directional buffer (Preceded by valid size), buffer contents
169 uint64_t _Syscall(int SyscallID, const char *ArgTypes, ...)
172 int paramCount, dataLength;
173 int retCount = 2, retLength = sizeof(uint64_t) + sizeof(uint32_t);
174 void **retPtrs; // Pointers to return buffers
182 // printf("&tRequestHeader->Params = %i\n", offsetof(tRequestHeader, Params));
183 // printf("&tRequestValue->Flags = %i\n", offsetof(tRequestValue, Flags));
184 // printf("&tRequestValue->Length = %i\n", offsetof(tRequestValue, Length));
187 va_start(args, ArgTypes);
193 tRequestValue tmpVal;
195 str = ReadEntry(&tmpVal, NULL, NULL, str, &args);
197 fprintf(stderr, "syscalls.c: ReadEntry failed (SyscallID = %i)\n", SyscallID);
201 if( !(tmpVal.Flags & ARG_FLAG_ZEROED) )
202 dataLength += tmpVal.Length;
204 if( tmpVal.Flags & ARG_FLAG_RETURN ) {
205 retLength += tmpVal.Length;
211 dataLength += sizeof(tRequestHeader) + paramCount*sizeof(tRequestValue);
212 retLength += sizeof(tRequestHeader) + retCount*sizeof(tRequestValue);
215 retPtrs = malloc( sizeof(void*) * (retCount+1) );
216 if( dataLength > retLength)
217 req = malloc( dataLength );
219 req = malloc( retLength );
220 req->ClientID = 0; //< Filled later
221 req->CallID = SyscallID;
222 req->NParams = paramCount;
223 req->MessageLength = dataLength;
224 dataPtr = &req->Params[paramCount];
226 // Fill `output` and `input`
227 va_start(args, ArgTypes);
229 // - re-zero so they can be used as indicies
234 str = ReadEntry(&req->Params[paramCount], dataPtr, &retPtrs[retCount], str, &args);
237 if( !(req->Params[paramCount].Flags & ARG_FLAG_ZEROED) )
238 dataPtr += req->Params[paramCount].Length;
239 if( req->Params[paramCount].Flags & ARG_FLAG_RETURN )
246 // --- Send syscall request
247 if( SendRequest(req, dataLength, retLength) < 0 ) {
248 fprintf(stderr, "syscalls.c: SendRequest failed (SyscallID = %i)\n", SyscallID);
252 dataPtr = (void*)&req->Params[req->NParams];
253 assert(req->NParams >= 2);
255 assert(req->Params[0].Type == ARG_TYPE_INT64);
256 assert(req->Params[0].Length == sizeof(uint64_t));
257 retValue = *(uint64_t*)dataPtr;
258 dataPtr += sizeof(uint64_t);
260 assert(req->Params[1].Type == ARG_TYPE_INT32);
261 assert(req->Params[1].Length == sizeof(uint32_t));
262 acess__errno = *(uint32_t*)dataPtr;
263 dataPtr += sizeof(uint32_t);
265 // Write changes to buffers
266 if( req->NParams - 2 != retCount ) {
267 fprintf(stderr, "syscalls.c: Return count inbalance (%i - 1 != exp %i) [Call %i]\n",
268 req->NParams, retCount, SyscallID);
272 for( i = 2; i < req->NParams; i ++ )
276 printf("Return Data %i: (%i)", i, req->Params[i].Length);
277 for( j = 0; j < req->Params[i].Length; j ++ )
278 printf(" %02x", ((uint8_t*)dataPtr)[j]);
281 assert( req->Params[i].Type == ARG_TYPE_DATA );
282 memcpy( retPtrs[retCount++], dataPtr, req->Params[i].Length );
283 dataPtr += req->Params[i].Length;
289 DEBUG(": %i 0x%llx", SyscallID, retValue);
295 int native_open(const char *Path, int Flags)
298 for(ret = 0; ret < MAX_FPS && gaSyscall_LocalFPs[ret]; ret ++ ) ;
299 if(ret == MAX_FPS) return -1;
300 // TODO: Handle directories
301 gaSyscall_LocalFPs[ret] = fopen(&Path[4], "r+");
302 if(!gaSyscall_LocalFPs[ret]) return -1;
306 void native_close(int FD)
308 fclose( gaSyscall_LocalFPs[FD] );
309 gaSyscall_LocalFPs[FD] = NULL;
312 size_t native_read(int FD, void *Dest, size_t Bytes)
314 return fread( Dest, Bytes, 1, gaSyscall_LocalFPs[FD] );
317 size_t native_write(int FD, const void *Src, size_t Bytes)
319 return fwrite( Src, Bytes, 1, gaSyscall_LocalFPs[FD] );
322 int native_seek(int FD, int64_t Ofs, int Dir)
325 return fseek( gaSyscall_LocalFPs[FD], Ofs, SEEK_CUR );
327 return fseek( gaSyscall_LocalFPs[FD], Ofs, SEEK_SET );
329 return fseek( gaSyscall_LocalFPs[FD], Ofs, SEEK_END );
332 uint64_t native_tell(int FD)
334 return ftell( gaSyscall_LocalFPs[FD] );
337 int native_execve(const char *filename, const char *const argv[], const char *const envp[])
340 ret = execve(filename, (void*)argv, (void*)envp);
341 perror("native_execve");
345 int native_spawn(const char *filename, const char *const argv[], const char *const envp[])
350 rv = _spawnve(_P_NOWAIT, filename, argv, envp);
352 rv = posix_spawn(NULL, filename, NULL, NULL, (void*)argv, (void*)envp);