1*8e3e3a7aSWarner Losh /* 2*8e3e3a7aSWarner Losh ** $Id: ldump.c,v 2.37 2015/10/08 15:53:49 roberto Exp $ 3*8e3e3a7aSWarner Losh ** save precompiled Lua chunks 4*8e3e3a7aSWarner Losh ** See Copyright Notice in lua.h 5*8e3e3a7aSWarner Losh */ 6*8e3e3a7aSWarner Losh 7*8e3e3a7aSWarner Losh #define ldump_c 8*8e3e3a7aSWarner Losh #define LUA_CORE 9*8e3e3a7aSWarner Losh 10*8e3e3a7aSWarner Losh #include "lprefix.h" 11*8e3e3a7aSWarner Losh 12*8e3e3a7aSWarner Losh 13*8e3e3a7aSWarner Losh #include <stddef.h> 14*8e3e3a7aSWarner Losh 15*8e3e3a7aSWarner Losh #include "lua.h" 16*8e3e3a7aSWarner Losh 17*8e3e3a7aSWarner Losh #include "lobject.h" 18*8e3e3a7aSWarner Losh #include "lstate.h" 19*8e3e3a7aSWarner Losh #include "lundump.h" 20*8e3e3a7aSWarner Losh 21*8e3e3a7aSWarner Losh 22*8e3e3a7aSWarner Losh typedef struct { 23*8e3e3a7aSWarner Losh lua_State *L; 24*8e3e3a7aSWarner Losh lua_Writer writer; 25*8e3e3a7aSWarner Losh void *data; 26*8e3e3a7aSWarner Losh int strip; 27*8e3e3a7aSWarner Losh int status; 28*8e3e3a7aSWarner Losh } DumpState; 29*8e3e3a7aSWarner Losh 30*8e3e3a7aSWarner Losh 31*8e3e3a7aSWarner Losh /* 32*8e3e3a7aSWarner Losh ** All high-level dumps go through DumpVector; you can change it to 33*8e3e3a7aSWarner Losh ** change the endianness of the result 34*8e3e3a7aSWarner Losh */ 35*8e3e3a7aSWarner Losh #define DumpVector(v,n,D) DumpBlock(v,(n)*sizeof((v)[0]),D) 36*8e3e3a7aSWarner Losh 37*8e3e3a7aSWarner Losh #define DumpLiteral(s,D) DumpBlock(s, sizeof(s) - sizeof(char), D) 38*8e3e3a7aSWarner Losh 39*8e3e3a7aSWarner Losh 40*8e3e3a7aSWarner Losh static void DumpBlock (const void *b, size_t size, DumpState *D) { 41*8e3e3a7aSWarner Losh if (D->status == 0 && size > 0) { 42*8e3e3a7aSWarner Losh lua_unlock(D->L); 43*8e3e3a7aSWarner Losh D->status = (*D->writer)(D->L, b, size, D->data); 44*8e3e3a7aSWarner Losh lua_lock(D->L); 45*8e3e3a7aSWarner Losh } 46*8e3e3a7aSWarner Losh } 47*8e3e3a7aSWarner Losh 48*8e3e3a7aSWarner Losh 49*8e3e3a7aSWarner Losh #define DumpVar(x,D) DumpVector(&x,1,D) 50*8e3e3a7aSWarner Losh 51*8e3e3a7aSWarner Losh 52*8e3e3a7aSWarner Losh static void DumpByte (int y, DumpState *D) { 53*8e3e3a7aSWarner Losh lu_byte x = (lu_byte)y; 54*8e3e3a7aSWarner Losh DumpVar(x, D); 55*8e3e3a7aSWarner Losh } 56*8e3e3a7aSWarner Losh 57*8e3e3a7aSWarner Losh 58*8e3e3a7aSWarner Losh static void DumpInt (int x, DumpState *D) { 59*8e3e3a7aSWarner Losh DumpVar(x, D); 60*8e3e3a7aSWarner Losh } 61*8e3e3a7aSWarner Losh 62*8e3e3a7aSWarner Losh 63*8e3e3a7aSWarner Losh static void DumpNumber (lua_Number x, DumpState *D) { 64*8e3e3a7aSWarner Losh DumpVar(x, D); 65*8e3e3a7aSWarner Losh } 66*8e3e3a7aSWarner Losh 67*8e3e3a7aSWarner Losh 68*8e3e3a7aSWarner Losh static void DumpInteger (lua_Integer x, DumpState *D) { 69*8e3e3a7aSWarner Losh DumpVar(x, D); 70*8e3e3a7aSWarner Losh } 71*8e3e3a7aSWarner Losh 72*8e3e3a7aSWarner Losh 73*8e3e3a7aSWarner Losh static void DumpString (const TString *s, DumpState *D) { 74*8e3e3a7aSWarner Losh if (s == NULL) 75*8e3e3a7aSWarner Losh DumpByte(0, D); 76*8e3e3a7aSWarner Losh else { 77*8e3e3a7aSWarner Losh size_t size = tsslen(s) + 1; /* include trailing '\0' */ 78*8e3e3a7aSWarner Losh const char *str = getstr(s); 79*8e3e3a7aSWarner Losh if (size < 0xFF) 80*8e3e3a7aSWarner Losh DumpByte(cast_int(size), D); 81*8e3e3a7aSWarner Losh else { 82*8e3e3a7aSWarner Losh DumpByte(0xFF, D); 83*8e3e3a7aSWarner Losh DumpVar(size, D); 84*8e3e3a7aSWarner Losh } 85*8e3e3a7aSWarner Losh DumpVector(str, size - 1, D); /* no need to save '\0' */ 86*8e3e3a7aSWarner Losh } 87*8e3e3a7aSWarner Losh } 88*8e3e3a7aSWarner Losh 89*8e3e3a7aSWarner Losh 90*8e3e3a7aSWarner Losh static void DumpCode (const Proto *f, DumpState *D) { 91*8e3e3a7aSWarner Losh DumpInt(f->sizecode, D); 92*8e3e3a7aSWarner Losh DumpVector(f->code, f->sizecode, D); 93*8e3e3a7aSWarner Losh } 94*8e3e3a7aSWarner Losh 95*8e3e3a7aSWarner Losh 96*8e3e3a7aSWarner Losh static void DumpFunction(const Proto *f, TString *psource, DumpState *D); 97*8e3e3a7aSWarner Losh 98*8e3e3a7aSWarner Losh static void DumpConstants (const Proto *f, DumpState *D) { 99*8e3e3a7aSWarner Losh int i; 100*8e3e3a7aSWarner Losh int n = f->sizek; 101*8e3e3a7aSWarner Losh DumpInt(n, D); 102*8e3e3a7aSWarner Losh for (i = 0; i < n; i++) { 103*8e3e3a7aSWarner Losh const TValue *o = &f->k[i]; 104*8e3e3a7aSWarner Losh DumpByte(ttype(o), D); 105*8e3e3a7aSWarner Losh switch (ttype(o)) { 106*8e3e3a7aSWarner Losh case LUA_TNIL: 107*8e3e3a7aSWarner Losh break; 108*8e3e3a7aSWarner Losh case LUA_TBOOLEAN: 109*8e3e3a7aSWarner Losh DumpByte(bvalue(o), D); 110*8e3e3a7aSWarner Losh break; 111*8e3e3a7aSWarner Losh case LUA_TNUMFLT: 112*8e3e3a7aSWarner Losh DumpNumber(fltvalue(o), D); 113*8e3e3a7aSWarner Losh break; 114*8e3e3a7aSWarner Losh case LUA_TNUMINT: 115*8e3e3a7aSWarner Losh DumpInteger(ivalue(o), D); 116*8e3e3a7aSWarner Losh break; 117*8e3e3a7aSWarner Losh case LUA_TSHRSTR: 118*8e3e3a7aSWarner Losh case LUA_TLNGSTR: 119*8e3e3a7aSWarner Losh DumpString(tsvalue(o), D); 120*8e3e3a7aSWarner Losh break; 121*8e3e3a7aSWarner Losh default: 122*8e3e3a7aSWarner Losh lua_assert(0); 123*8e3e3a7aSWarner Losh } 124*8e3e3a7aSWarner Losh } 125*8e3e3a7aSWarner Losh } 126*8e3e3a7aSWarner Losh 127*8e3e3a7aSWarner Losh 128*8e3e3a7aSWarner Losh static void DumpProtos (const Proto *f, DumpState *D) { 129*8e3e3a7aSWarner Losh int i; 130*8e3e3a7aSWarner Losh int n = f->sizep; 131*8e3e3a7aSWarner Losh DumpInt(n, D); 132*8e3e3a7aSWarner Losh for (i = 0; i < n; i++) 133*8e3e3a7aSWarner Losh DumpFunction(f->p[i], f->source, D); 134*8e3e3a7aSWarner Losh } 135*8e3e3a7aSWarner Losh 136*8e3e3a7aSWarner Losh 137*8e3e3a7aSWarner Losh static void DumpUpvalues (const Proto *f, DumpState *D) { 138*8e3e3a7aSWarner Losh int i, n = f->sizeupvalues; 139*8e3e3a7aSWarner Losh DumpInt(n, D); 140*8e3e3a7aSWarner Losh for (i = 0; i < n; i++) { 141*8e3e3a7aSWarner Losh DumpByte(f->upvalues[i].instack, D); 142*8e3e3a7aSWarner Losh DumpByte(f->upvalues[i].idx, D); 143*8e3e3a7aSWarner Losh } 144*8e3e3a7aSWarner Losh } 145*8e3e3a7aSWarner Losh 146*8e3e3a7aSWarner Losh 147*8e3e3a7aSWarner Losh static void DumpDebug (const Proto *f, DumpState *D) { 148*8e3e3a7aSWarner Losh int i, n; 149*8e3e3a7aSWarner Losh n = (D->strip) ? 0 : f->sizelineinfo; 150*8e3e3a7aSWarner Losh DumpInt(n, D); 151*8e3e3a7aSWarner Losh DumpVector(f->lineinfo, n, D); 152*8e3e3a7aSWarner Losh n = (D->strip) ? 0 : f->sizelocvars; 153*8e3e3a7aSWarner Losh DumpInt(n, D); 154*8e3e3a7aSWarner Losh for (i = 0; i < n; i++) { 155*8e3e3a7aSWarner Losh DumpString(f->locvars[i].varname, D); 156*8e3e3a7aSWarner Losh DumpInt(f->locvars[i].startpc, D); 157*8e3e3a7aSWarner Losh DumpInt(f->locvars[i].endpc, D); 158*8e3e3a7aSWarner Losh } 159*8e3e3a7aSWarner Losh n = (D->strip) ? 0 : f->sizeupvalues; 160*8e3e3a7aSWarner Losh DumpInt(n, D); 161*8e3e3a7aSWarner Losh for (i = 0; i < n; i++) 162*8e3e3a7aSWarner Losh DumpString(f->upvalues[i].name, D); 163*8e3e3a7aSWarner Losh } 164*8e3e3a7aSWarner Losh 165*8e3e3a7aSWarner Losh 166*8e3e3a7aSWarner Losh static void DumpFunction (const Proto *f, TString *psource, DumpState *D) { 167*8e3e3a7aSWarner Losh if (D->strip || f->source == psource) 168*8e3e3a7aSWarner Losh DumpString(NULL, D); /* no debug info or same source as its parent */ 169*8e3e3a7aSWarner Losh else 170*8e3e3a7aSWarner Losh DumpString(f->source, D); 171*8e3e3a7aSWarner Losh DumpInt(f->linedefined, D); 172*8e3e3a7aSWarner Losh DumpInt(f->lastlinedefined, D); 173*8e3e3a7aSWarner Losh DumpByte(f->numparams, D); 174*8e3e3a7aSWarner Losh DumpByte(f->is_vararg, D); 175*8e3e3a7aSWarner Losh DumpByte(f->maxstacksize, D); 176*8e3e3a7aSWarner Losh DumpCode(f, D); 177*8e3e3a7aSWarner Losh DumpConstants(f, D); 178*8e3e3a7aSWarner Losh DumpUpvalues(f, D); 179*8e3e3a7aSWarner Losh DumpProtos(f, D); 180*8e3e3a7aSWarner Losh DumpDebug(f, D); 181*8e3e3a7aSWarner Losh } 182*8e3e3a7aSWarner Losh 183*8e3e3a7aSWarner Losh 184*8e3e3a7aSWarner Losh static void DumpHeader (DumpState *D) { 185*8e3e3a7aSWarner Losh DumpLiteral(LUA_SIGNATURE, D); 186*8e3e3a7aSWarner Losh DumpByte(LUAC_VERSION, D); 187*8e3e3a7aSWarner Losh DumpByte(LUAC_FORMAT, D); 188*8e3e3a7aSWarner Losh DumpLiteral(LUAC_DATA, D); 189*8e3e3a7aSWarner Losh DumpByte(sizeof(int), D); 190*8e3e3a7aSWarner Losh DumpByte(sizeof(size_t), D); 191*8e3e3a7aSWarner Losh DumpByte(sizeof(Instruction), D); 192*8e3e3a7aSWarner Losh DumpByte(sizeof(lua_Integer), D); 193*8e3e3a7aSWarner Losh DumpByte(sizeof(lua_Number), D); 194*8e3e3a7aSWarner Losh DumpInteger(LUAC_INT, D); 195*8e3e3a7aSWarner Losh DumpNumber(LUAC_NUM, D); 196*8e3e3a7aSWarner Losh } 197*8e3e3a7aSWarner Losh 198*8e3e3a7aSWarner Losh 199*8e3e3a7aSWarner Losh /* 200*8e3e3a7aSWarner Losh ** dump Lua function as precompiled chunk 201*8e3e3a7aSWarner Losh */ 202*8e3e3a7aSWarner Losh int luaU_dump(lua_State *L, const Proto *f, lua_Writer w, void *data, 203*8e3e3a7aSWarner Losh int strip) { 204*8e3e3a7aSWarner Losh DumpState D; 205*8e3e3a7aSWarner Losh D.L = L; 206*8e3e3a7aSWarner Losh D.writer = w; 207*8e3e3a7aSWarner Losh D.data = data; 208*8e3e3a7aSWarner Losh D.strip = strip; 209*8e3e3a7aSWarner Losh D.status = 0; 210*8e3e3a7aSWarner Losh DumpHeader(&D); 211*8e3e3a7aSWarner Losh DumpByte(f->sizeupvalues, &D); 212*8e3e3a7aSWarner Losh DumpFunction(f, NULL, &D); 213*8e3e3a7aSWarner Losh return D.status; 214*8e3e3a7aSWarner Losh } 215*8e3e3a7aSWarner Losh 216