Coverage Report

Created: 2024-04-23 06:32

/src/testdir/build/lua-master/source/ldump.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
** $Id: ldump.c $
3
** save precompiled Lua chunks
4
** See Copyright Notice in lua.h
5
*/
6
7
#define ldump_c
8
#define LUA_CORE
9
10
#include "lprefix.h"
11
12
13
#include <limits.h>
14
#include <stddef.h>
15
16
#include "lua.h"
17
18
#include "lgc.h"
19
#include "lobject.h"
20
#include "lstate.h"
21
#include "ltable.h"
22
#include "lundump.h"
23
24
25
typedef struct {
26
  lua_State *L;
27
  lua_Writer writer;
28
  void *data;
29
  lu_mem offset;  /* current position relative to beginning of dump */
30
  int strip;
31
  int status;
32
  Table *h;  /* table to track saved strings */
33
  lua_Integer nstr;  /* counter for counting saved strings */
34
} DumpState;
35
36
37
/*
38
** All high-level dumps go through dumpVector; you can change it to
39
** change the endianness of the result
40
*/
41
2.66M
#define dumpVector(D,v,n) dumpBlock(D,v,(n)*sizeof((v)[0]))
42
43
3.17k
#define dumpLiteral(D, s) dumpBlock(D,s,sizeof(s) - sizeof(char))
44
45
46
/*
47
** Dump the block of memory pointed by 'b' with given 'size'.
48
** 'b' should not be NULL, except for the last call signaling the end
49
** of the dump.
50
*/
51
2.72M
static void dumpBlock (DumpState *D, const void *b, size_t size) {
52
2.72M
  if (D->status == 0) {  /* do not write anything after an error */
53
2.72M
    lua_unlock(D->L);
54
2.72M
    D->status = (*D->writer)(D->L, b, size, D->data);
55
2.72M
    lua_lock(D->L);
56
2.72M
    D->offset += size;
57
2.72M
  }
58
2.72M
}
59
60
61
/*
62
** Dump enough zeros to ensure that current position is a multiple of
63
** 'align'.
64
*/
65
69.5k
static void dumpAlign (DumpState *D, int align) {
66
69.5k
  int padding = align - (D->offset % align);
67
69.5k
  if (padding < align) {  /* padding == align means no padding */
68
53.1k
    static lua_Integer paddingContent = 0;
69
53.1k
    lua_assert(cast_uint(align) <= sizeof(lua_Integer));
70
53.1k
    dumpBlock(D, &paddingContent, padding);
71
53.1k
  }
72
69.5k
  lua_assert(D->offset % align == 0);
73
69.5k
}
74
75
76
604k
#define dumpVar(D,x)    dumpVector(D,&x,1)
77
78
79
599k
static void dumpByte (DumpState *D, int y) {
80
599k
  lu_byte x = (lu_byte)y;
81
599k
  dumpVar(D, x);
82
599k
}
83
84
85
/*
86
** size for 'dumpVarint' buffer: each byte can store up to 7 bits.
87
** (The "+6" rounds up the division.)
88
*/
89
2.07M
#define DIBS    ((sizeof(size_t) * CHAR_BIT + 6) / 7)
90
91
/*
92
** Dumps an unsigned integer using the MSB Varint encoding
93
*/
94
1.77M
static void dumpVarint (DumpState *D, size_t x) {
95
1.77M
  lu_byte buff[DIBS];
96
1.77M
  int n = 1;
97
1.77M
  buff[DIBS - 1] = x & 0x7f;  /* fill least-significant byte */
98
2.07M
  while ((x >>= 7) != 0)  /* fill other bytes in reverse order */
99
301k
    buff[DIBS - (++n)] = (x & 0x7f) | 0x80;
100
1.77M
  dumpVector(D, buff + DIBS - n, n);
101
1.77M
}
102
103
104
787k
static void dumpSize (DumpState *D, size_t sz) {
105
787k
  dumpVarint(D, sz);
106
787k
}
107
108
987k
static void dumpInt (DumpState *D, int x) {
109
987k
  lua_assert(x >= 0);
110
987k
  dumpVarint(D, cast(size_t, x));
111
987k
}
112
113
114
2.69k
static void dumpNumber (DumpState *D, lua_Number x) {
115
2.69k
  dumpVar(D, x);
116
2.69k
}
117
118
119
2.98k
static void dumpInteger (DumpState *D, lua_Integer x) {
120
2.98k
  dumpVar(D, x);
121
2.98k
}
122
123
124
/*
125
** Dump a String. First dump its "size": size==0 means NULL;
126
** size==1 is followed by an index and means "reuse saved string with
127
** that index"; size>=2 is followed by the string contents with real
128
** size==size-2 and means that string, which will be saved with
129
** the next available index.
130
*/
131
466k
static void dumpString (DumpState *D, TString *ts) {
132
466k
  if (ts == NULL)
133
0
    dumpSize(D, 0);
134
466k
  else {
135
466k
    TValue idx;
136
466k
    int tag = luaH_getstr(D->h, ts, &idx);
137
466k
    if (!tagisempty(tag)) {  /* string already saved? */
138
321k
      dumpSize(D, 1);  /* reuse a saved string */
139
321k
      dumpSize(D, cast_sizet(ivalue(&idx)));  /* index of saved string */
140
321k
    }
141
144k
    else {  /* must write and save the string */
142
144k
      TValue key, value;  /* to save the string in the hash */
143
144k
      size_t size;
144
144k
      const char *s = getlstr(ts, size);
145
144k
      dumpSize(D, size + 2);
146
144k
      dumpVector(D, s, size + 1);  /* include ending '\0' */
147
144k
      D->nstr++;  /* one more saved string */
148
144k
      setsvalue(D->L, &key, ts);  /* the string is the key */
149
144k
      setivalue(&value, D->nstr);  /* its index is the value */
150
144k
      luaH_set(D->L, D->h, &key, &value);  /* h[ts] = nstr */
151
      /* integer value does not need barrier */
152
144k
    }
153
466k
  }
154
466k
}
155
156
157
67.6k
static void dumpCode (DumpState *D, const Proto *f) {
158
67.6k
  dumpInt(D, f->sizecode);
159
67.6k
  dumpAlign(D, sizeof(f->code[0]));
160
67.6k
  lua_assert(f->code != NULL);
161
67.6k
  dumpVector(D, f->code, f->sizecode);
162
67.6k
}
163
164
165
static void dumpFunction (DumpState *D, const Proto *f);
166
167
67.6k
static void dumpConstants (DumpState *D, const Proto *f) {
168
67.6k
  int i;
169
67.6k
  int n = f->sizek;
170
67.6k
  dumpInt(D, n);
171
248k
  for (i = 0; i < n; i++) {
172
180k
    const TValue *o = &f->k[i];
173
180k
    int tt = ttypetag(o);
174
180k
    dumpByte(D, tt);
175
180k
    switch (tt) {
176
1.10k
      case LUA_VNUMFLT:
177
1.10k
        dumpNumber(D, fltvalue(o));
178
0
        break;
179
1.39k
      case LUA_VNUMINT:
180
1.39k
        dumpInteger(D, ivalue(o));
181
0
        break;
182
174k
      case LUA_VSHRSTR:
183
174k
      case LUA_VLNGSTR:
184
174k
        dumpString(D, tsvalue(o));
185
0
        break;
186
3.64k
      default:
187
3.64k
        lua_assert(tt == LUA_VNIL || tt == LUA_VFALSE || tt == LUA_VTRUE);
188
180k
    }
189
180k
  }
190
67.6k
}
191
192
193
67.6k
static void dumpProtos (DumpState *D, const Proto *f) {
194
67.6k
  int i;
195
67.6k
  int n = f->sizep;
196
67.6k
  dumpInt(D, n);
197
133k
  for (i = 0; i < n; i++)
198
66.1k
    dumpFunction(D, f->p[i]);
199
67.6k
}
200
201
202
67.6k
static void dumpUpvalues (DumpState *D, const Proto *f) {
203
67.6k
  int i, n = f->sizeupvalues;
204
67.6k
  dumpInt(D, n);
205
136k
  for (i = 0; i < n; i++) {
206
68.7k
    dumpByte(D, f->upvalues[i].instack);
207
68.7k
    dumpByte(D, f->upvalues[i].idx);
208
68.7k
    dumpByte(D, f->upvalues[i].kind);
209
68.7k
  }
210
67.6k
}
211
212
213
67.6k
static void dumpDebug (DumpState *D, const Proto *f) {
214
67.6k
  int i, n;
215
67.6k
  n = (D->strip) ? 0 : f->sizelineinfo;
216
67.6k
  dumpInt(D, n);
217
67.6k
  if (f->lineinfo != NULL)
218
67.6k
    dumpVector(D, f->lineinfo, n);
219
67.6k
  n = (D->strip) ? 0 : f->sizeabslineinfo;
220
67.6k
  dumpInt(D, n);
221
67.6k
  if (n > 0) {
222
    /* 'abslineinfo' is an array of structures of int's */
223
1.84k
    dumpAlign(D, sizeof(int));
224
1.84k
    dumpVector(D, f->abslineinfo, n);
225
1.84k
  }
226
67.6k
  n = (D->strip) ? 0 : f->sizelocvars;
227
67.6k
  dumpInt(D, n);
228
223k
  for (i = 0; i < n; i++) {
229
155k
    dumpString(D, f->locvars[i].varname);
230
155k
    dumpInt(D, f->locvars[i].startpc);
231
155k
    dumpInt(D, f->locvars[i].endpc);
232
155k
  }
233
67.6k
  n = (D->strip) ? 0 : f->sizeupvalues;
234
67.6k
  dumpInt(D, n);
235
136k
  for (i = 0; i < n; i++)
236
68.7k
    dumpString(D, f->upvalues[i].name);
237
67.6k
}
238
239
240
67.6k
static void dumpFunction (DumpState *D, const Proto *f) {
241
67.6k
  dumpInt(D, f->linedefined);
242
67.6k
  dumpInt(D, f->lastlinedefined);
243
67.6k
  dumpByte(D, f->numparams);
244
67.6k
  dumpByte(D, f->flag);
245
67.6k
  dumpByte(D, f->maxstacksize);
246
67.6k
  dumpCode(D, f);
247
67.6k
  dumpConstants(D, f);
248
67.6k
  dumpUpvalues(D, f);
249
67.6k
  dumpProtos(D, f);
250
67.6k
  dumpString(D, D->strip ? NULL : f->source);
251
67.6k
  dumpDebug(D, f);
252
67.6k
}
253
254
255
1.58k
static void dumpHeader (DumpState *D) {
256
1.58k
  dumpLiteral(D, LUA_SIGNATURE);
257
1.58k
  dumpByte(D, LUAC_VERSION);
258
1.58k
  dumpByte(D, LUAC_FORMAT);
259
1.58k
  dumpLiteral(D, LUAC_DATA);
260
1.58k
  dumpByte(D, sizeof(Instruction));
261
1.58k
  dumpByte(D, sizeof(lua_Integer));
262
1.58k
  dumpByte(D, sizeof(lua_Number));
263
1.58k
  dumpInteger(D, LUAC_INT);
264
1.58k
  dumpNumber(D, LUAC_NUM);
265
1.58k
}
266
267
268
/*
269
** dump Lua function as precompiled chunk
270
*/
271
int luaU_dump (lua_State *L, const Proto *f, lua_Writer w, void *data,
272
1.58k
               int strip) {
273
1.58k
  DumpState D;
274
1.58k
  D.h = luaH_new(L);  /* aux. table to keep strings already dumped */
275
1.58k
  sethvalue2s(L, L->top.p, D.h);  /* anchor it */
276
1.58k
  L->top.p++;
277
1.58k
  D.L = L;
278
1.58k
  D.writer = w;
279
1.58k
  D.offset = 0;
280
1.58k
  D.data = data;
281
1.58k
  D.strip = strip;
282
1.58k
  D.status = 0;
283
1.58k
  D.nstr = 0;
284
1.58k
  dumpHeader(&D);
285
1.58k
  dumpByte(&D, f->sizeupvalues);
286
1.58k
  dumpFunction(&D, f);
287
1.58k
  dumpBlock(&D, NULL, 0);  /* signal end of dump */
288
1.58k
  return D.status;
289
1.58k
}
290