Merge tag 'v3.14.25' into backport/v3.14.24-ltsi-rc1+v3.14.25/snapshot-merge.wip
[platform/adaptation/renesas_rcar/renesas_kernel.git] / drivers / staging / ktap / runtime / kp_load.c
1 /*
2  * kp_load.c - loader for ktap bytecode chunk file
3  *
4  * This file is part of ktap by Jovi Zhangwei.
5  *
6  * Copyright (C) 2012-2013 Jovi Zhangwei <jovi.zhangwei@gmail.com>.
7  *
8  * Copyright (C) 1994-2013 Lua.org, PUC-Rio.
9  *  - The part of code in this file is copied from lua initially.
10  *  - lua's MIT license is compatible with GPL.
11  *
12  * ktap is free software; you can redistribute it and/or modify it
13  * under the terms and conditions of the GNU General Public License,
14  * version 2, as published by the Free Software Foundation.
15  *
16  * ktap is distributed in the hope it will be useful, but WITHOUT
17  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
19  * more details.
20  *
21  * You should have received a copy of the GNU General Public License along with
22  * this program; if not, write to the Free Software Foundation, Inc.,
23  * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
24  */
25
26 #include <linux/slab.h>
27 #include "../include/ktap_types.h"
28 #include "../include/ktap_ffi.h"
29 #include "ktap.h"
30 #include "kp_load.h"
31 #include "kp_obj.h"
32 #include "kp_str.h"
33 #include "kp_tab.h"
34 #include "kp_vm.h"
35
36 #define KTAPC_TAIL      "\x19\x93\r\n\x1a\n"
37
38 struct load_state {
39         unsigned char *buff;
40         int pos;
41         ktap_state *ks;
42 };
43
44 #define READ_CHAR(S)  (S->buff[S->pos++])
45 #define READ_BYTE(S)  READ_CHAR(S)
46 #define READ_INT(S)  load_int(S)
47 #define READ_NUMBER(S) load_number(S)
48 #define READ_STRING(S)  load_string(S)
49 #define READ_VECTOR(S, dst, size)  \
50         do {    \
51                 memcpy(dst, &S->buff[S->pos], size);    \
52                 S->pos += size; \
53         } while(0)
54
55 #define NEW_VECTOR(S, size)     kp_malloc(S->ks, size)
56 #define FREE_VECTOR(S, v)       kp_free(S->ks, v)
57 #define GET_CURRENT(S)          &S->buff[S->pos]
58 #define ADD_POS(S, size)        S->pos += size
59
60
61 static int load_function(struct load_state *S, ktap_proto *f);
62
63
64 static int load_int(struct load_state *S)
65 {
66         int x;
67
68         READ_VECTOR(S, &x, sizeof(int));
69         return x;
70 }
71
72 static long load_number(struct load_state *S)
73 {
74         long x;
75
76         READ_VECTOR(S, &x, sizeof(ktap_number));
77         return x;
78 }
79
80 static ktap_string *load_string(struct load_state *S)
81 {
82         ktap_string *ts;
83         size_t size;
84
85         size = READ_INT(S);
86
87         if (!size)
88                 return NULL;
89         else {
90                 char *s = GET_CURRENT(S);
91                 ADD_POS(S, size);
92                 /* remove trailing '\0' */
93                 ts = kp_tstring_newlstr(S->ks, s, size - 1);
94                 return ts;
95         }
96 }
97
98
99 static int load_code(struct load_state *S, ktap_proto *f)
100 {
101         int n = READ_INT(S);
102
103         f->sizecode = n;
104         f->code = NEW_VECTOR(S, n * sizeof(ktap_instruction));
105         READ_VECTOR(S, f->code, n * sizeof(ktap_instruction));
106
107         return 0;
108 }
109
110 static int load_constants(struct load_state *S, ktap_proto *f)
111 {
112         int i,n;
113
114         n = READ_INT(S);
115
116         f->sizek = n;
117         f->k = NEW_VECTOR(S, n * sizeof(ktap_value));
118         for (i = 0; i < n; i++)
119                 set_nil(&f->k[i]);
120
121         for (i=0; i < n; i++) {
122                 ktap_value *o = &f->k[i];
123
124                 int t = READ_CHAR(S);
125                 switch (t) {
126                 case KTAP_TNIL:
127                         set_nil(o);
128                         break;
129                 case KTAP_TBOOLEAN:
130                         set_boolean(o, READ_CHAR(S));
131                         break;
132                 case KTAP_TNUMBER:
133                         /*
134                          * todo: kernel not support fp, check double when
135                          * loading
136                          */
137                         set_number(o, READ_NUMBER(S));
138                         break;
139                 case KTAP_TSTRING:
140                         set_string(o, READ_STRING(S));
141                         break;
142                 default:
143                         kp_error(S->ks, "ktap: load_constants: "
144                                         "unknow ktap_value\n");
145                         return -1;
146
147                 }
148         }
149
150         n = READ_INT(S);
151         f->p = NEW_VECTOR(S, n * sizeof(ktap_proto));
152         f->sizep = n;
153         for (i = 0; i < n; i++)
154                 f->p[i] = NULL;
155         for (i = 0; i < n; i++) {
156                 f->p[i] = kp_newproto(S->ks);
157                 if (load_function(S, f->p[i]))
158                         return -1;
159         }
160
161         return 0;
162 }
163
164
165 static int load_upvalues(struct load_state *S, ktap_proto *f)
166 {
167         int i,n;
168
169         n = READ_INT(S);
170         f->upvalues = NEW_VECTOR(S, n * sizeof(ktap_upvaldesc));
171         f->sizeupvalues = n;
172
173         for (i = 0; i < n; i++)
174                 f->upvalues[i].name = NULL;
175
176         for (i = 0; i < n; i++) {
177                 f->upvalues[i].instack = READ_BYTE(S);
178                 f->upvalues[i].idx = READ_BYTE(S);
179         }
180
181         return 0;
182 }
183
184 static int load_debuginfo(struct load_state *S, ktap_proto *f)
185 {
186         int i,n;
187
188         f->source = READ_STRING(S);
189         n = READ_INT(S);
190         f->sizelineinfo = n;
191         f->lineinfo = NEW_VECTOR(S, n * sizeof(int));
192         READ_VECTOR(S, f->lineinfo, n * sizeof(int));
193         n = READ_INT(S);
194         f->locvars = NEW_VECTOR(S, n * sizeof(struct ktap_locvar));
195         f->sizelocvars = n;
196         for (i = 0; i < n; i++)
197                 f->locvars[i].varname = NULL;
198         for (i = 0; i < n; i++) {
199                 f->locvars[i].varname = READ_STRING(S);
200                 f->locvars[i].startpc = READ_INT(S);
201                 f->locvars[i].endpc = READ_INT(S);
202         }
203         n = READ_INT(S);
204         for (i = 0; i < n; i++)
205                 f->upvalues[i].name = READ_STRING(S);
206
207         return 0;
208 }
209
210 static int load_function(struct load_state *S, ktap_proto *f)
211 {
212         f->linedefined = READ_INT(S);
213         f->lastlinedefined = READ_INT(S);
214         f->numparams = READ_BYTE(S);
215         f->is_vararg = READ_BYTE(S);
216         f->maxstacksize = READ_BYTE(S);
217         if (load_code(S, f))
218                 return -1;
219         if (load_constants(S, f))
220                 return -1;
221         if (load_upvalues(S, f))
222                 return -1;
223         if (load_debuginfo(S, f))
224                 return -1;
225
226         return 0;
227 }
228
229
230 #define error(S, why) \
231         kp_error(S->ks, "load failed: %s precompiled chunk\n", why)
232
233 #define N0      KTAPC_HEADERSIZE
234 #define N1      (sizeof(KTAP_SIGNATURE) - sizeof(char))
235 #define N2      N1 + 2
236 #define N3      N2 + 6
237
238 static int load_header(struct load_state *S)
239 {
240         u8 h[KTAPC_HEADERSIZE];
241         u8 s[KTAPC_HEADERSIZE];
242
243         kp_header(h);
244         READ_VECTOR(S, s, KTAPC_HEADERSIZE);
245
246         if (memcmp(h, s, N0) == 0)
247                 return 0;
248         if (memcmp(h, s, N1) != 0)
249                 error(S, "not a");
250         else if (memcmp(h, s, N2) != 0)
251                 error(S, "version mismatch in");
252         else if (memcmp(h, s, N3) != 0)
253                 error(S, "incompatible");
254         else
255                 error(S,"corrupted");
256
257         return -1;
258 }
259
260 #ifdef CONFIG_KTAP_FFI
261 void ffi_set_csym_arr(ktap_state *ks, int cs_nr, csymbol *new_arr);
262
263 static void load_csymbol_func(struct load_state *S, csymbol *cs)
264 {
265         csymbol_func *csf = csym_func(cs);
266         int arg_nr = csymf_arg_nr(csf);
267
268         if (arg_nr > 0) {
269                 csf->arg_ids = NEW_VECTOR(S, arg_nr*sizeof(int));
270                 READ_VECTOR(S, csf->arg_ids, arg_nr*sizeof(int));
271         } else {
272                 csf->arg_ids = NULL;
273         }
274 }
275
276 static void load_csymbol_struct(struct load_state *S, csymbol *cs)
277 {
278         csymbol_struct *csst = csym_struct(cs);
279         int mb_nr = csymst_mb_nr(csst);
280
281         csst->members = NEW_VECTOR(S, mb_nr*sizeof(struct_member));
282         READ_VECTOR(S, csst->members, mb_nr*sizeof(struct_member));
283 }
284
285 static int load_csymbols(struct load_state *S)
286 {
287         csymbol *cs_arr, *cs;
288         int i, csym_nr;
289
290         /* read number of csymbols */
291         csym_nr = READ_INT(S);
292         if (csym_nr <= 0) {
293                 ffi_set_csym_arr(S->ks, 0, NULL);
294                 return 0;
295         }
296
297         /* csymbol size safty check */
298         if (sizeof(csymbol) != READ_INT(S)) {
299                 kp_error(S->ks, "invalid csymbol size in chunk\n");
300                 return -1;
301         }
302
303         cs_arr = NEW_VECTOR(S, sizeof(csymbol)*csym_nr);
304         for (i = 0; i < csym_nr; i++) {
305                 cs = &cs_arr[i];
306                 READ_VECTOR(S, cs, sizeof(csymbol));
307                 switch (cs->type) {
308                 case FFI_FUNC:
309                         load_csymbol_func(S, cs);
310                         break;
311                 case FFI_STRUCT:
312                         load_csymbol_struct(S, cs);
313                         break;
314                 default:
315                         break;
316                 }
317         }
318
319         ffi_set_csym_arr(S->ks, csym_nr, cs_arr);
320
321         return 0;
322 }
323 #else
324 static int load_csymbols(struct load_state *S)
325 {
326         int csym_nr = READ_INT(S);
327
328         /* if FFI is disabled in ktapc, csym_nr should be 0 */
329         if (csym_nr != 0) {
330                  /* skip corrupted csymbol chunk */
331                 int cs_size = READ_INT(S);
332                 ADD_POS(S, cs_size*csym_nr);
333                 kp_error(S->ks, "VM compiled without FFI support!\n");
334                 return -1;
335         }
336
337         return 0;
338 }
339 #endif
340
341 static int verify_code(struct load_state *S, ktap_proto *f)
342 {
343         /* not support now */
344         return 0;
345 }
346
347
348 ktap_closure *kp_load(ktap_state *ks, unsigned char *buff)
349 {
350         struct load_state S;
351         ktap_closure *cl;
352         int ret, i;
353
354         S.ks = ks;
355         S.buff = buff;
356         S.pos = 0;
357
358         ret = load_header(&S);
359         if (ret)
360                 return NULL;
361
362         ret = load_csymbols(&S);
363         if (ret)
364                 return NULL;
365
366         cl = kp_newclosure(ks, 1);
367         if (!cl)
368                 return cl;
369
370         /* put closure on the top, prepare to run with this closure */
371         set_closure(ks->top, cl);
372         incr_top(ks);
373
374         cl->p = kp_newproto(ks);
375         if (load_function(&S, cl->p))
376                 return NULL;
377
378         if (cl->p->sizeupvalues != 1) {
379                 ktap_proto *p = cl->p;
380                 cl = kp_newclosure(ks, cl->p->sizeupvalues);
381                 cl->p = p;
382                 set_closure(ks->top - 1, cl);
383         }
384
385         for (i = 0; i < cl->nupvalues; i++) {  /* initialize upvalues */
386                 ktap_upval *up = kp_newupval(ks);
387                 cl->upvals[i] = up;
388         }
389
390         /* set global table as 1st upvalue of 'f' */
391         if (cl->nupvalues == 1) {
392                 ktap_tab *reg = hvalue(&G(ks)->registry);
393                 const ktap_value *gt = kp_tab_getint(reg, KTAP_RIDX_GLOBALS);
394                 set_obj(cl->upvals[0]->v, gt);
395         }
396
397         verify_code(&S, cl->p);
398
399         return cl;
400 }
401