From 8d9d959acd012225236cc3937342d5e32ec50a37 Mon Sep 17 00:00:00 2001 From: Luke Gorrie Date: Tue, 8 May 2018 11:16:43 +0000 Subject: [PATCH 1/6] Extend GCproto debug with declared function name (declname) Lua functions can be declared in many different ways: function () end function foo () end function foo.bar () end function foo.bar:baz() end local function foo.bar:baz() end This change captures the text between 'function' and '(' as the "declared name" (declname) and records this in the GCproto object's debug information. This makes it possible to recover the declared name of a function, such as "foo.bar:baz", from its prototype. The Lua approach is usually to resolve names at runtime using introspection to see what name a function is bound to. However we need a mechanism that works on the "cold" debug information in the audit.log. One consequence is that semantically equivalent function declarations will have different levels of debug information in practice: fun = function () end -- Has no declname function fun () end -- Has declname "fun" which might penalize certain legitimate programming styles. That is lamentable. The situation is similar to the Scheme world: (define fun (lamdba ())) ; Function object has no debug name (define (fun)) ; Function object has debug name "fun" --- src/lj_bcread.c | 12 +++++++---- src/lj_bcwrite.c | 6 ++++-- src/lj_lex.c | 20 +++++++++++++++++- src/lj_lex.h | 4 ++++ src/lj_obj.h | 2 ++ src/lj_parse.c | 53 +++++++++++++++++++++++++++++++++++++++--------- 6 files changed, 80 insertions(+), 17 deletions(-) diff --git a/src/lj_bcread.c b/src/lj_bcread.c index 3afd8250be..9618ddae43 100644 --- a/src/lj_bcread.c +++ b/src/lj_bcread.c @@ -152,7 +152,7 @@ static uint32_t bcread_uleb128_33(LexState *ls) static void bcread_dbg(LexState *ls, GCproto *pt, MSize sizedbg) { uint32_t *lineinfo = (uint32_t*)proto_lineinfo(pt); - bcread_block(ls, lineinfo, sizedbg); + bcread_block(ls, (void*)proto_declname(pt), sizedbg); /* Swap lineinfo if the endianess differs. */ if (bcread_swap(ls)) { int i; @@ -302,7 +302,7 @@ GCproto *lj_bcread_proto(LexState *ls) MSize framesize, numparams, flags, sizeuv, sizekgc, sizekn, sizebc, sizept; MSize ofsk, ofsuv, ofsdbg; MSize sizedbg = 0; - BCLine firstline = 0, numline = 0; + BCLine firstline = 0, numline = 0, ndeclname = 0; /* Read prototype header. */ flags = bcread_byte(ls); @@ -315,6 +315,7 @@ GCproto *lj_bcread_proto(LexState *ls) if (!(bcread_flags(ls) & BCDUMP_F_STRIP)) { sizedbg = bcread_uleb128(ls); if (sizedbg) { + ndeclname = bcread_uleb128(ls); firstline = bcread_uleb128(ls); numline = bcread_uleb128(ls); } @@ -362,11 +363,14 @@ GCproto *lj_bcread_proto(LexState *ls) pt->numline = numline; if (sizedbg) { MSize sizeli = (sizebc-1) * sizeof(BCLine); - setmref(pt->lineinfo, (char *)pt + ofsdbg); - setmref(pt->uvinfo, (char *)pt + ofsdbg + sizeli); + setmref(pt->declname, (char *)pt + ofsdbg); + setmref(pt->lineinfo, (char *)pt + ofsdbg + ndeclname); + setmref(pt->uvinfo, (char *)pt + ofsdbg + ndeclname + sizeli); bcread_dbg(ls, pt, sizedbg); setmref(pt->varinfo, bcread_varinfo(pt)); + lua_assert(strlen(pt->declname)+1 == ndeclname); } else { + setmref(pt->declname, NULL); setmref(pt->lineinfo, NULL); setmref(pt->uvinfo, NULL); setmref(pt->varinfo, NULL); diff --git a/src/lj_bcwrite.c b/src/lj_bcwrite.c index 69bb430f91..5167c731d3 100644 --- a/src/lj_bcwrite.c +++ b/src/lj_bcwrite.c @@ -212,6 +212,7 @@ static void bcwrite_proto(BCWriteCtx *ctx, GCproto *pt) { MSize sizedbg = 0; char *p; + const char *declname = pt->declname ? proto_declname(pt) : ""; /* Recursively write children of prototype. */ if ((pt->flags & PROTO_CHILD)) { @@ -239,9 +240,10 @@ static void bcwrite_proto(BCWriteCtx *ctx, GCproto *pt) p = lj_strfmt_wuleb128(p, pt->sizebc-1); if (!ctx->strip) { if (proto_lineinfo(pt)) - sizedbg = pt->sizept - (MSize)((char *)proto_lineinfo(pt) - (char *)pt); + sizedbg = pt->sizept - (MSize)((char *)proto_declname(pt) - (char *)pt); p = lj_strfmt_wuleb128(p, sizedbg); if (sizedbg) { + p = lj_strfmt_wuleb128(p, strlen(declname)+1); p = lj_strfmt_wuleb128(p, pt->firstline); p = lj_strfmt_wuleb128(p, pt->numline); } @@ -259,7 +261,7 @@ static void bcwrite_proto(BCWriteCtx *ctx, GCproto *pt) /* Write debug info, if not stripped. */ if (sizedbg) { p = lj_buf_more(&ctx->sb, sizedbg); - p = lj_buf_wmem(p, proto_lineinfo(pt), sizedbg); + p = lj_buf_wmem(p, declname, sizedbg); setsbufP(&ctx->sb, p); } diff --git a/src/lj_lex.c b/src/lj_lex.c index a2cc6b2f52..2265c8836d 100644 --- a/src/lj_lex.c +++ b/src/lj_lex.c @@ -54,7 +54,9 @@ static LJ_NOINLINE LexChar lex_more(LexState *ls) /* Get next character. */ static LJ_AINLINE LexChar lex_next(LexState *ls) { - return (ls->c = ls->p < ls->pe ? (LexChar)(uint8_t)*ls->p++ : lex_more(ls)); + LexChar c = (ls->c = ls->p < ls->pe ? (LexChar)(uint8_t)*ls->p++ : lex_more(ls)); + if (ls->log && ls->log < ls->logend) *ls->log++ = c; + return c; } /* Save character. */ @@ -399,6 +401,8 @@ int lj_lex_setup(lua_State *L, LexState *ls) ls->lookahead = TK_eof; /* No look-ahead token. */ ls->linenumber = 1; ls->lastline = 1; + ls->log = NULL; + ls->logend = NULL; lex_next(ls); /* Read-ahead first char. */ if (ls->c == 0xef && ls->p + 2 <= ls->pe && (uint8_t)ls->p[0] == 0xbb && (uint8_t)ls->p[1] == 0xbf) { /* Skip UTF-8 BOM (if buffered). */ @@ -489,6 +493,20 @@ void lj_lex_error(LexState *ls, LexToken tok, ErrMsg em, ...) va_end(argp); } +/* Log the next input characters to a bounded buffer. */ +void lj_lex_log(LexState *ls, char *log, int size) +{ + ls->log = log; + ls->logend = log + size-1; +} + +/* Stop logging input characters. */ +void lj_lex_endlog(LexState *ls) +{ + ls->log = NULL; + ls->logend = NULL; +} + /* Initialize strings for reserved words. */ void lj_lex_init(lua_State *L) { diff --git a/src/lj_lex.h b/src/lj_lex.h index 33fa865726..5d6e7d9eb7 100644 --- a/src/lj_lex.h +++ b/src/lj_lex.h @@ -73,6 +73,8 @@ typedef struct LexState { BCInsLine *bcstack; /* Stack for bytecode instructions/line numbers. */ MSize sizebcstack; /* Size of bytecode stack. */ uint32_t level; /* Syntactical nesting level. */ + char *log; /* Current position where input should be logged. */ + char *logend; /* Last position where input can be logged. */ } LexState; LJ_FUNC int lj_lex_setup(lua_State *L, LexState *ls); @@ -80,6 +82,8 @@ LJ_FUNC void lj_lex_cleanup(lua_State *L, LexState *ls); LJ_FUNC void lj_lex_next(LexState *ls); LJ_FUNC LexToken lj_lex_lookahead(LexState *ls); LJ_FUNC const char *lj_lex_token2str(LexState *ls, LexToken tok); +LJ_FUNC void lj_lex_log(LexState *ls, char *log, int size); +LJ_FUNC void lj_lex_endlog(LexState *ls); LJ_FUNC_NORET void lj_lex_error(LexState *ls, LexToken tok, ErrMsg em, ...); LJ_FUNC void lj_lex_init(lua_State *L); diff --git a/src/lj_obj.h b/src/lj_obj.h index 7586aa55bf..9d9349ef86 100644 --- a/src/lj_obj.h +++ b/src/lj_obj.h @@ -311,6 +311,7 @@ typedef struct GCproto { GCRef chunkname; /* Name of the chunk this function was defined in. */ BCLine firstline; /* First line of the function definition. */ BCLine numline; /* Number of lines for the function definition. */ + MRef declname; /* Declared name of function (null-terminated). */ MRef lineinfo; /* Map from bytecode ins. to source line. */ MRef uvinfo; /* Upvalue names. */ MRef varinfo; /* Names and compressed extents of local variables. */ @@ -344,6 +345,7 @@ typedef struct GCproto { #define proto_chunkname(pt) (strref((pt)->chunkname)) #define proto_chunknamestr(pt) (strdata(proto_chunkname((pt)))) +#define proto_declname(pt) (mref((pt)->declname, const char)) #define proto_lineinfo(pt) (mref((pt)->lineinfo, const uint32_t)) #define proto_uvinfo(pt) (mref((pt)->uvinfo, const uint8_t)) #define proto_varinfo(pt) (mref((pt)->varinfo, const uint8_t)) diff --git a/src/lj_parse.c b/src/lj_parse.c index 1b50a640b5..6abff004aa 100644 --- a/src/lj_parse.c +++ b/src/lj_parse.c @@ -1366,12 +1366,20 @@ static void fs_fixup_line(FuncState *fs, GCproto *pt, } /* Prepare variable info for prototype. */ -static size_t fs_prep_var(LexState *ls, FuncState *fs, size_t *ofsvar) +static size_t fs_prep_var(LexState *ls, FuncState *fs, size_t *ofsvar, const char *declname) { VarInfo *vs =ls->vstack, *ve; MSize i, n; BCPos lastpc; lj_buf_reset(&ls->sb); /* Copy to temp. string buffer. */ + /* Store function declaration name. */ + { + char *p; + int len = strlen(declname) + 1; + p = lj_buf_more(&ls->sb, len); + p = lj_buf_wmem(p, declname, len); + setsbufP(&ls->sb, p); + } /* Store upvalue names. */ for (i = 0, n = fs->nuv; i < n; i++) { GCstr *s = strref(vs[fs->uvmap[i]].name); @@ -1410,7 +1418,9 @@ static size_t fs_prep_var(LexState *ls, FuncState *fs, size_t *ofsvar) /* Fixup variable info for prototype. */ static void fs_fixup_var(LexState *ls, GCproto *pt, uint8_t *p, size_t ofsvar) { - setmref(pt->uvinfo, p); + int ndeclname = strlen((char*)p)+1; + setmref(pt->declname, p); + setmref(pt->uvinfo, p + ndeclname); setmref(pt->varinfo, (char *)p + ofsvar); memcpy(p, sbufB(&ls->sb), sbuflen(&ls->sb)); /* Copy from temp. buffer. */ } @@ -1466,7 +1476,7 @@ static void fs_fixup_ret(FuncState *fs) } /* Finish a FuncState and return the new prototype. */ -static GCproto *fs_finish(LexState *ls, BCLine line) +static GCproto *fs_finish(LexState *ls, BCLine line, char *declname) { lua_State *L = ls->L; FuncState *fs = ls->fs; @@ -1483,7 +1493,7 @@ static GCproto *fs_finish(LexState *ls, BCLine line) ofsk = sizept; sizept += fs->nkn*sizeof(TValue); ofsuv = sizept; sizept += ((fs->nuv+1)&~1)*2; ofsli = sizept; sizept += fs_prep_line(fs, numline); - ofsdbg = sizept; sizept += fs_prep_var(ls, fs, &ofsvar); + ofsdbg = sizept; sizept += fs_prep_var(ls, fs, &ofsvar, declname); /* Allocate prototype and initialize its fields. */ pt = (GCproto *)lj_mem_newgco(L, (MSize)sizept); @@ -1742,7 +1752,8 @@ static BCReg parse_params(LexState *ls, int needself) static void parse_chunk(LexState *ls); /* Parse body of a function. */ -static void parse_body(LexState *ls, ExpDesc *e, int needself, BCLine line) +static void parse_body(LexState *ls, ExpDesc *e, int needself, BCLine line, + char *declname) { FuncState fs, *pfs = ls->fs; FuncScope bl; @@ -1757,7 +1768,7 @@ static void parse_body(LexState *ls, ExpDesc *e, int needself, BCLine line) bcemit_AD(&fs, BC_FUNCF, 0, 0); /* Placeholder. */ parse_chunk(ls); if (ls->tok != TK_end) lex_match(ls, TK_end, TK_function, line); - pt = fs_finish(ls, (ls->lastline = ls->linenumber)); + pt = fs_finish(ls, (ls->lastline = ls->linenumber), declname); pfs->bcbase = ls->bcstack + oldbase; /* May have been reallocated. */ pfs->bclim = (BCPos)(ls->sizebcstack - oldbase); /* Store new prototype in the constant array of the parent. */ @@ -1908,7 +1919,7 @@ static void expr_simple(LexState *ls, ExpDesc *v) return; case TK_function: lj_lex_next(ls); - parse_body(ls, v, 0, ls->linenumber); + parse_body(ls, v, 0, ls->linenumber, ""); return; default: expr_primary(ls, v); @@ -2137,9 +2148,24 @@ static void parse_call_assign(LexState *ls) } } +/* Convert the logged input into a canonical function declaration name. */ +static char *log_declname(char *log) +{ + char *end = log + strlen(log) - 1; + /* Strip off trailing chars e.g. change "myfunc (X" to "myfunc". */ + while (end > log && *end != '(') end--; /* Rewind to '('. */ + if (*end != '(') return log; else end--; /* Skip '(' if present. */ + while (end > log && *end == ' ') end--; /* Rewind over spaces. */ + *(end+1) = '\0'; /* Truncate. */ + return log; +} + /* Parse 'local' statement. */ static void parse_local(LexState *ls) { + char log[128]; + memset(&log[0], 0, sizeof(log)); + lj_lex_log(ls, &log[0], sizeof(log)-1); if (lex_opt(ls, TK_function)) { /* Local function declaration. */ ExpDesc v, b; FuncState *fs = ls->fs; @@ -2148,7 +2174,8 @@ static void parse_local(LexState *ls) v.u.s.aux = fs->varmap[fs->freereg]; bcreg_reserve(fs, 1); var_add(ls, 1); - parse_body(ls, &b, 0, ls->linenumber); + lj_lex_endlog(ls); /* Captured declared function name. */ + parse_body(ls, &b, 0, ls->linenumber, log_declname(log)); /* bcemit_store(fs, &v, &b) without setting VSTACK_VAR_RW. */ expr_free(fs, &b); expr_toreg(fs, &b, v.u.s.info); @@ -2157,6 +2184,7 @@ static void parse_local(LexState *ls) } else { /* Local variable declaration. */ ExpDesc e; BCReg nexps, nvars = 0; + lj_lex_endlog(ls); /* Not used for variables. */ do { /* Collect LHS. */ var_new(ls, nvars++, lex_str(ls)); } while (lex_opt(ls, ',')); @@ -2177,6 +2205,10 @@ static void parse_func(LexState *ls, BCLine line) FuncState *fs; ExpDesc v, b; int needself = 0; + char log[128]; + log[0] = 'c'; + memset(log, 0, sizeof(log)); + lj_lex_log(ls, log, sizeof(log)-1); lj_lex_next(ls); /* Skip 'function'. */ /* Parse function name. */ var_lookup(ls, &v); @@ -2186,7 +2218,8 @@ static void parse_func(LexState *ls, BCLine line) needself = 1; expr_field(ls, &v); } - parse_body(ls, &b, needself, line); + lj_lex_endlog(ls); + parse_body(ls, &b, needself, line, log_declname(log)); fs = ls->fs; bcemit_store(fs, &v, &b); fs->bcbase[fs->pc - 1].line = line; /* Set line for the store. */ @@ -2616,7 +2649,7 @@ GCproto *lj_parse(LexState *ls) parse_chunk(ls); if (ls->tok != TK_eof) err_token(ls, TK_eof); - pt = fs_finish(ls, ls->linenumber); + pt = fs_finish(ls, ls->linenumber, ""); L->top--; /* Drop chunkname. */ lua_assert(fs.prev == NULL); lua_assert(ls->fs == NULL); From 01f8b4cf93294f5d36df857379d3dfd0546a974e Mon Sep 17 00:00:00 2001 From: Luke Gorrie Date: Tue, 8 May 2018 13:06:59 +0000 Subject: [PATCH 2/6] lj_bcread.c: Remove suspicious loop Remove a loop in bcread_varinfo() that looks strange. What is this loop supposed to do? The code doesn't make sense to me, and this change is resolving a segfault problem. --- src/lj_bcread.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/lj_bcread.c b/src/lj_bcread.c index 9618ddae43..52a22da9ed 100644 --- a/src/lj_bcread.c +++ b/src/lj_bcread.c @@ -164,9 +164,7 @@ static void bcread_dbg(LexState *ls, GCproto *pt, MSize sizedbg) static const void *bcread_varinfo(GCproto *pt) { const uint8_t *p = proto_uvinfo(pt); - MSize n = pt->sizeuv; - if (n) while (*p++ || --n) ; - return p; + return p + pt->sizeuv; } /* Read a single constant key/value of a template table. */ From 8f55c034371b5c83c677694088d652ca58dcebdf Mon Sep 17 00:00:00 2001 From: Luke Gorrie Date: Tue, 8 May 2018 13:13:44 +0000 Subject: [PATCH 3/6] src/reusevm: Update generated code --- src/reusevm/lj_vm.S | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/reusevm/lj_vm.S b/src/reusevm/lj_vm.S index c0abc094f8..3ff330bcb4 100644 --- a/src/reusevm/lj_vm.S +++ b/src/reusevm/lj_vm.S @@ -797,7 +797,7 @@ lj_BC_CALLT: .byte 20,72,139,93,32,139,11,15,182,233,15,182,205,72,131,195 .byte 4,65,255,36,238,247,195,3,0,0,0,117,228,15,182,75 .byte 253,72,247,217,76,139,124,202,224,73,193,231,17,73,193,239 - .byte 17,77,139,127,32,77,139,127,184,235,198,72,131,235,3,247 + .byte 17,77,139,127,32,77,139,127,176,235,198,72,131,235,3,247 .byte 195,7,0,0,0,117,15,72,41,218,73,137,215,72,139,90 .byte 248,233,119,255,255,255,131,195,3,233,111,255,255,255 @@ -881,7 +881,7 @@ lj_BC_RET: .byte 111,240,73,131,199,8,131,232,1,117,239,139,4,36,15,182 .byte 107,255,57,197,119,51,15,182,75,253,72,247,217,72,141,84 .byte 202,240,76,139,122,240,73,193,231,17,73,193,239,17,77,139 - .byte 127,32,77,139,127,184,139,3,15,182,204,15,182,232,72,131 + .byte 127,32,77,139,127,176,139,3,15,182,204,15,182,232,72,131 .byte 195,4,193,232,16,65,255,36,238,73,199,71,240,255,255,255 .byte 255,73,131,199,8,72,131,192,1,235,183,72,141,107,253,247 .byte 197,7,0,0,0,15,133,154,5,0,0,72,41,234,72,1 @@ -895,7 +895,7 @@ lj_BC_RET0: .byte 72,139,90,248,137,4,36,247,195,3,0,0,0,117,71,56 .byte 67,255,119,51,15,182,75,253,72,247,217,72,141,84,202,240 .byte 76,139,122,240,73,193,231,17,73,193,239,17,77,139,127,32 - .byte 77,139,127,184,139,3,15,182,204,15,182,232,72,131,195,4 + .byte 77,139,127,176,139,3,15,182,204,15,182,232,72,131,195,4 .byte 193,232,16,65,255,36,238,72,199,68,194,232,255,255,255,255 .byte 72,131,192,1,235,185,72,141,107,253,247,197,7,0,0,0 .byte 15,133,41,5,0,0,72,41,234,235,149 @@ -908,7 +908,7 @@ lj_BC_RET1: .byte 193,225,3,72,139,90,248,137,4,36,247,195,3,0,0,0 .byte 117,79,72,139,44,10,72,137,106,240,56,67,255,119,51,15 .byte 182,75,253,72,247,217,72,141,84,202,240,76,139,122,240,73 - .byte 193,231,17,73,193,239,17,77,139,127,32,77,139,127,184,139 + .byte 193,231,17,73,193,239,17,77,139,127,32,77,139,127,176,139 .byte 3,15,182,204,15,182,232,72,131,195,4,193,232,16,65,255 .byte 36,238,72,199,68,194,232,255,255,255,255,72,131,192,1,235 .byte 185,72,141,107,253,247,197,7,0,0,0,15,133,179,4,0 @@ -1045,8 +1045,8 @@ lj_BC_FUNCF: .type lj_BC_IFUNCF, @function .size lj_BC_IFUNCF, 68 lj_BC_IFUNCF: - .byte 76,139,123,180,72,139,108,36,16,72,141,12,202,72,59,77 - .byte 48,15,135,81,3,0,0,15,182,75,158,57,200,118,19,139 + .byte 76,139,123,172,72,139,108,36,16,72,141,12,202,72,59,77 + .byte 48,15,135,81,3,0,0,15,182,75,150,57,200,118,19,139 .byte 3,15,182,204,15,182,232,72,131,195,4,193,232,16,65,255 .byte 36,238,72,199,68,194,248,255,255,255,255,131,192,1,57,200 .byte 118,240,235,219 @@ -1056,8 +1056,8 @@ lj_BC_IFUNCF: .type lj_BC_JFUNCF, @function .size lj_BC_JFUNCF, 58 lj_BC_JFUNCF: - .byte 76,139,123,180,72,139,108,36,16,72,141,12,202,72,59,77 - .byte 48,15,135,13,3,0,0,15,182,75,158,57,200,118,9,15 + .byte 76,139,123,172,72,139,108,36,16,72,141,12,202,72,59,77 + .byte 48,15,135,13,3,0,0,15,182,75,150,57,200,118,9,15 .byte 183,67,254,233,51,255,255,255,72,199,68,194,248,255,255,255 .byte 255,131,192,1,57,200,118,240,235,229 @@ -1075,10 +1075,10 @@ lj_BC_IFUNCV: .byte 141,44,197,11,0,0,0,72,141,68,194,8,76,139,122,240 .byte 72,137,104,248,76,137,120,240,72,139,108,36,16,72,141,12 .byte 200,72,59,77,48,15,135,185,2,0,0,72,137,209,72,137 - .byte 194,15,182,107,158,133,237,116,37,72,131,193,8,72,131,193 + .byte 194,15,182,107,150,133,237,116,37,72,131,193,8,72,131,193 .byte 8,72,57,209,115,47,76,139,121,240,76,137,56,72,131,192 .byte 8,72,199,65,240,255,255,255,255,131,237,1,117,223,76,139 - .byte 123,180,139,3,15,182,204,15,182,232,72,131,195,4,193,232 + .byte 123,172,139,3,15,182,204,15,182,232,72,131,195,4,193,232 .byte 16,65,255,36,238,72,199,0,255,255,255,255,72,131,192,8 .byte 131,237,1,117,240,235,215 @@ -1233,7 +1233,7 @@ lj_vm_growstack_v: .type lj_vm_growstack_f, @function .size lj_vm_growstack_f, 86 lj_vm_growstack_f: - .byte 72,141,68,194,248,15,182,75,159,72,131,195,4,72,137,85 + .byte 72,141,68,194,248,15,182,75,151,72,131,195,4,72,137,85 .byte 32,72,137,69,40,72,137,92,36,24,72,137,206,72,137,239 call lj_state_growstack .byte 72,139,85,32,72,139,69,40,72,139,106,240,72,193,229,17 @@ -1314,7 +1314,7 @@ lj_cont_dispatch: .byte 72,1,209,72,131,227,248,72,137,213,72,41,218,72,199,68 .byte 193,248,255,255,255,255,72,137,200,72,139,93,232,72,139,77 .byte 224,72,131,249,1,118,22,76,139,122,240,73,193,231,17,73 - .byte 193,239,17,77,139,127,32,77,139,127,184,255,225,15,132,22 + .byte 193,239,17,77,139,127,32,77,139,127,176,255,225,15,132,22 .byte 31,0,0,72,41,213,193,237,3,141,69,253,233,84,24,0 .byte 0 @@ -2477,7 +2477,7 @@ lj_cont_hook: .size lj_vm_hotloop, 66 lj_vm_hotloop: .byte 72,139,106,240,72,193,229,17,72,193,237,17,72,139,109,32 - .byte 15,182,69,163,72,141,4,194,72,139,108,36,16,72,137,85 + .byte 15,182,69,155,72,141,4,194,72,139,108,36,16,72,137,85 .byte 32,72,137,69,40,72,137,222,73,141,190,80,243,255,255,73 .byte 137,174,224,243,255,255,72,137,92,36,24 call lj_trace_hot @@ -2553,13 +2553,13 @@ lj_vm_exit_interp: .byte 114,7,69,137,150,48,241,255,255,76,139,105,248,76,139,33 .byte 72,137,204,133,192,15,136,134,0,0,0,72,139,108,36,16 .byte 137,4,36,76,139,122,240,73,193,231,17,73,193,239,17,77 - .byte 139,127,32,77,139,127,184,72,137,85,32,73,199,134,16,242 + .byte 139,127,32,77,139,127,176,72,137,85,32,73,199,134,16,242 .byte 255,255,0,0,0,0,69,139,150,40,241,255,255,65,199,134 .byte 40,241,255,255,255,255,255,255,139,3,15,182,204,15,182,232 .byte 72,131,195,4,193,232,16,131,253,89,114,8,131,253,97,115 .byte 7,139,4,36,65,255,36,238,72,139,66,248,169,3,0,0 .byte 0,117,238,15,182,64,253,72,247,216,76,139,124,194,224,73 - .byte 193,231,17,73,193,239,17,77,139,127,32,77,139,127,184,235 + .byte 193,231,17,73,193,239,17,77,139,127,32,77,139,127,176,235 .byte 208,72,247,216,72,137,239,72,137,198 call lj_err_throw From d60c59518ff6ce8639112095a63faa3cf08a4a8a Mon Sep 17 00:00:00 2001 From: Luke Gorrie Date: Tue, 8 May 2018 13:18:33 +0000 Subject: [PATCH 4/6] lj_prase.c: Remove old debug noise --- src/lj_parse.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/lj_parse.c b/src/lj_parse.c index 6abff004aa..1e948d97ce 100644 --- a/src/lj_parse.c +++ b/src/lj_parse.c @@ -2206,7 +2206,6 @@ static void parse_func(LexState *ls, BCLine line) ExpDesc v, b; int needself = 0; char log[128]; - log[0] = 'c'; memset(log, 0, sizeof(log)); lj_lex_log(ls, log, sizeof(log)-1); lj_lex_next(ls); /* Skip 'function'. */ From c552236ca957899d74dd876a131751397b7468dd Mon Sep 17 00:00:00 2001 From: Luke Gorrie Date: Wed, 9 May 2018 06:38:17 +0000 Subject: [PATCH 5/6] Restore older debug info fields to their original positions The declname field had been inserted at the beginning of the debug information, but now it is appended to the end. This preserves the order of the existing fields. This is a defensive move to avoid bugs due to unknowingly disturbing invariants in the debug info structure. (Lame, I know, but I have other fish to fry right now.) --- src/lj_bcread.c | 17 ++++++++--------- src/lj_bcwrite.c | 12 +++++++----- src/lj_obj.h | 4 ++-- src/lj_parse.c | 33 +++++++++++++++++---------------- 4 files changed, 34 insertions(+), 32 deletions(-) diff --git a/src/lj_bcread.c b/src/lj_bcread.c index 52a22da9ed..2d84c46736 100644 --- a/src/lj_bcread.c +++ b/src/lj_bcread.c @@ -152,7 +152,7 @@ static uint32_t bcread_uleb128_33(LexState *ls) static void bcread_dbg(LexState *ls, GCproto *pt, MSize sizedbg) { uint32_t *lineinfo = (uint32_t*)proto_lineinfo(pt); - bcread_block(ls, (void*)proto_declname(pt), sizedbg); + bcread_block(ls, (void*)lineinfo, sizedbg); /* Swap lineinfo if the endianess differs. */ if (bcread_swap(ls)) { int i; @@ -298,9 +298,9 @@ GCproto *lj_bcread_proto(LexState *ls) { GCproto *pt; MSize framesize, numparams, flags, sizeuv, sizekgc, sizekn, sizebc, sizept; - MSize ofsk, ofsuv, ofsdbg; + MSize ofsk, ofsuv, ofsdbg, ofsdeclname = 0; MSize sizedbg = 0; - BCLine firstline = 0, numline = 0, ndeclname = 0; + BCLine firstline = 0, numline = 0; /* Read prototype header. */ flags = bcread_byte(ls); @@ -313,9 +313,9 @@ GCproto *lj_bcread_proto(LexState *ls) if (!(bcread_flags(ls) & BCDUMP_F_STRIP)) { sizedbg = bcread_uleb128(ls); if (sizedbg) { - ndeclname = bcread_uleb128(ls); firstline = bcread_uleb128(ls); numline = bcread_uleb128(ls); + ofsdeclname = bcread_uleb128(ls); } } @@ -361,17 +361,16 @@ GCproto *lj_bcread_proto(LexState *ls) pt->numline = numline; if (sizedbg) { MSize sizeli = (sizebc-1) * sizeof(BCLine); - setmref(pt->declname, (char *)pt + ofsdbg); - setmref(pt->lineinfo, (char *)pt + ofsdbg + ndeclname); - setmref(pt->uvinfo, (char *)pt + ofsdbg + ndeclname + sizeli); + setmref(pt->lineinfo, (char *)pt + ofsdbg); + setmref(pt->uvinfo, (char *)pt + ofsdbg + sizeli); + setmref(pt->declname, (char *)pt + ofsdbg + ofsdeclname); bcread_dbg(ls, pt, sizedbg); setmref(pt->varinfo, bcread_varinfo(pt)); - lua_assert(strlen(pt->declname)+1 == ndeclname); } else { - setmref(pt->declname, NULL); setmref(pt->lineinfo, NULL); setmref(pt->uvinfo, NULL); setmref(pt->varinfo, NULL); + setmref(pt->declname, NULL); } return pt; } diff --git a/src/lj_bcwrite.c b/src/lj_bcwrite.c index 5167c731d3..353a677cf6 100644 --- a/src/lj_bcwrite.c +++ b/src/lj_bcwrite.c @@ -210,7 +210,7 @@ static char *bcwrite_bytecode(BCWriteCtx *ctx, char *p, GCproto *pt) /* Write prototype. */ static void bcwrite_proto(BCWriteCtx *ctx, GCproto *pt) { - MSize sizedbg = 0; + MSize sizedbg = 0, ofsdeclname = 0; char *p; const char *declname = pt->declname ? proto_declname(pt) : ""; @@ -239,13 +239,15 @@ static void bcwrite_proto(BCWriteCtx *ctx, GCproto *pt) p = lj_strfmt_wuleb128(p, pt->sizekn); p = lj_strfmt_wuleb128(p, pt->sizebc-1); if (!ctx->strip) { - if (proto_lineinfo(pt)) - sizedbg = pt->sizept - (MSize)((char *)proto_declname(pt) - (char *)pt); + if (proto_lineinfo(pt)) { + sizedbg = pt->sizept - (MSize)((char *)proto_lineinfo(pt) - (char *)pt); + ofsdeclname = (MSize)((char*)proto_declname(pt) - (char *)proto_lineinfo(pt)); + } p = lj_strfmt_wuleb128(p, sizedbg); if (sizedbg) { - p = lj_strfmt_wuleb128(p, strlen(declname)+1); p = lj_strfmt_wuleb128(p, pt->firstline); p = lj_strfmt_wuleb128(p, pt->numline); + p = lj_strfmt_wuleb128(p, ofsdeclname); } } @@ -261,7 +263,7 @@ static void bcwrite_proto(BCWriteCtx *ctx, GCproto *pt) /* Write debug info, if not stripped. */ if (sizedbg) { p = lj_buf_more(&ctx->sb, sizedbg); - p = lj_buf_wmem(p, declname, sizedbg); + p = lj_buf_wmem(p, proto_lineinfo(pt), sizedbg); setsbufP(&ctx->sb, p); } diff --git a/src/lj_obj.h b/src/lj_obj.h index 9d9349ef86..fc6022ef83 100644 --- a/src/lj_obj.h +++ b/src/lj_obj.h @@ -311,10 +311,10 @@ typedef struct GCproto { GCRef chunkname; /* Name of the chunk this function was defined in. */ BCLine firstline; /* First line of the function definition. */ BCLine numline; /* Number of lines for the function definition. */ - MRef declname; /* Declared name of function (null-terminated). */ MRef lineinfo; /* Map from bytecode ins. to source line. */ MRef uvinfo; /* Upvalue names. */ MRef varinfo; /* Names and compressed extents of local variables. */ + MRef declname; /* Declared name of function (null-terminated). */ } GCproto; /* Flags for prototype. */ @@ -345,10 +345,10 @@ typedef struct GCproto { #define proto_chunkname(pt) (strref((pt)->chunkname)) #define proto_chunknamestr(pt) (strdata(proto_chunkname((pt)))) -#define proto_declname(pt) (mref((pt)->declname, const char)) #define proto_lineinfo(pt) (mref((pt)->lineinfo, const uint32_t)) #define proto_uvinfo(pt) (mref((pt)->uvinfo, const uint8_t)) #define proto_varinfo(pt) (mref((pt)->varinfo, const uint8_t)) +#define proto_declname(pt) (mref((pt)->declname, const char)) /* -- Upvalue object ------------------------------------------------------ */ diff --git a/src/lj_parse.c b/src/lj_parse.c index 1e948d97ce..e9672f00d8 100644 --- a/src/lj_parse.c +++ b/src/lj_parse.c @@ -1366,20 +1366,13 @@ static void fs_fixup_line(FuncState *fs, GCproto *pt, } /* Prepare variable info for prototype. */ -static size_t fs_prep_var(LexState *ls, FuncState *fs, size_t *ofsvar, const char *declname) +static size_t fs_prep_var(LexState *ls, FuncState *fs, size_t *ofsvar, + size_t *ofsdeclname, const char *declname) { VarInfo *vs =ls->vstack, *ve; MSize i, n; BCPos lastpc; lj_buf_reset(&ls->sb); /* Copy to temp. string buffer. */ - /* Store function declaration name. */ - { - char *p; - int len = strlen(declname) + 1; - p = lj_buf_more(&ls->sb, len); - p = lj_buf_wmem(p, declname, len); - setsbufP(&ls->sb, p); - } /* Store upvalue names. */ for (i = 0, n = fs->nuv; i < n; i++) { GCstr *s = strref(vs[fs->uvmap[i]].name); @@ -1412,16 +1405,24 @@ static size_t fs_prep_var(LexState *ls, FuncState *fs, size_t *ofsvar, const cha } } lj_buf_putb(&ls->sb, '\0'); /* Terminator for varinfo. */ + /* Store function declaration name. */ + *ofsdeclname = sbuflen(&ls->sb); + { + char *p; + int len = strlen(declname) + 1; + p = lj_buf_more(&ls->sb, len); + p = lj_buf_wmem(p, declname, len); + setsbufP(&ls->sb, p); + } return sbuflen(&ls->sb); } /* Fixup variable info for prototype. */ -static void fs_fixup_var(LexState *ls, GCproto *pt, uint8_t *p, size_t ofsvar) +static void fs_fixup_var(LexState *ls, GCproto *pt, uint8_t *p, size_t ofsvar, size_t ofsdeclname) { - int ndeclname = strlen((char*)p)+1; - setmref(pt->declname, p); - setmref(pt->uvinfo, p + ndeclname); + setmref(pt->uvinfo, p); setmref(pt->varinfo, (char *)p + ofsvar); + setmref(pt->declname, (char*)p + ofsdeclname); memcpy(p, sbufB(&ls->sb), sbuflen(&ls->sb)); /* Copy from temp. buffer. */ } @@ -1481,7 +1482,7 @@ static GCproto *fs_finish(LexState *ls, BCLine line, char *declname) lua_State *L = ls->L; FuncState *fs = ls->fs; BCLine numline = line - fs->linedefined; - size_t sizept, ofsk, ofsuv, ofsli, ofsdbg, ofsvar; + size_t sizept, ofsk, ofsuv, ofsli, ofsdbg, ofsvar, ofsdeclname; GCproto *pt; /* Apply final fixups. */ @@ -1493,7 +1494,7 @@ static GCproto *fs_finish(LexState *ls, BCLine line, char *declname) ofsk = sizept; sizept += fs->nkn*sizeof(TValue); ofsuv = sizept; sizept += ((fs->nuv+1)&~1)*2; ofsli = sizept; sizept += fs_prep_line(fs, numline); - ofsdbg = sizept; sizept += fs_prep_var(ls, fs, &ofsvar, declname); + ofsdbg = sizept; sizept += fs_prep_var(ls, fs, &ofsvar, &ofsdeclname, declname); /* Allocate prototype and initialize its fields. */ pt = (GCproto *)lj_mem_newgco(L, (MSize)sizept); @@ -1511,7 +1512,7 @@ static GCproto *fs_finish(LexState *ls, BCLine line, char *declname) fs_fixup_k(fs, pt, (void *)((char *)pt + ofsk)); fs_fixup_uv1(fs, pt, (uint16_t *)((char *)pt + ofsuv)); fs_fixup_line(fs, pt, (void *)((char *)pt + ofsli), numline); - fs_fixup_var(ls, pt, (uint8_t *)((char *)pt + ofsdbg), ofsvar); + fs_fixup_var(ls, pt, (uint8_t *)((char *)pt + ofsdbg), ofsvar, ofsdeclname); L->top--; /* Pop table of constants. */ ls->vtop = fs->vbase; /* Reset variable stack. */ From 96e00a6f86f55d93b2b2ee95f747c50b0bf87338 Mon Sep 17 00:00:00 2001 From: Luke Gorrie Date: Wed, 9 May 2018 06:59:37 +0000 Subject: [PATCH 6/6] lj_bcwrite.c: Remove unused variable --- src/lj_bcwrite.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/lj_bcwrite.c b/src/lj_bcwrite.c index 353a677cf6..e46e2b8757 100644 --- a/src/lj_bcwrite.c +++ b/src/lj_bcwrite.c @@ -212,7 +212,6 @@ static void bcwrite_proto(BCWriteCtx *ctx, GCproto *pt) { MSize sizedbg = 0, ofsdeclname = 0; char *p; - const char *declname = pt->declname ? proto_declname(pt) : ""; /* Recursively write children of prototype. */ if ((pt->flags & PROTO_CHILD)) {