forked from parca-dev/parca-agent
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Works with openresty and luajit with caveats. lua_State is looked up via uprobes on lua_pcall and lua_resume. If uprobes aren't enabled an attempt will be made to look up lua_State via nginx_lua_co_ctx object which seems to work well for openresty but isn't well tested. Fixes: parca-dev#1889
- Loading branch information
Showing
24 changed files
with
3,514 additions
and
24 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,270 @@ | ||
/* | ||
** Bytecode instruction format. | ||
** Copyright (C) 2005-2023 Mike Pall. See Copyright Notice in luajit.h | ||
*/ | ||
|
||
#ifndef _LJ_BC_H | ||
#define _LJ_BC_H | ||
|
||
// #include "lj_def.h" | ||
// #include "lj_arch.h" | ||
|
||
/* Bytecode instruction format, 32 bit wide, fields of 8 or 16 bit: | ||
** | ||
** +----+----+----+----+ | ||
** | B | C | A | OP | Format ABC | ||
** +----+----+----+----+ | ||
** | D | A | OP | Format AD | ||
** +-------------------- | ||
** MSB LSB | ||
** | ||
** In-memory instructions are always stored in host byte order. | ||
*/ | ||
|
||
/* Operand ranges and related constants. */ | ||
#define BCMAX_A 0xff | ||
#define BCMAX_B 0xff | ||
#define BCMAX_C 0xff | ||
#define BCMAX_D 0xffff | ||
#define BCBIAS_J 0x8000 | ||
#define NO_REG BCMAX_A | ||
#define NO_JMP (~(BCPos)0) | ||
|
||
/* Macros to get instruction fields. */ | ||
#define bc_op(i) ((BCOp)((i) & 0xff)) | ||
#define bc_a(i) ((BCReg)(((i) >> 8) & 0xff)) | ||
#define bc_b(i) ((BCReg)((i) >> 24)) | ||
#define bc_c(i) ((BCReg)(((i) >> 16) & 0xff)) | ||
#define bc_d(i) ((BCReg)((i) >> 16)) | ||
#define bc_j(i) ((ptrdiff_t)bc_d(i) - BCBIAS_J) | ||
|
||
/* Macros to set instruction fields. */ | ||
#define setbc_byte(p, x, ofs) ((uint8_t *)(p))[LJ_ENDIAN_SELECT(ofs, 3 - ofs)] = (uint8_t)(x) | ||
#define setbc_op(p, x) setbc_byte(p, (x), 0) | ||
#define setbc_a(p, x) setbc_byte(p, (x), 1) | ||
#define setbc_b(p, x) setbc_byte(p, (x), 3) | ||
#define setbc_c(p, x) setbc_byte(p, (x), 2) | ||
#define setbc_d(p, x) ((uint16_t *)(p))[LJ_ENDIAN_SELECT(1, 0)] = (uint16_t)(x) | ||
#define setbc_j(p, x) setbc_d(p, (BCPos)((int32_t)(x) + BCBIAS_J)) | ||
|
||
/* Macros to compose instructions. */ | ||
#define BCINS_ABC(o, a, b, c) (((BCIns)(o)) | ((BCIns)(a) << 8) | ((BCIns)(b) << 24) | ((BCIns)(c) << 16)) | ||
#define BCINS_AD(o, a, d) (((BCIns)(o)) | ((BCIns)(a) << 8) | ((BCIns)(d) << 16)) | ||
#define BCINS_AJ(o, a, j) BCINS_AD(o, a, (BCPos)((int32_t)(j) + BCBIAS_J)) | ||
|
||
/* Bytecode instruction definition. Order matters, see below. | ||
** | ||
** (name, filler, Amode, Bmode, Cmode or Dmode, metamethod) | ||
** | ||
** The opcode name suffixes specify the type for RB/RC or RD: | ||
** V = variable slot | ||
** S = string const | ||
** N = number const | ||
** P = primitive type (~itype) | ||
** B = unsigned byte literal | ||
** M = multiple args/results | ||
*/ | ||
#define BCDEF(_) \ | ||
/* Comparison ops. ORDER OPR. */ \ | ||
_(ISLT, var, ___, var, lt) \ | ||
_(ISGE, var, ___, var, lt) \ | ||
_(ISLE, var, ___, var, le) \ | ||
_(ISGT, var, ___, var, le) \ | ||
\ | ||
_(ISEQV, var, ___, var, eq) \ | ||
_(ISNEV, var, ___, var, eq) \ | ||
_(ISEQS, var, ___, str, eq) \ | ||
_(ISNES, var, ___, str, eq) \ | ||
_(ISEQN, var, ___, num, eq) \ | ||
_(ISNEN, var, ___, num, eq) \ | ||
_(ISEQP, var, ___, pri, eq) \ | ||
_(ISNEP, var, ___, pri, eq) \ | ||
\ | ||
/* Unary test and copy ops. */ \ | ||
_(ISTC, dst, ___, var, ___) \ | ||
_(ISFC, dst, ___, var, ___) \ | ||
_(IST, ___, ___, var, ___) \ | ||
_(ISF, ___, ___, var, ___) \ | ||
_(ISTYPE, var, ___, lit, ___) \ | ||
_(ISNUM, var, ___, lit, ___) \ | ||
\ | ||
/* Unary ops. */ \ | ||
_(MOV, dst, ___, var, ___) \ | ||
_(NOT, dst, ___, var, ___) \ | ||
_(UNM, dst, ___, var, unm) \ | ||
_(LEN, dst, ___, var, len) \ | ||
\ | ||
/* Binary ops. ORDER OPR. VV last, POW must be next. */ \ | ||
_(ADDVN, dst, var, num, add) \ | ||
_(SUBVN, dst, var, num, sub) \ | ||
_(MULVN, dst, var, num, mul) \ | ||
_(DIVVN, dst, var, num, div) \ | ||
_(MODVN, dst, var, num, mod) \ | ||
\ | ||
_(ADDNV, dst, var, num, add) \ | ||
_(SUBNV, dst, var, num, sub) \ | ||
_(MULNV, dst, var, num, mul) \ | ||
_(DIVNV, dst, var, num, div) \ | ||
_(MODNV, dst, var, num, mod) \ | ||
\ | ||
_(ADDVV, dst, var, var, add) \ | ||
_(SUBVV, dst, var, var, sub) \ | ||
_(MULVV, dst, var, var, mul) \ | ||
_(DIVVV, dst, var, var, div) \ | ||
_(MODVV, dst, var, var, mod) \ | ||
\ | ||
_(POW, dst, var, var, pow) \ | ||
_(CAT, dst, rbase, rbase, concat) \ | ||
\ | ||
/* Constant ops. */ \ | ||
_(KSTR, dst, ___, str, ___) \ | ||
_(KCDATA, dst, ___, cdata, ___) \ | ||
_(KSHORT, dst, ___, lits, ___) \ | ||
_(KNUM, dst, ___, num, ___) \ | ||
_(KPRI, dst, ___, pri, ___) \ | ||
_(KNIL, base, ___, base, ___) \ | ||
\ | ||
/* Upvalue and function ops. */ \ | ||
_(UGET, dst, ___, uv, ___) \ | ||
_(USETV, uv, ___, var, ___) \ | ||
_(USETS, uv, ___, str, ___) \ | ||
_(USETN, uv, ___, num, ___) \ | ||
_(USETP, uv, ___, pri, ___) \ | ||
_(UCLO, rbase, ___, jump, ___) \ | ||
_(FNEW, dst, ___, func, gc) \ | ||
\ | ||
/* Table ops. */ \ | ||
_(TNEW, dst, ___, lit, gc) \ | ||
_(TDUP, dst, ___, tab, gc) \ | ||
_(GGET, dst, ___, str, index) \ | ||
_(GSET, var, ___, str, newindex) \ | ||
_(TGETV, dst, var, var, index) \ | ||
_(TGETS, dst, var, str, index) \ | ||
_(TGETB, dst, var, lit, index) \ | ||
_(TGETR, dst, var, var, index) \ | ||
_(TSETV, var, var, var, newindex) \ | ||
_(TSETS, var, var, str, newindex) \ | ||
_(TSETB, var, var, lit, newindex) \ | ||
_(TSETM, base, ___, num, newindex) \ | ||
_(TSETR, var, var, var, newindex) \ | ||
\ | ||
/* Calls and vararg handling. T = tail call. */ \ | ||
_(CALLM, base, lit, lit, call) \ | ||
_(CALL, base, lit, lit, call) \ | ||
_(CALLMT, base, ___, lit, call) \ | ||
_(CALLT, base, ___, lit, call) \ | ||
_(ITERC, base, lit, lit, call) \ | ||
_(ITERN, base, lit, lit, call) \ | ||
_(VARG, base, lit, lit, ___) \ | ||
_(ISNEXT, base, ___, jump, ___) \ | ||
\ | ||
/* Returns. */ \ | ||
_(RETM, base, ___, lit, ___) \ | ||
_(RET, rbase, ___, lit, ___) \ | ||
_(RET0, rbase, ___, lit, ___) \ | ||
_(RET1, rbase, ___, lit, ___) \ | ||
\ | ||
/* Loops and branches. I/J = interp/JIT, I/C/L = init/call/loop. */ \ | ||
_(FORI, base, ___, jump, ___) \ | ||
_(JFORI, base, ___, jump, ___) \ | ||
\ | ||
_(FORL, base, ___, jump, ___) \ | ||
_(IFORL, base, ___, jump, ___) \ | ||
_(JFORL, base, ___, lit, ___) \ | ||
\ | ||
_(ITERL, base, ___, jump, ___) \ | ||
_(IITERL, base, ___, jump, ___) \ | ||
_(JITERL, base, ___, lit, ___) \ | ||
\ | ||
_(LOOP, rbase, ___, jump, ___) \ | ||
_(ILOOP, rbase, ___, jump, ___) \ | ||
_(JLOOP, rbase, ___, lit, ___) \ | ||
\ | ||
_(JMP, rbase, ___, jump, ___) \ | ||
\ | ||
/* Function headers. I/J = interp/JIT, F/V/C = fixarg/vararg/C func. */ \ | ||
_(FUNCF, rbase, ___, ___, ___) \ | ||
_(IFUNCF, rbase, ___, ___, ___) \ | ||
_(JFUNCF, rbase, ___, lit, ___) \ | ||
_(FUNCV, rbase, ___, ___, ___) \ | ||
_(IFUNCV, rbase, ___, ___, ___) \ | ||
_(JFUNCV, rbase, ___, lit, ___) \ | ||
_(FUNCC, rbase, ___, ___, ___) \ | ||
_(FUNCCW, rbase, ___, ___, ___) | ||
|
||
/* Bytecode opcode numbers. */ | ||
typedef enum { | ||
#define BCENUM(name, ma, mb, mc, mt) BC_##name, | ||
BCDEF(BCENUM) | ||
#undef BCENUM | ||
BC__MAX | ||
} BCOp; | ||
|
||
LJ_STATIC_ASSERT((int)BC_ISEQV + 1 == (int)BC_ISNEV); | ||
LJ_STATIC_ASSERT(((int)BC_ISEQV ^ 1) == (int)BC_ISNEV); | ||
LJ_STATIC_ASSERT(((int)BC_ISEQS ^ 1) == (int)BC_ISNES); | ||
LJ_STATIC_ASSERT(((int)BC_ISEQN ^ 1) == (int)BC_ISNEN); | ||
LJ_STATIC_ASSERT(((int)BC_ISEQP ^ 1) == (int)BC_ISNEP); | ||
LJ_STATIC_ASSERT(((int)BC_ISLT ^ 1) == (int)BC_ISGE); | ||
LJ_STATIC_ASSERT(((int)BC_ISLE ^ 1) == (int)BC_ISGT); | ||
LJ_STATIC_ASSERT(((int)BC_ISLT ^ 3) == (int)BC_ISGT); | ||
LJ_STATIC_ASSERT((int)BC_IST - (int)BC_ISTC == (int)BC_ISF - (int)BC_ISFC); | ||
LJ_STATIC_ASSERT((int)BC_CALLT - (int)BC_CALL == (int)BC_CALLMT - (int)BC_CALLM); | ||
LJ_STATIC_ASSERT((int)BC_CALLMT + 1 == (int)BC_CALLT); | ||
LJ_STATIC_ASSERT((int)BC_RETM + 1 == (int)BC_RET); | ||
LJ_STATIC_ASSERT((int)BC_FORL + 1 == (int)BC_IFORL); | ||
LJ_STATIC_ASSERT((int)BC_FORL + 2 == (int)BC_JFORL); | ||
LJ_STATIC_ASSERT((int)BC_ITERL + 1 == (int)BC_IITERL); | ||
LJ_STATIC_ASSERT((int)BC_ITERL + 2 == (int)BC_JITERL); | ||
LJ_STATIC_ASSERT((int)BC_LOOP + 1 == (int)BC_ILOOP); | ||
LJ_STATIC_ASSERT((int)BC_LOOP + 2 == (int)BC_JLOOP); | ||
LJ_STATIC_ASSERT((int)BC_FUNCF + 1 == (int)BC_IFUNCF); | ||
LJ_STATIC_ASSERT((int)BC_FUNCF + 2 == (int)BC_JFUNCF); | ||
LJ_STATIC_ASSERT((int)BC_FUNCV + 1 == (int)BC_IFUNCV); | ||
LJ_STATIC_ASSERT((int)BC_FUNCV + 2 == (int)BC_JFUNCV); | ||
|
||
/* This solves a circular dependency problem, change as needed. */ | ||
#define FF_next_N 4 | ||
|
||
/* Stack slots used by FORI/FORL, relative to operand A. */ | ||
enum { FORL_IDX, FORL_STOP, FORL_STEP, FORL_EXT }; | ||
|
||
/* Bytecode operand modes. ORDER BCMode */ | ||
typedef enum { | ||
BCMnone, | ||
BCMdst, | ||
BCMbase, | ||
BCMvar, | ||
BCMrbase, | ||
BCMuv, /* Mode A must be <= 7 */ | ||
BCMlit, | ||
BCMlits, | ||
BCMpri, | ||
BCMnum, | ||
BCMstr, | ||
BCMtab, | ||
BCMfunc, | ||
BCMjump, | ||
BCMcdata, | ||
BCM_max | ||
} BCMode; | ||
#define BCM___ BCMnone | ||
|
||
#define bcmode_a(op) ((BCMode)(lj_bc_mode[op] & 7)) | ||
#define bcmode_b(op) ((BCMode)((lj_bc_mode[op] >> 3) & 15)) | ||
#define bcmode_c(op) ((BCMode)((lj_bc_mode[op] >> 7) & 15)) | ||
#define bcmode_d(op) bcmode_c(op) | ||
#define bcmode_hasd(op) ((lj_bc_mode[op] & (15 << 3)) == (BCMnone << 3)) | ||
#define bcmode_mm(op) ((MMS)(lj_bc_mode[op] >> 11)) | ||
|
||
#define BCMODE(name, ma, mb, mc, mm) (BCM##ma | (BCM##mb << 3) | (BCM##mc << 7) | (MM_##mm << 11)), | ||
#define BCMODE_FF 0 | ||
|
||
static LJ_AINLINE int bc_isret(BCOp op) { | ||
return (op == BC_RETM || op == BC_RET || op == BC_RET0 || op == BC_RET1); | ||
} | ||
|
||
LJ_DATA const uint16_t lj_bc_mode[]; | ||
LJ_DATA const uint16_t lj_bc_ofs[]; | ||
|
||
#endif |
Oops, something went wrong.