📄 jsopcode.c
字号:
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Mozilla Communicator client code, released * March 31, 1998. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** *//* * JS bytecode descriptors, disassemblers, and decompilers. */#include "jsstddef.h"#ifdef HAVE_MEMORY_H#include <memory.h>#endif#include <stdarg.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include "jstypes.h"#include "jsarena.h" /* Added by JSIFY */#include "jsutil.h" /* Added by JSIFY */#include "jsdtoa.h"#include "jsprf.h"#include "jsapi.h"#include "jsarray.h"#include "jsatom.h"#include "jscntxt.h"#include "jsconfig.h"#include "jsdbgapi.h"#include "jsemit.h"#include "jsfun.h"#include "jslock.h"#include "jsobj.h"#include "jsopcode.h"#include "jsscope.h"#include "jsscript.h"#include "jsstr.h"const char js_const_str[] = "const";const char js_var_str[] = "var";const char js_function_str[] = "function";const char js_in_str[] = "in";const char js_instanceof_str[] = "instanceof";const char js_new_str[] = "new";const char js_delete_str[] = "delete";const char js_typeof_str[] = "typeof";const char js_void_str[] = "void";const char js_null_str[] = "null";const char js_this_str[] = "this";const char js_false_str[] = "false";const char js_true_str[] = "true";const char *js_incop_str[] = {"++", "--"};/* Pollute the namespace locally for MSVC Win16, but not for WatCom. */#ifdef __WINDOWS_386__ #ifdef FAR #undef FAR #endif#else /* !__WINDOWS_386__ */#ifndef FAR#define FAR#endif#endif /* !__WINDOWS_386__ */const JSCodeSpec FAR js_CodeSpec[] = {#define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \ {name,token,length,nuses,ndefs,prec,format},#include "jsopcode.tbl"#undef OPDEF};uintN js_NumCodeSpecs = sizeof (js_CodeSpec) / sizeof js_CodeSpec[0];/************************************************************************/static ptrdiff_tGetJumpOffset(jsbytecode *pc, jsbytecode *pc2){ uint32 type; type = (js_CodeSpec[*pc].format & JOF_TYPEMASK); if (JOF_TYPE_IS_EXTENDED_JUMP(type)) return GET_JUMPX_OFFSET(pc2); return GET_JUMP_OFFSET(pc2);}#ifdef DEBUGJS_FRIEND_API(void)js_Disassemble(JSContext *cx, JSScript *script, JSBool lines, FILE *fp){ jsbytecode *pc, *end; uintN len; pc = script->code; end = pc + script->length; while (pc < end) { if (pc == script->main) fputs("main:\n", fp); len = js_Disassemble1(cx, script, pc, PTRDIFF(pc, script->code, jsbytecode), lines, fp); if (!len) return; pc += len; }}JS_FRIEND_API(uintN)js_Disassemble1(JSContext *cx, JSScript *script, jsbytecode *pc, uintN loc, JSBool lines, FILE *fp){ JSOp op; const JSCodeSpec *cs; ptrdiff_t len, off, jmplen; uint32 type; JSAtom *atom; JSString *str; char *cstr; op = (JSOp)*pc; if (op >= JSOP_LIMIT) { char numBuf1[12], numBuf2[12]; JS_snprintf(numBuf1, sizeof numBuf1, "%d", op); JS_snprintf(numBuf2, sizeof numBuf2, "%d", JSOP_LIMIT); JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BYTECODE_TOO_BIG, numBuf1, numBuf2); return 0; } cs = &js_CodeSpec[op]; len = (intN)cs->length; fprintf(fp, "%05u:", loc); if (lines) fprintf(fp, "%4u", JS_PCToLineNumber(cx, script, pc)); fprintf(fp, " %s", cs->name); type = cs->format & JOF_TYPEMASK; switch (type) { case JOF_BYTE: if (op == JSOP_TRAP) { op = JS_GetTrapOpcode(cx, script, pc); if (op == JSOP_LIMIT) return 0; len = (intN)js_CodeSpec[op].length; } break; case JOF_JUMP: case JOF_JUMPX: off = GetJumpOffset(pc, pc); fprintf(fp, " %td (%td)", loc + off, off); break; case JOF_CONST: atom = GET_ATOM(cx, script, pc); str = js_ValueToSource(cx, ATOM_KEY(atom)); if (!str) return 0; cstr = js_DeflateString(cx, JSSTRING_CHARS(str), JSSTRING_LENGTH(str)); if (!cstr) return 0; fprintf(fp, " %s", cstr); JS_free(cx, cstr); break; case JOF_UINT16: fprintf(fp, " %u", GET_ARGC(pc)); break;#if JS_HAS_SWITCH_STATEMENT case JOF_TABLESWITCH: case JOF_TABLESWITCHX: { jsbytecode *pc2; jsint i, low, high; jmplen = (type == JOF_TABLESWITCH) ? JUMP_OFFSET_LEN : JUMPX_OFFSET_LEN; pc2 = pc; off = GetJumpOffset(pc, pc2); pc2 += jmplen; low = GET_JUMP_OFFSET(pc2); pc2 += JUMP_OFFSET_LEN; high = GET_JUMP_OFFSET(pc2); pc2 += JUMP_OFFSET_LEN; fprintf(fp, " defaultOffset %td low %d high %d", off, low, high); for (i = low; i <= high; i++) { off = GetJumpOffset(pc, pc2); fprintf(fp, "\n\t%d: %td", i, off); pc2 += jmplen; } len = 1 + pc2 - pc; break; } case JOF_LOOKUPSWITCH: case JOF_LOOKUPSWITCHX: { jsbytecode *pc2; jsint npairs; jmplen = (type == JOF_LOOKUPSWITCH) ? JUMP_OFFSET_LEN : JUMPX_OFFSET_LEN; pc2 = pc; off = GetJumpOffset(pc, pc2); pc2 += jmplen; npairs = (jsint) GET_ATOM_INDEX(pc2); pc2 += ATOM_INDEX_LEN; fprintf(fp, " offset %td npairs %u", off, (uintN) npairs); while (npairs) { atom = GET_ATOM(cx, script, pc2); pc2 += ATOM_INDEX_LEN; off = GetJumpOffset(pc, pc2); pc2 += jmplen; str = js_ValueToSource(cx, ATOM_KEY(atom)); if (!str) return 0; cstr = js_DeflateString(cx, JSSTRING_CHARS(str), JSSTRING_LENGTH(str)); if (!cstr) return 0; fprintf(fp, "\n\t%s: %td", cstr, off); JS_free(cx, cstr); npairs--; } len = 1 + pc2 - pc; break; }#endif /* JS_HAS_SWITCH_STATEMENT */ case JOF_QARG: fprintf(fp, " %u", GET_ARGNO(pc)); break; case JOF_QVAR: fprintf(fp, " %u", GET_VARNO(pc)); break;#if JS_HAS_LEXICAL_CLOSURE case JOF_DEFLOCALVAR: fprintf(fp, " %u", GET_VARNO(pc)); pc += VARNO_LEN; atom = GET_ATOM(cx, script, pc); str = js_ValueToSource(cx, ATOM_KEY(atom)); if (!str) return 0; cstr = js_DeflateString(cx, JSSTRING_CHARS(str), JSSTRING_LENGTH(str)); if (!cstr) return 0; fprintf(fp, " %s", cstr); JS_free(cx, cstr); break;#endif default: { char numBuf[12]; JS_snprintf(numBuf, sizeof numBuf, "%lx", (unsigned long) cs->format); JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_UNKNOWN_FORMAT, numBuf); return 0; } } fputs("\n", fp); return len;}#endif /* DEBUG *//************************************************************************//* * Sprintf, but with unlimited and automatically allocated buffering. */typedef struct Sprinter { JSContext *context; /* context executing the decompiler */ JSArenaPool *pool; /* string allocation pool */ char *base; /* base address of buffer in pool */ size_t size; /* size of buffer allocated at base */ ptrdiff_t offset; /* offset of next free char in buffer */} Sprinter;#define INIT_SPRINTER(cx, sp, ap, off) \ ((sp)->context = cx, (sp)->pool = ap, (sp)->base = NULL, (sp)->size = 0, \ (sp)->offset = off)#define OFF2STR(sp,off) ((sp)->base + (off))#define STR2OFF(sp,str) ((str) - (sp)->base)#define RETRACT(sp,str) ((sp)->offset = STR2OFF(sp, str))static JSBoolSprintAlloc(Sprinter *sp, size_t nb){ if (!sp->base) { JS_ARENA_ALLOCATE_CAST(sp->base, char *, sp->pool, nb); } else { JS_ARENA_GROW_CAST(sp->base, char *, sp->pool, sp->size, nb); } if (!sp->base) { JS_ReportOutOfMemory(sp->context); return JS_FALSE; } sp->size += nb; return JS_TRUE;}static ptrdiff_tSprintPut(Sprinter *sp, const char *s, size_t len){ ptrdiff_t nb, offset; char *bp; /* Allocate space for s, including the '\0' at the end. */ nb = (sp->offset + len + 1) - sp->size; if (nb > 0 && !SprintAlloc(sp, nb)) return -1; /* Advance offset and copy s into sp's buffer. */ offset = sp->offset; sp->offset += len; bp = sp->base + offset; memmove(bp, s, len); bp[len] = 0; return offset;}static ptrdiff_tSprint(Sprinter *sp, const char *format, ...){ va_list ap; char *bp; ptrdiff_t offset; va_start(ap, format); bp = JS_vsmprintf(format, ap); /* XXX vsaprintf */ va_end(ap); if (!bp) { JS_ReportOutOfMemory(sp->context); return -1; } offset = SprintPut(sp, bp, strlen(bp)); free(bp); return offset;}const jschar js_EscapeMap[] = { '\b', 'b', '\f', 'f', '\n', 'n',
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -