Home | History | Annotate | Line # | Download | only in src
      1 /*	$NetBSD: ldump.c,v 1.12 2023/06/08 21:12:08 nikita Exp $	*/
      2 
      3 /*
      4 ** Id: ldump.c
      5 ** save precompiled Lua chunks
      6 ** See Copyright Notice in lua.h
      7 */
      8 
      9 #define ldump_c
     10 #define LUA_CORE
     11 
     12 #include "lprefix.h"
     13 
     14 
     15 #ifndef _KERNEL
     16 #include <limits.h>
     17 #include <stddef.h>
     18 #endif /* _KERNEL */
     19 
     20 #include "lua.h"
     21 
     22 #include "lobject.h"
     23 #include "lstate.h"
     24 #include "lundump.h"
     25 
     26 
     27 typedef struct {
     28   lua_State *L;
     29   lua_Writer writer;
     30   void *data;
     31   int strip;
     32   int status;
     33 } DumpState;
     34 
     35 
     36 /*
     37 ** All high-level dumps go through dumpVector; you can change it to
     38 ** change the endianness of the result
     39 */
     40 #define dumpVector(D,v,n)	dumpBlock(D,v,(n)*sizeof((v)[0]))
     41 
     42 #define dumpLiteral(D, s)	dumpBlock(D,s,sizeof(s) - sizeof(char))
     43 
     44 
     45 static void dumpBlock (DumpState *D, const void *b, size_t size) {
     46   if (D->status == 0 && size > 0) {
     47     lua_unlock(D->L);
     48     D->status = (*D->writer)(D->L, b, size, D->data);
     49     lua_lock(D->L);
     50   }
     51 }
     52 
     53 
     54 #define dumpVar(D,x)		dumpVector(D,&x,1)
     55 
     56 
     57 static void dumpByte (DumpState *D, int y) {
     58   lu_byte x = (lu_byte)y;
     59   dumpVar(D, x);
     60 }
     61 
     62 
     63 #ifdef _KERNEL
     64 /* dumpInt Buff Size */
     65 #define DIBS    ((sizeof(size_t) * 8 / 7) + 1)
     66 #endif /* _KERNEL */
     67 #ifndef _KERNEL
     68 /*
     69 ** 'dumpSize' buffer size: each byte can store up to 7 bits. (The "+6"
     70 ** rounds up the division.)
     71 */
     72 #define DIBS    ((sizeof(size_t) * CHAR_BIT + 6) / 7)
     73 #endif /* _KERNEL */
     74 
     75 
     76 static void dumpSize (DumpState *D, size_t x) {
     77   lu_byte buff[DIBS];
     78   int n = 0;
     79   do {
     80     buff[DIBS - (++n)] = x & 0x7f;  /* fill buffer in reverse order */
     81     x >>= 7;
     82   } while (x != 0);
     83   buff[DIBS - 1] |= 0x80;  /* mark last byte */
     84   dumpVector(D, buff + DIBS - n, n);
     85 }
     86 
     87 
     88 static void dumpInt (DumpState *D, int x) {
     89   dumpSize(D, x);
     90 }
     91 
     92 
     93 static void dumpNumber (DumpState *D, lua_Number x) {
     94   dumpVar(D, x);
     95 }
     96 
     97 
     98 static void dumpInteger (DumpState *D, lua_Integer x) {
     99   dumpVar(D, x);
    100 }
    101 
    102 
    103 static void dumpString (DumpState *D, const TString *s) {
    104   if (s == NULL)
    105     dumpSize(D, 0);
    106   else {
    107     size_t size = tsslen(s);
    108     const char *str = getstr(s);
    109     dumpSize(D, size + 1);
    110     dumpVector(D, str, size);
    111   }
    112 }
    113 
    114 
    115 static void dumpCode (DumpState *D, const Proto *f) {
    116   dumpInt(D, f->sizecode);
    117   dumpVector(D, f->code, f->sizecode);
    118 }
    119 
    120 
    121 static void dumpFunction(DumpState *D, const Proto *f, TString *psource);
    122 
    123 static void dumpConstants (DumpState *D, const Proto *f) {
    124   int i;
    125   int n = f->sizek;
    126   dumpInt(D, n);
    127   for (i = 0; i < n; i++) {
    128     const TValue *o = &f->k[i];
    129     int tt = ttypetag(o);
    130     dumpByte(D, tt);
    131     switch (tt) {
    132 #ifndef _KERNEL
    133       case LUA_VNUMFLT:
    134         dumpNumber(D, fltvalue(o));
    135         break;
    136 #endif /* _KERNEL */
    137       case LUA_VNUMINT:
    138         dumpInteger(D, ivalue(o));
    139         break;
    140       case LUA_VSHRSTR:
    141       case LUA_VLNGSTR:
    142         dumpString(D, tsvalue(o));
    143         break;
    144       default:
    145         lua_assert(tt == LUA_VNIL || tt == LUA_VFALSE || tt == LUA_VTRUE);
    146     }
    147   }
    148 }
    149 
    150 
    151 static void dumpProtos (DumpState *D, const Proto *f) {
    152   int i;
    153   int n = f->sizep;
    154   dumpInt(D, n);
    155   for (i = 0; i < n; i++)
    156     dumpFunction(D, f->p[i], f->source);
    157 }
    158 
    159 
    160 static void dumpUpvalues (DumpState *D, const Proto *f) {
    161   int i, n = f->sizeupvalues;
    162   dumpInt(D, n);
    163   for (i = 0; i < n; i++) {
    164     dumpByte(D, f->upvalues[i].instack);
    165     dumpByte(D, f->upvalues[i].idx);
    166     dumpByte(D, f->upvalues[i].kind);
    167   }
    168 }
    169 
    170 
    171 static void dumpDebug (DumpState *D, const Proto *f) {
    172   int i, n;
    173   n = (D->strip) ? 0 : f->sizelineinfo;
    174   dumpInt(D, n);
    175   dumpVector(D, f->lineinfo, n);
    176   n = (D->strip) ? 0 : f->sizeabslineinfo;
    177   dumpInt(D, n);
    178   for (i = 0; i < n; i++) {
    179     dumpInt(D, f->abslineinfo[i].pc);
    180     dumpInt(D, f->abslineinfo[i].line);
    181   }
    182   n = (D->strip) ? 0 : f->sizelocvars;
    183   dumpInt(D, n);
    184   for (i = 0; i < n; i++) {
    185     dumpString(D, f->locvars[i].varname);
    186     dumpInt(D, f->locvars[i].startpc);
    187     dumpInt(D, f->locvars[i].endpc);
    188   }
    189   n = (D->strip) ? 0 : f->sizeupvalues;
    190   dumpInt(D, n);
    191   for (i = 0; i < n; i++)
    192     dumpString(D, f->upvalues[i].name);
    193 }
    194 
    195 
    196 static void dumpFunction (DumpState *D, const Proto *f, TString *psource) {
    197   if (D->strip || f->source == psource)
    198     dumpString(D, NULL);  /* no debug info or same source as its parent */
    199   else
    200     dumpString(D, f->source);
    201   dumpInt(D, f->linedefined);
    202   dumpInt(D, f->lastlinedefined);
    203   dumpByte(D, f->numparams);
    204   dumpByte(D, f->is_vararg);
    205   dumpByte(D, f->maxstacksize);
    206   dumpCode(D, f);
    207   dumpConstants(D, f);
    208   dumpUpvalues(D, f);
    209   dumpProtos(D, f);
    210   dumpDebug(D, f);
    211 }
    212 
    213 
    214 static void dumpHeader (DumpState *D) {
    215   dumpLiteral(D, LUA_SIGNATURE);
    216   dumpByte(D, LUAC_VERSION);
    217   dumpByte(D, LUAC_FORMAT);
    218   dumpLiteral(D, LUAC_DATA);
    219   dumpByte(D, sizeof(Instruction));
    220   dumpByte(D, sizeof(lua_Integer));
    221   dumpByte(D, sizeof(lua_Number));
    222   dumpInteger(D, LUAC_INT);
    223   dumpNumber(D, LUAC_NUM);
    224 }
    225 
    226 
    227 /*
    228 ** dump Lua function as precompiled chunk
    229 */
    230 int luaU_dump(lua_State *L, const Proto *f, lua_Writer w, void *data,
    231               int strip) {
    232   DumpState D;
    233   D.L = L;
    234   D.writer = w;
    235   D.data = data;
    236   D.strip = strip;
    237   D.status = 0;
    238   dumpHeader(&D);
    239   dumpByte(&D, f->sizeupvalues);
    240   dumpFunction(&D, f, NULL);
    241   return D.status;
    242 }
    243 
    244