Remove old JIT implementation (#12498)

* Remove old JIT implementation

* Remove ext/opcache/jit/zend_jit_vtune.c
This commit is contained in:
Dmitry Stogov 2023-10-24 11:37:58 +03:00 committed by GitHub
parent e58af7c160
commit be275433d9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
55 changed files with 21 additions and 69086 deletions

View file

@ -119,9 +119,6 @@ clean:
find . -name \*.so | xargs rm -f find . -name \*.so | xargs rm -f
find . -name .libs -a -type d|xargs rm -rf find . -name .libs -a -type d|xargs rm -rf
rm -f libphp.la $(SAPI_CLI_PATH) $(SAPI_CGI_PATH) $(SAPI_LITESPEED_PATH) $(SAPI_FPM_PATH) $(OVERALL_TARGET) modules/* libs/* rm -f libphp.la $(SAPI_CLI_PATH) $(SAPI_CGI_PATH) $(SAPI_LITESPEED_PATH) $(SAPI_FPM_PATH) $(OVERALL_TARGET) modules/* libs/*
rm -f ext/opcache/jit/zend_jit_x86.c
rm -f ext/opcache/jit/zend_jit_arm64.c
rm -f ext/opcache/minilua
rm -f ext/opcache/jit/ir/gen_ir_fold_hash rm -f ext/opcache/jit/ir/gen_ir_fold_hash
rm -f ext/opcache/jit/ir/minilua rm -f ext/opcache/jit/ir/minilua
rm -f ext/opcache/jit/ir/ir_fold_hash.h rm -f ext/opcache/jit/ir/ir_fold_hash.h

View file

@ -24,13 +24,6 @@ PHP_ARG_WITH([capstone],,
[no], [no],
[no]) [no])
PHP_ARG_ENABLE([opcache-jit-ir],
[whether to enable JIT based on IR framework],
[AS_HELP_STRING([--disable-opcache-jit-ir],
[Disable JIT based on IR framework (use old JIT)])],
[yes],
[no])
if test "$PHP_OPCACHE" != "no"; then if test "$PHP_OPCACHE" != "no"; then
dnl Always build as shared extension dnl Always build as shared extension
@ -51,52 +44,7 @@ if test "$PHP_OPCACHE" != "no"; then
esac esac
fi fi
if test "$PHP_OPCACHE_JIT" = "yes" -a "$PHP_OPCACHE_JIT_IR" = "no" ; then if test "$PHP_OPCACHE_JIT" = "yes" ; then
AC_DEFINE(HAVE_JIT, 1, [Define to enable JIT])
ZEND_JIT_SRC="jit/zend_jit.c jit/zend_jit_gdb.c jit/zend_jit_vm_helpers.c"
dnl Find out which ABI we are using.
case $host_alias in
x86_64-*-darwin*)
DASM_FLAGS="-D X64APPLE=1 -D X64=1"
DASM_ARCH="x86"
;;
x86_64*)
DASM_FLAGS="-D X64=1"
DASM_ARCH="x86"
;;
i[[34567]]86*)
DASM_ARCH="x86"
;;
x86*)
DASM_ARCH="x86"
;;
aarch64*)
DASM_FLAGS="-D ARM64=1"
DASM_ARCH="arm64"
;;
esac
if test "$PHP_THREAD_SAFETY" = "yes"; then
DASM_FLAGS="$DASM_FLAGS -D ZTS=1"
fi
AS_IF([test x"$with_capstone" = "xyes"],[
PKG_CHECK_MODULES([CAPSTONE],[capstone >= 3.0.0],[
AC_DEFINE([HAVE_CAPSTONE], [1], [Capstone is available])
PHP_EVAL_LIBLINE($CAPSTONE_LIBS, OPCACHE_SHARED_LIBADD)
PHP_EVAL_INCLINE($CAPSTONE_CFLAGS)
],[
AC_MSG_ERROR([capstone >= 3.0 required but not found])
])
])
PHP_SUBST(DASM_FLAGS)
PHP_SUBST(DASM_ARCH)
JIT_CFLAGS=
elif test "$PHP_OPCACHE_JIT" = "yes" -a "$PHP_OPCACHE_JIT_IR" = "yes"; then
AC_DEFINE(HAVE_JIT, 1, [Define to enable JIT]) AC_DEFINE(HAVE_JIT, 1, [Define to enable JIT])
AC_DEFINE(ZEND_JIT_IR, 1, [Use JIT IR framework]) AC_DEFINE(ZEND_JIT_IR, 1, [Use JIT IR framework])
ZEND_JIT_SRC="jit/zend_jit.c jit/zend_jit_vm_helpers.c jit/ir/ir.c jit/ir/ir_strtab.c \ ZEND_JIT_SRC="jit/zend_jit.c jit/zend_jit_vm_helpers.c jit/ir/ir.c jit/ir/ir_strtab.c \
@ -383,9 +331,7 @@ int main(void) {
if test "$PHP_OPCACHE_JIT" = "yes"; then if test "$PHP_OPCACHE_JIT" = "yes"; then
PHP_ADD_BUILD_DIR([$ext_builddir/jit], 1) PHP_ADD_BUILD_DIR([$ext_builddir/jit], 1)
if test "$PHP_OPCACHE_JIT_IR" = "yes"; then PHP_ADD_BUILD_DIR([$ext_builddir/jit/ir], 1)
PHP_ADD_BUILD_DIR([$ext_builddir/jit/ir], 1)
fi
PHP_ADD_MAKEFILE_FRAGMENT($ext_srcdir/jit/Makefile.frag) PHP_ADD_MAKEFILE_FRAGMENT($ext_srcdir/jit/Makefile.frag)
fi fi
PHP_SUBST(OPCACHE_SHARED_LIBADD) PHP_SUBST(OPCACHE_SHARED_LIBADD)

View file

@ -5,8 +5,6 @@ if (PHP_OPCACHE != "no") {
ARG_ENABLE("opcache-jit", "whether to enable JIT", "yes"); ARG_ENABLE("opcache-jit", "whether to enable JIT", "yes");
ARG_ENABLE("opcache-jit-ir", "whether to enable JIT based on IR framework", "yes");
ZEND_EXTENSION('opcache', "\ ZEND_EXTENSION('opcache', "\
ZendAccelerator.c \ ZendAccelerator.c \
zend_accelerator_blacklist.c \ zend_accelerator_blacklist.c \
@ -20,26 +18,7 @@ if (PHP_OPCACHE != "no") {
zend_shared_alloc.c \ zend_shared_alloc.c \
shared_alloc_win32.c", true, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1"); shared_alloc_win32.c", true, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1");
if (PHP_OPCACHE_JIT == "yes" && PHP_OPCACHE_JIT_IR == "no") { if (PHP_OPCACHE_JIT == "yes") {
if (CHECK_HEADER_ADD_INCLUDE("dynasm/dasm_x86.h", "CFLAGS_OPCACHE", PHP_OPCACHE + ";ext\\opcache\\jit")) {
var dasm_flags = (X64 ? "-D X64=1" : "") + (X64 ? " -D X64WIN=1" : "") + " -D WIN=1";
if (PHP_ZTS == "yes") {
dasm_flags += " -D ZTS=1";
}
DEFINE("DASM_FLAGS", dasm_flags);
DEFINE("DASM_ARCH", "x86");
AC_DEFINE('HAVE_JIT', 1, 'Define to enable JIT');
/* XXX read this dynamically */
/*ADD_FLAG("CFLAGS_OPCACHE", "/D DASM_VERSION=10400");*/
ADD_MAKEFILE_FRAGMENT(configure_module_dirname + "\\jit\\Makefile.frag.w32");
ADD_SOURCES(configure_module_dirname + "\\jit", "zend_jit.c zend_jit_vm_helpers.c", "opcache", "ext\\opcache\\jit");
} else {
WARNING("JIT not enabled, headers not found");
}
} else if (PHP_OPCACHE_JIT == "yes" && PHP_OPCACHE_JIT_IR == "yes") {
if (CHECK_HEADER_ADD_INCLUDE("ir/ir.h", "CFLAGS_OPCACHE", PHP_OPCACHE + ";ext\\opcache\\jit")) { if (CHECK_HEADER_ADD_INCLUDE("ir/ir.h", "CFLAGS_OPCACHE", PHP_OPCACHE + ";ext\\opcache\\jit")) {
var dasm_flags = (X64 ? "-D X64=1" : "") + (X64 ? " -D X64WIN=1" : "") + " -D WIN=1"; var dasm_flags = (X64 ? "-D X64=1" : "") + (X64 ? " -D X64WIN=1" : "") + " -D WIN=1";
var ir_target = (X64 ? "IR_TARGET_X64" : "IR_TARGET_X86"); var ir_target = (X64 ? "IR_TARGET_X64" : "IR_TARGET_X86");

View file

@ -1,5 +1,3 @@
ifdef IR_TARGET
# New IR based JIT
$(builddir)/jit/ir/minilua: $(srcdir)/jit/ir/dynasm/minilua.c $(builddir)/jit/ir/minilua: $(srcdir)/jit/ir/dynasm/minilua.c
$(BUILD_CC) $(srcdir)/jit/ir/dynasm/minilua.c -lm -o $@ $(BUILD_CC) $(srcdir)/jit/ir/dynasm/minilua.c -lm -o $@
@ -22,26 +20,6 @@ $(builddir)/jit/zend_jit.lo: \
$(srcdir)/jit/zend_jit_helpers.c \ $(srcdir)/jit/zend_jit_helpers.c \
$(srcdir)/jit/zend_jit_ir.c $(srcdir)/jit/zend_jit_ir.c
else
# Old DynAsm based JIT
$(builddir)/minilua: $(srcdir)/jit/dynasm/minilua.c
$(BUILD_CC) $(srcdir)/jit/dynasm/minilua.c -lm -o $@
$(builddir)/jit/zend_jit_$(DASM_ARCH).c: $(srcdir)/jit/zend_jit_$(DASM_ARCH).dasc $(srcdir)/jit/dynasm/*.lua $(builddir)/minilua
$(builddir)/minilua $(srcdir)/jit/dynasm/dynasm.lua $(DASM_FLAGS) -o $@ $(srcdir)/jit/zend_jit_$(DASM_ARCH).dasc
$(builddir)/jit/zend_jit.lo: \
$(builddir)/jit/zend_jit_$(DASM_ARCH).c \
$(srcdir)/jit/zend_jit_helpers.c \
$(srcdir)/jit/zend_jit_disasm.c \
$(srcdir)/jit/zend_jit_gdb.c \
$(srcdir)/jit/zend_jit_perf_dump.c \
$(srcdir)/jit/zend_jit_vtune.c \
$(srcdir)/jit/zend_jit_trace.c \
$(srcdir)/jit/zend_elf.c
endif
# For non-GNU make, jit/zend_jit.lo and ./jit/zend_jit.lo are considered distinct targets. # For non-GNU make, jit/zend_jit.lo and ./jit/zend_jit.lo are considered distinct targets.
# Use this workaround to allow building from inside ext/opcache. # Use this workaround to allow building from inside ext/opcache.
jit/zend_jit.lo: $(builddir)/jit/zend_jit.lo jit/zend_jit.lo: $(builddir)/jit/zend_jit.lo

View file

@ -1,6 +1,3 @@
!if "$(IR_TARGET)" != ""
# New IR based JIT
$(BUILD_DIR)\\minilua.exe: ext\opcache\jit\ir\dynasm\minilua.c $(BUILD_DIR)\\minilua.exe: ext\opcache\jit\ir\dynasm\minilua.c
@if exist $(BUILD_DIR)\\minilua.exe del $(BUILD_DIR)\\minilua.exe @if exist $(BUILD_DIR)\\minilua.exe del $(BUILD_DIR)\\minilua.exe
$(PHP_CL) /Fo$(BUILD_DIR)\ /Fd$(BUILD_DIR)\ /Fp$(BUILD_DIR)\ /FR$(BUILD_DIR) /Fe$(BUILD_DIR)\minilua.exe ext\opcache\jit\ir\dynasm\minilua.c $(PHP_CL) /Fo$(BUILD_DIR)\ /Fd$(BUILD_DIR)\ /Fp$(BUILD_DIR)\ /FR$(BUILD_DIR) /Fe$(BUILD_DIR)\minilua.exe ext\opcache\jit\ir\dynasm\minilua.c
@ -39,24 +36,3 @@ $(BUILD_DIR)\ext\opcache\jit\zend_jit.obj: \
ext\opcache\jit\zend_jit_helpers.c \ ext\opcache\jit\zend_jit_helpers.c \
ext\opcache\jit\ir\ir.h \ ext\opcache\jit\ir\ir.h \
ext\opcache\jit\ir\ir_builder.h ext\opcache\jit\ir\ir_builder.h
!else
# Old DynAsm based JIT
$(BUILD_DIR)\\minilua.exe: ext\opcache\jit\dynasm\minilua.c
@if exist $(BUILD_DIR)\\minilua.exe del $(BUILD_DIR)\\minilua.exe
$(PHP_CL) /Fo$(BUILD_DIR)\ /Fd$(BUILD_DIR)\ /Fp$(BUILD_DIR)\ /FR$(BUILD_DIR) /Fe$(BUILD_DIR)\minilua.exe ext\opcache\jit\dynasm\minilua.c
ext\opcache\jit\zend_jit_x86.c: ext\opcache\jit\zend_jit_x86.dasc $(BUILD_DIR)\\minilua.exe
@if exist ext\opcache\jit\zend_jit_x86.c del ext\opcache\jit\zend_jit_x86.c
$(BUILD_DIR)\\minilua.exe ext/opcache/jit/dynasm/dynasm.lua $(DASM_FLAGS) -o $@ ext/opcache/jit/zend_jit_x86.dasc
$(BUILD_DIR)\ext\opcache\jit\zend_jit.obj: \
ext/opcache/jit/zend_jit_x86.c \
ext/opcache/jit/zend_jit_helpers.c \
ext/opcache/jit/zend_jit_disasm.c \
ext/opcache/jit/zend_jit_gdb.c \
ext/opcache/jit/zend_jit_perf_dump.c \
ext/opcache/jit/zend_jit_trace.c \
ext/opcache/jit/zend_jit_vtune.c
!endif

View file

@ -1,32 +0,0 @@
New JIT implementation
======================
This branch provides a new JIT implementation based on [IR - Lightweight
JIT Compilation Framework](https://github.com/dstogov/ir).
As opposed to the PHP 8.* JIT approach that generates native code directly from
PHP byte-code, this implementation generates intermediate representation (IR)
and delegates all lower-level tasks to the IR Framework. IR for JIT is like an
AST for compiler.
Key benefits of the new JIT implementation:
- Usage of IR opens possibilities for better optimization and register
allocation (the resulting native code is more efficient)
- PHP doesn't have to care about most low-level details (different CPUs,
calling conventions, TLS details, etc)
- it's much easier to implement support for new targets (e.g. RISCV)
- IR framework is going to be developed separately from PHP and may accept
contributions from other projects (new optimizations, improvements, bug fixes)
Disadvantages:
- JIT compilation becomes slower (this is almost invisible for tracing
JIT, but function JIT compilation of Wordpress becomes 4 times slower)
The necessary part of the IR Framework is embedded into php-src. So, the PR
doesn't introduce new dependencies.
The new JIT implementation successfully passes all CI workflows, but it's still
not mature and may cause failures. To reduce risks, this patch doesn't remove
the old JIT implementation (that is the same as PHP-8.3 JIT). It's possible
to build PHP with the old JIT by configuring with **--disable-opcache-jit-ir**.
In the future the old implementation should be removed.

View file

@ -2,33 +2,10 @@ Opcache JIT
=========== ===========
This is the implementation of Opcache's JIT (Just-In-Time compiler), This is the implementation of Opcache's JIT (Just-In-Time compiler),
This converts the PHP Virtual Machine's opcodes into x64/x86 assembly, This converts the PHP Virtual Machine's opcodes into Intermediate
on POSIX platforms and Windows. Representation and uses [IR - Lightweight JIT Compilation Framework](https://github.com/dstogov/ir)
to produce optimized native code. The necessary part of the IR
It generates native code directly from PHP byte-code and information collected Framework is embedded into php-src.
by the SSA static analysis framework (a part of the opcache optimizer).
Code is usually generated separately for each PHP byte-code instruction. Only
a few combinations are considered together (e.g. compare + conditional jump).
See [the JIT RFC](https://wiki.php.net/rfc/jit) for more details.
DynAsm
------
This uses [DynAsm](https://luajit.org/dynasm.html) (developed for LuaJIT project)
for the generation of native code. It's a very lightweight and advanced tool,
but does assume good, and very low-level development knowledge of target
assembler languages. In the past we tried LLVM, but its code generation speed
was almost 100 times slower, making it prohibitively expensive to use.
[The unofficial DynASM Documentation](https://corsix.github.io/dynasm-doc/tutorial.html)
has a tutorial, reference, and instruction listing.
In x86 builds, `zend_jit_x86.dasc` gets automatically converted to `zend_jit_x86.c` by the bundled
`dynasm` during `make`.
In arm64 builds, `zend_jit_arm64.dasc` gets automatically converted to `zend_jit_arm64.c` by the bundled
`dynasm` during `make`.
Running tests of the JIT Running tests of the JIT
------------------------ ------------------------
@ -62,17 +39,6 @@ Note that the JIT supports 3 different architectures: `X86_64`, `i386`, and `arm
Miscellaneous Miscellaneous
------------- -------------
### Checking dasc files for in a different architecture
The following command can be run to manually check if the modified `.dasc code` is at least transpilable
for an architecture you're not using, e.g.:
For arm64: `ext/opcache/minilua ext/opcache/jit/dynasm/dynasm.lua -D ARM64=1 -o ext/opcache/jit/zend_jit_arm64.ignored.c ext/opcache/jit/zend_jit_arm64.dasc`
For x86_64: `ext/opcache/minilua ext/opcache/jit/dynasm/dynasm.lua -D X64=1 -o ext/opcache/jit/zend_jit_x86.ignored.c ext/opcache/jit/zend_jit_x86.dasc`
For i386 (i.e. 32-bit): `ext/opcache/minilua ext/opcache/jit/dynasm/dynasm.lua -o ext/opcache/jit/zend_jit_x86.ignored.c ext/opcache/jit/zend_jit_x86.dasc`
### How to build 32-bit builds on x86_64 environments ### How to build 32-bit builds on x86_64 environments
Refer to [../../../.github/workflows/push.yml](../../../.github/workflows/push.yml) for examples of Refer to [../../../.github/workflows/push.yml](../../../.github/workflows/push.yml) for examples of

View file

@ -1,461 +0,0 @@
/*
** DynASM ARM encoding engine.
** Copyright (C) 2005-2021 Mike Pall. All rights reserved.
** Released under the MIT license. See dynasm.lua for full copyright notice.
*/
#include <stddef.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#define DASM_ARCH "arm"
#ifndef DASM_EXTERN
#define DASM_EXTERN(a,b,c,d) 0
#endif
/* Action definitions. */
enum {
DASM_STOP, DASM_SECTION, DASM_ESC, DASM_REL_EXT,
/* The following actions need a buffer position. */
DASM_ALIGN, DASM_REL_LG, DASM_LABEL_LG,
/* The following actions also have an argument. */
DASM_REL_PC, DASM_LABEL_PC,
DASM_IMM, DASM_IMM12, DASM_IMM16, DASM_IMML8, DASM_IMML12, DASM_IMMV8,
DASM__MAX
};
/* Maximum number of section buffer positions for a single dasm_put() call. */
#define DASM_MAXSECPOS 25
/* DynASM encoder status codes. Action list offset or number are or'ed in. */
#define DASM_S_OK 0x00000000
#define DASM_S_NOMEM 0x01000000
#define DASM_S_PHASE 0x02000000
#define DASM_S_MATCH_SEC 0x03000000
#define DASM_S_RANGE_I 0x11000000
#define DASM_S_RANGE_SEC 0x12000000
#define DASM_S_RANGE_LG 0x13000000
#define DASM_S_RANGE_PC 0x14000000
#define DASM_S_RANGE_REL 0x15000000
#define DASM_S_UNDEF_LG 0x21000000
#define DASM_S_UNDEF_PC 0x22000000
/* Macros to convert positions (8 bit section + 24 bit index). */
#define DASM_POS2IDX(pos) ((pos)&0x00ffffff)
#define DASM_POS2BIAS(pos) ((pos)&0xff000000)
#define DASM_SEC2POS(sec) ((sec)<<24)
#define DASM_POS2SEC(pos) ((pos)>>24)
#define DASM_POS2PTR(D, pos) (D->sections[DASM_POS2SEC(pos)].rbuf + (pos))
/* Action list type. */
typedef const unsigned int *dasm_ActList;
/* Per-section structure. */
typedef struct dasm_Section {
int *rbuf; /* Biased buffer pointer (negative section bias). */
int *buf; /* True buffer pointer. */
size_t bsize; /* Buffer size in bytes. */
int pos; /* Biased buffer position. */
int epos; /* End of biased buffer position - max single put. */
int ofs; /* Byte offset into section. */
} dasm_Section;
/* Core structure holding the DynASM encoding state. */
struct dasm_State {
size_t psize; /* Allocated size of this structure. */
dasm_ActList actionlist; /* Current actionlist pointer. */
int *lglabels; /* Local/global chain/pos ptrs. */
size_t lgsize;
int *pclabels; /* PC label chains/pos ptrs. */
size_t pcsize;
void **globals; /* Array of globals (bias -10). */
dasm_Section *section; /* Pointer to active section. */
size_t codesize; /* Total size of all code sections. */
int maxsection; /* 0 <= sectionidx < maxsection. */
int status; /* Status code. */
dasm_Section sections[1]; /* All sections. Alloc-extended. */
};
/* The size of the core structure depends on the max. number of sections. */
#define DASM_PSZ(ms) (sizeof(dasm_State)+(ms-1)*sizeof(dasm_Section))
/* Initialize DynASM state. */
void dasm_init(Dst_DECL, int maxsection)
{
dasm_State *D;
size_t psz = 0;
int i;
Dst_REF = NULL;
DASM_M_GROW(Dst, struct dasm_State, Dst_REF, psz, DASM_PSZ(maxsection));
D = Dst_REF;
D->psize = psz;
D->lglabels = NULL;
D->lgsize = 0;
D->pclabels = NULL;
D->pcsize = 0;
D->globals = NULL;
D->maxsection = maxsection;
for (i = 0; i < maxsection; i++) {
D->sections[i].buf = NULL; /* Need this for pass3. */
D->sections[i].rbuf = D->sections[i].buf - DASM_SEC2POS(i);
D->sections[i].bsize = 0;
D->sections[i].epos = 0; /* Wrong, but is recalculated after resize. */
}
}
/* Free DynASM state. */
void dasm_free(Dst_DECL)
{
dasm_State *D = Dst_REF;
int i;
for (i = 0; i < D->maxsection; i++)
if (D->sections[i].buf)
DASM_M_FREE(Dst, D->sections[i].buf, D->sections[i].bsize);
if (D->pclabels) DASM_M_FREE(Dst, D->pclabels, D->pcsize);
if (D->lglabels) DASM_M_FREE(Dst, D->lglabels, D->lgsize);
DASM_M_FREE(Dst, D, D->psize);
}
/* Setup global label array. Must be called before dasm_setup(). */
void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl)
{
dasm_State *D = Dst_REF;
D->globals = gl - 10; /* Negative bias to compensate for locals. */
DASM_M_GROW(Dst, int, D->lglabels, D->lgsize, (10+maxgl)*sizeof(int));
}
/* Grow PC label array. Can be called after dasm_setup(), too. */
void dasm_growpc(Dst_DECL, unsigned int maxpc)
{
dasm_State *D = Dst_REF;
size_t osz = D->pcsize;
DASM_M_GROW(Dst, int, D->pclabels, D->pcsize, maxpc*sizeof(int));
memset((void *)(((unsigned char *)D->pclabels)+osz), 0, D->pcsize-osz);
}
/* Setup encoder. */
void dasm_setup(Dst_DECL, const void *actionlist)
{
dasm_State *D = Dst_REF;
int i;
D->actionlist = (dasm_ActList)actionlist;
D->status = DASM_S_OK;
D->section = &D->sections[0];
memset((void *)D->lglabels, 0, D->lgsize);
if (D->pclabels) memset((void *)D->pclabels, 0, D->pcsize);
for (i = 0; i < D->maxsection; i++) {
D->sections[i].pos = DASM_SEC2POS(i);
D->sections[i].ofs = 0;
}
}
#ifdef DASM_CHECKS
#define CK(x, st) \
do { if (!(x)) { \
D->status = DASM_S_##st|(p-D->actionlist-1); return; } } while (0)
#define CKPL(kind, st) \
do { if ((size_t)((char *)pl-(char *)D->kind##labels) >= D->kind##size) { \
D->status = DASM_S_RANGE_##st|(p-D->actionlist-1); return; } } while (0)
#else
#define CK(x, st) ((void)0)
#define CKPL(kind, st) ((void)0)
#endif
static int dasm_imm12(unsigned int n)
{
int i;
for (i = 0; i < 16; i++, n = (n << 2) | (n >> 30))
if (n <= 255) return (int)(n + (i << 8));
return -1;
}
/* Pass 1: Store actions and args, link branches/labels, estimate offsets. */
void dasm_put(Dst_DECL, int start, ...)
{
va_list ap;
dasm_State *D = Dst_REF;
dasm_ActList p = D->actionlist + start;
dasm_Section *sec = D->section;
int pos = sec->pos, ofs = sec->ofs;
int *b;
if (pos >= sec->epos) {
DASM_M_GROW(Dst, int, sec->buf, sec->bsize,
sec->bsize + 2*DASM_MAXSECPOS*sizeof(int));
sec->rbuf = sec->buf - DASM_POS2BIAS(pos);
sec->epos = (int)sec->bsize/sizeof(int) - DASM_MAXSECPOS+DASM_POS2BIAS(pos);
}
b = sec->rbuf;
b[pos++] = start;
va_start(ap, start);
while (1) {
unsigned int ins = *p++;
unsigned int action = (ins >> 16);
if (action >= DASM__MAX) {
ofs += 4;
} else {
int *pl, n = action >= DASM_REL_PC ? va_arg(ap, int) : 0;
switch (action) {
case DASM_STOP: goto stop;
case DASM_SECTION:
n = (ins & 255); CK(n < D->maxsection, RANGE_SEC);
D->section = &D->sections[n]; goto stop;
case DASM_ESC: p++; ofs += 4; break;
case DASM_REL_EXT: break;
case DASM_ALIGN: ofs += (ins & 255); b[pos++] = ofs; break;
case DASM_REL_LG:
n = (ins & 2047) - 10; pl = D->lglabels + n;
/* Bkwd rel or global. */
if (n >= 0) { CK(n>=10||*pl<0, RANGE_LG); CKPL(lg, LG); goto putrel; }
pl += 10; n = *pl;
if (n < 0) n = 0; /* Start new chain for fwd rel if label exists. */
goto linkrel;
case DASM_REL_PC:
pl = D->pclabels + n; CKPL(pc, PC);
putrel:
n = *pl;
if (n < 0) { /* Label exists. Get label pos and store it. */
b[pos] = -n;
} else {
linkrel:
b[pos] = n; /* Else link to rel chain, anchored at label. */
*pl = pos;
}
pos++;
break;
case DASM_LABEL_LG:
pl = D->lglabels + (ins & 2047) - 10; CKPL(lg, LG); goto putlabel;
case DASM_LABEL_PC:
pl = D->pclabels + n; CKPL(pc, PC);
putlabel:
n = *pl; /* n > 0: Collapse rel chain and replace with label pos. */
while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = pos;
}
*pl = -pos; /* Label exists now. */
b[pos++] = ofs; /* Store pass1 offset estimate. */
break;
case DASM_IMM:
case DASM_IMM16:
#ifdef DASM_CHECKS
CK((n & ((1<<((ins>>10)&31))-1)) == 0, RANGE_I);
if ((ins & 0x8000))
CK(((n + (1<<(((ins>>5)&31)-1)))>>((ins>>5)&31)) == 0, RANGE_I);
else
CK((n>>((ins>>5)&31)) == 0, RANGE_I);
#endif
b[pos++] = n;
break;
case DASM_IMMV8:
CK((n & 3) == 0, RANGE_I);
n >>= 2;
/* fallthrough */
case DASM_IMML8:
case DASM_IMML12:
CK(n >= 0 ? ((n>>((ins>>5)&31)) == 0) :
(((-n)>>((ins>>5)&31)) == 0), RANGE_I);
b[pos++] = n;
break;
case DASM_IMM12:
CK(dasm_imm12((unsigned int)n) != -1, RANGE_I);
b[pos++] = n;
break;
}
}
}
stop:
va_end(ap);
sec->pos = pos;
sec->ofs = ofs;
}
#undef CK
/* Pass 2: Link sections, shrink aligns, fix label offsets. */
int dasm_link(Dst_DECL, size_t *szp)
{
dasm_State *D = Dst_REF;
int secnum;
int ofs = 0;
#ifdef DASM_CHECKS
*szp = 0;
if (D->status != DASM_S_OK) return D->status;
{
int pc;
for (pc = 0; pc*sizeof(int) < D->pcsize; pc++)
if (D->pclabels[pc] > 0) return DASM_S_UNDEF_PC|pc;
}
#endif
{ /* Handle globals not defined in this translation unit. */
int idx;
for (idx = 10; idx*sizeof(int) < D->lgsize; idx++) {
int n = D->lglabels[idx];
/* Undefined label: Collapse rel chain and replace with marker (< 0). */
while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; }
}
}
/* Combine all code sections. No support for data sections (yet). */
for (secnum = 0; secnum < D->maxsection; secnum++) {
dasm_Section *sec = D->sections + secnum;
int *b = sec->rbuf;
int pos = DASM_SEC2POS(secnum);
int lastpos = sec->pos;
while (pos != lastpos) {
dasm_ActList p = D->actionlist + b[pos++];
while (1) {
unsigned int ins = *p++;
unsigned int action = (ins >> 16);
switch (action) {
case DASM_STOP: case DASM_SECTION: goto stop;
case DASM_ESC: p++; break;
case DASM_REL_EXT: break;
case DASM_ALIGN: ofs -= (b[pos++] + ofs) & (ins & 255); break;
case DASM_REL_LG: case DASM_REL_PC: pos++; break;
case DASM_LABEL_LG: case DASM_LABEL_PC: b[pos++] += ofs; break;
case DASM_IMM: case DASM_IMM12: case DASM_IMM16:
case DASM_IMML8: case DASM_IMML12: case DASM_IMMV8: pos++; break;
}
}
stop: (void)0;
}
ofs += sec->ofs; /* Next section starts right after current section. */
}
D->codesize = ofs; /* Total size of all code sections */
*szp = ofs;
return DASM_S_OK;
}
#ifdef DASM_CHECKS
#define CK(x, st) \
do { if (!(x)) return DASM_S_##st|(p-D->actionlist-1); } while (0)
#else
#define CK(x, st) ((void)0)
#endif
/* Pass 3: Encode sections. */
int dasm_encode(Dst_DECL, void *buffer)
{
dasm_State *D = Dst_REF;
char *base = (char *)buffer;
unsigned int *cp = (unsigned int *)buffer;
int secnum;
/* Encode all code sections. No support for data sections (yet). */
for (secnum = 0; secnum < D->maxsection; secnum++) {
dasm_Section *sec = D->sections + secnum;
int *b = sec->buf;
int *endb = sec->rbuf + sec->pos;
while (b != endb) {
dasm_ActList p = D->actionlist + *b++;
while (1) {
unsigned int ins = *p++;
unsigned int action = (ins >> 16);
int n = (action >= DASM_ALIGN && action < DASM__MAX) ? *b++ : 0;
switch (action) {
case DASM_STOP: case DASM_SECTION: goto stop;
case DASM_ESC: *cp++ = *p++; break;
case DASM_REL_EXT:
n = DASM_EXTERN(Dst, (unsigned char *)cp, (ins&2047), !(ins&2048));
goto patchrel;
case DASM_ALIGN:
ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0xe1a00000;
break;
case DASM_REL_LG:
if (n < 0) {
n = (int)((ptrdiff_t)D->globals[-n] - (ptrdiff_t)cp - 4);
goto patchrel;
}
/* fallthrough */
case DASM_REL_PC:
CK(n >= 0, UNDEF_PC);
n = *DASM_POS2PTR(D, n) - (int)((char *)cp - base) - 4;
patchrel:
if ((ins & 0x800) == 0) {
CK((n & 3) == 0 && ((n+0x02000000) >> 26) == 0, RANGE_REL);
cp[-1] |= ((n >> 2) & 0x00ffffff);
} else if ((ins & 0x1000)) {
CK((n & 3) == 0 && -256 <= n && n <= 256, RANGE_REL);
goto patchimml8;
} else if ((ins & 0x2000) == 0) {
CK((n & 3) == 0 && -4096 <= n && n <= 4096, RANGE_REL);
goto patchimml;
} else {
CK((n & 3) == 0 && -1020 <= n && n <= 1020, RANGE_REL);
n >>= 2;
goto patchimml;
}
break;
case DASM_LABEL_LG:
ins &= 2047; if (ins >= 20) D->globals[ins-10] = (void *)(base + n);
break;
case DASM_LABEL_PC: break;
case DASM_IMM:
cp[-1] |= ((n>>((ins>>10)&31)) & ((1<<((ins>>5)&31))-1)) << (ins&31);
break;
case DASM_IMM12:
cp[-1] |= dasm_imm12((unsigned int)n);
break;
case DASM_IMM16:
cp[-1] |= ((n & 0xf000) << 4) | (n & 0x0fff);
break;
case DASM_IMML8: patchimml8:
cp[-1] |= n >= 0 ? (0x00800000 | (n & 0x0f) | ((n & 0xf0) << 4)) :
((-n & 0x0f) | ((-n & 0xf0) << 4));
break;
case DASM_IMML12: case DASM_IMMV8: patchimml:
cp[-1] |= n >= 0 ? (0x00800000 | n) : (-n);
break;
default: *cp++ = ins; break;
}
}
stop: (void)0;
}
}
if (base + D->codesize != (char *)cp) /* Check for phase errors. */
return DASM_S_PHASE;
return DASM_S_OK;
}
#undef CK
/* Get PC label offset. */
int dasm_getpclabel(Dst_DECL, unsigned int pc)
{
dasm_State *D = Dst_REF;
if (pc*sizeof(int) < D->pcsize) {
int pos = D->pclabels[pc];
if (pos < 0) return *DASM_POS2PTR(D, -pos);
if (pos > 0) return -1; /* Undefined. */
}
return -2; /* Unused or out of range. */
}
#ifdef DASM_CHECKS
/* Optional sanity checker to call between isolated encoding steps. */
int dasm_checkstep(Dst_DECL, int secmatch)
{
dasm_State *D = Dst_REF;
if (D->status == DASM_S_OK) {
int i;
for (i = 1; i <= 9; i++) {
if (D->lglabels[i] > 0) { D->status = DASM_S_UNDEF_LG|i; break; }
D->lglabels[i] = 0;
}
}
if (D->status == DASM_S_OK && secmatch >= 0 &&
D->section != &D->sections[secmatch])
D->status = DASM_S_MATCH_SEC|(D->section-D->sections);
return D->status;
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,570 +0,0 @@
/*
** DynASM ARM64 encoding engine.
** Copyright (C) 2005-2021 Mike Pall. All rights reserved.
** Released under the MIT license. See dynasm.lua for full copyright notice.
*/
#include <stddef.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#define DASM_ARCH "arm64"
#ifndef DASM_EXTERN
#define DASM_EXTERN(a,b,c,d) 0
#endif
/* Action definitions. */
enum {
DASM_STOP, DASM_SECTION, DASM_ESC, DASM_REL_EXT,
/* The following actions need a buffer position. */
DASM_ALIGN, DASM_REL_LG, DASM_LABEL_LG,
/* The following actions also have an argument. */
DASM_REL_PC, DASM_LABEL_PC, DASM_REL_A,
DASM_IMM, DASM_IMM6, DASM_IMM12, DASM_IMM13W, DASM_IMM13X, DASM_IMML,
DASM_IMMV, DASM_VREG,
DASM__MAX
};
/* Maximum number of section buffer positions for a single dasm_put() call. */
#define DASM_MAXSECPOS 25
/* DynASM encoder status codes. Action list offset or number are or'ed in. */
#define DASM_S_OK 0x00000000
#define DASM_S_NOMEM 0x01000000
#define DASM_S_PHASE 0x02000000
#define DASM_S_MATCH_SEC 0x03000000
#define DASM_S_RANGE_I 0x11000000
#define DASM_S_RANGE_SEC 0x12000000
#define DASM_S_RANGE_LG 0x13000000
#define DASM_S_RANGE_PC 0x14000000
#define DASM_S_RANGE_REL 0x15000000
#define DASM_S_RANGE_VREG 0x16000000
#define DASM_S_UNDEF_LG 0x21000000
#define DASM_S_UNDEF_PC 0x22000000
/* Macros to convert positions (8 bit section + 24 bit index). */
#define DASM_POS2IDX(pos) ((pos)&0x00ffffff)
#define DASM_POS2BIAS(pos) ((pos)&0xff000000)
#define DASM_SEC2POS(sec) ((sec)<<24)
#define DASM_POS2SEC(pos) ((pos)>>24)
#define DASM_POS2PTR(D, pos) (D->sections[DASM_POS2SEC(pos)].rbuf + (pos))
/* Action list type. */
typedef const unsigned int *dasm_ActList;
/* Per-section structure. */
typedef struct dasm_Section {
int *rbuf; /* Biased buffer pointer (negative section bias). */
int *buf; /* True buffer pointer. */
size_t bsize; /* Buffer size in bytes. */
int pos; /* Biased buffer position. */
int epos; /* End of biased buffer position - max single put. */
int ofs; /* Byte offset into section. */
} dasm_Section;
/* Core structure holding the DynASM encoding state. */
struct dasm_State {
size_t psize; /* Allocated size of this structure. */
dasm_ActList actionlist; /* Current actionlist pointer. */
int *lglabels; /* Local/global chain/pos ptrs. */
size_t lgsize;
int *pclabels; /* PC label chains/pos ptrs. */
size_t pcsize;
void **globals; /* Array of globals (bias -10). */
dasm_Section *section; /* Pointer to active section. */
size_t codesize; /* Total size of all code sections. */
int maxsection; /* 0 <= sectionidx < maxsection. */
int status; /* Status code. */
dasm_Section sections[1]; /* All sections. Alloc-extended. */
};
/* The size of the core structure depends on the max. number of sections. */
#define DASM_PSZ(ms) (sizeof(dasm_State)+(ms-1)*sizeof(dasm_Section))
/* Initialize DynASM state. */
void dasm_init(Dst_DECL, int maxsection)
{
dasm_State *D;
size_t psz = 0;
int i;
Dst_REF = NULL;
DASM_M_GROW(Dst, struct dasm_State, Dst_REF, psz, DASM_PSZ(maxsection));
D = Dst_REF;
D->psize = psz;
D->lglabels = NULL;
D->lgsize = 0;
D->pclabels = NULL;
D->pcsize = 0;
D->globals = NULL;
D->maxsection = maxsection;
for (i = 0; i < maxsection; i++) {
D->sections[i].buf = NULL; /* Need this for pass3. */
D->sections[i].rbuf = D->sections[i].buf - DASM_SEC2POS(i);
D->sections[i].bsize = 0;
D->sections[i].epos = 0; /* Wrong, but is recalculated after resize. */
}
}
/* Free DynASM state. */
void dasm_free(Dst_DECL)
{
dasm_State *D = Dst_REF;
int i;
for (i = 0; i < D->maxsection; i++)
if (D->sections[i].buf)
DASM_M_FREE(Dst, D->sections[i].buf, D->sections[i].bsize);
if (D->pclabels) DASM_M_FREE(Dst, D->pclabels, D->pcsize);
if (D->lglabels) DASM_M_FREE(Dst, D->lglabels, D->lgsize);
DASM_M_FREE(Dst, D, D->psize);
}
/* Setup global label array. Must be called before dasm_setup(). */
void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl)
{
dasm_State *D = Dst_REF;
D->globals = gl - 10; /* Negative bias to compensate for locals. */
DASM_M_GROW(Dst, int, D->lglabels, D->lgsize, (10+maxgl)*sizeof(int));
}
/* Grow PC label array. Can be called after dasm_setup(), too. */
void dasm_growpc(Dst_DECL, unsigned int maxpc)
{
dasm_State *D = Dst_REF;
size_t osz = D->pcsize;
DASM_M_GROW(Dst, int, D->pclabels, D->pcsize, maxpc*sizeof(int));
memset((void *)(((unsigned char *)D->pclabels)+osz), 0, D->pcsize-osz);
}
/* Setup encoder. */
void dasm_setup(Dst_DECL, const void *actionlist)
{
dasm_State *D = Dst_REF;
int i;
D->actionlist = (dasm_ActList)actionlist;
D->status = DASM_S_OK;
D->section = &D->sections[0];
memset((void *)D->lglabels, 0, D->lgsize);
if (D->pclabels) memset((void *)D->pclabels, 0, D->pcsize);
for (i = 0; i < D->maxsection; i++) {
D->sections[i].pos = DASM_SEC2POS(i);
D->sections[i].ofs = 0;
}
}
#ifdef DASM_CHECKS
#define CK(x, st) \
do { if (!(x)) { \
D->status = DASM_S_##st|(p-D->actionlist-1); return; } } while (0)
#define CKPL(kind, st) \
do { if ((size_t)((char *)pl-(char *)D->kind##labels) >= D->kind##size) { \
D->status = DASM_S_RANGE_##st|(p-D->actionlist-1); return; } } while (0)
#else
#define CK(x, st) ((void)0)
#define CKPL(kind, st) ((void)0)
#endif
static int dasm_imm12(unsigned int n)
{
if ((n >> 12) == 0)
return n;
else if ((n & 0xff000fff) == 0)
return (n >> 12) | 0x1000;
else
return -1;
}
static int dasm_ffs(unsigned long long x)
{
int n = -1;
while (x) { x >>= 1; n++; }
return n;
}
static int dasm_imm13(int lo, int hi)
{
int inv = 0, w = 64, s = 0xfff, xa, xb;
unsigned long long n = (((unsigned long long)hi) << 32) | (unsigned int)lo;
unsigned long long m = 1ULL, a, b, c;
if (n & 1) { n = ~n; inv = 1; }
a = n & -n; b = (n+a)&-(n+a); c = (n+a-b)&-(n+a-b);
xa = dasm_ffs(a); xb = dasm_ffs(b);
if (c) {
w = dasm_ffs(c) - xa;
if (w == 32) m = 0x0000000100000001UL;
else if (w == 16) m = 0x0001000100010001UL;
else if (w == 8) m = 0x0101010101010101UL;
else if (w == 4) m = 0x1111111111111111UL;
else if (w == 2) m = 0x5555555555555555UL;
else return -1;
s = (-2*w & 0x3f) - 1;
} else if (!a) {
return -1;
} else if (xb == -1) {
xb = 64;
}
if ((b-a) * m != n) return -1;
if (inv) {
return ((w - xb) << 6) | (s+w+xa-xb);
} else {
return ((w - xa) << 6) | (s+xb-xa);
}
return -1;
}
/* Pass 1: Store actions and args, link branches/labels, estimate offsets. */
void dasm_put(Dst_DECL, int start, ...)
{
va_list ap;
dasm_State *D = Dst_REF;
dasm_ActList p = D->actionlist + start;
dasm_Section *sec = D->section;
int pos = sec->pos, ofs = sec->ofs;
int *b;
if (pos >= sec->epos) {
DASM_M_GROW(Dst, int, sec->buf, sec->bsize,
sec->bsize + 2*DASM_MAXSECPOS*sizeof(int));
sec->rbuf = sec->buf - DASM_POS2BIAS(pos);
sec->epos = (int)sec->bsize/sizeof(int) - DASM_MAXSECPOS+DASM_POS2BIAS(pos);
}
b = sec->rbuf;
b[pos++] = start;
va_start(ap, start);
while (1) {
unsigned int ins = *p++;
unsigned int action = (ins >> 16);
if (action >= DASM__MAX) {
ofs += 4;
} else {
int *pl, n = action >= DASM_REL_PC ? va_arg(ap, int) : 0;
switch (action) {
case DASM_STOP: goto stop;
case DASM_SECTION:
n = (ins & 255); CK(n < D->maxsection, RANGE_SEC);
D->section = &D->sections[n]; goto stop;
case DASM_ESC: p++; ofs += 4; break;
case DASM_REL_EXT: if ((ins & 0x8000)) ofs += 8; break;
case DASM_ALIGN: ofs += (ins & 255); b[pos++] = ofs; break;
case DASM_REL_LG:
n = (ins & 2047) - 10; pl = D->lglabels + n;
/* Bkwd rel or global. */
if (n >= 0) { CK(n>=10||*pl<0, RANGE_LG); CKPL(lg, LG); goto putrel; }
pl += 10; n = *pl;
if (n < 0) n = 0; /* Start new chain for fwd rel if label exists. */
goto linkrel;
case DASM_REL_PC:
pl = D->pclabels + n; CKPL(pc, PC);
putrel:
n = *pl;
if (n < 0) { /* Label exists. Get label pos and store it. */
b[pos] = -n;
} else {
linkrel:
b[pos] = n; /* Else link to rel chain, anchored at label. */
*pl = pos;
}
pos++;
if ((ins & 0x8000)) ofs += 8;
break;
case DASM_REL_A:
b[pos++] = n;
b[pos++] = va_arg(ap, int);
break;
case DASM_LABEL_LG:
pl = D->lglabels + (ins & 2047) - 10; CKPL(lg, LG); goto putlabel;
case DASM_LABEL_PC:
pl = D->pclabels + n; CKPL(pc, PC);
putlabel:
n = *pl; /* n > 0: Collapse rel chain and replace with label pos. */
while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = pos;
}
*pl = -pos; /* Label exists now. */
b[pos++] = ofs; /* Store pass1 offset estimate. */
break;
case DASM_IMM:
CK((n & ((1<<((ins>>10)&31))-1)) == 0, RANGE_I);
n >>= ((ins>>10)&31);
#ifdef DASM_CHECKS
if ((ins & 0x8000))
CK(((n + (1<<(((ins>>5)&31)-1)))>>((ins>>5)&31)) == 0, RANGE_I);
else
CK((n>>((ins>>5)&31)) == 0, RANGE_I);
#endif
b[pos++] = n;
break;
case DASM_IMM6:
CK((n >> 6) == 0, RANGE_I);
b[pos++] = n;
break;
case DASM_IMM12:
CK(dasm_imm12((unsigned int)n) != -1, RANGE_I);
b[pos++] = n;
break;
case DASM_IMM13W:
CK(dasm_imm13(n, n) != -1, RANGE_I);
b[pos++] = n;
break;
case DASM_IMM13X: {
int m = va_arg(ap, int);
CK(dasm_imm13(n, m) != -1, RANGE_I);
b[pos++] = n;
b[pos++] = m;
break;
}
case DASM_IMML: {
#ifdef DASM_CHECKS
int scale = (ins & 3);
CK((!(n & ((1<<scale)-1)) && (unsigned int)(n>>scale) < 4096) ||
(unsigned int)(n+256) < 512, RANGE_I);
#endif
b[pos++] = n;
break;
}
case DASM_IMMV:
ofs += 4;
b[pos++] = n;
break;
case DASM_VREG:
CK(n < 32, RANGE_VREG);
b[pos++] = n;
break;
}
}
}
stop:
va_end(ap);
sec->pos = pos;
sec->ofs = ofs;
}
#undef CK
/* Pass 2: Link sections, shrink aligns, fix label offsets. */
int dasm_link(Dst_DECL, size_t *szp)
{
dasm_State *D = Dst_REF;
int secnum;
int ofs = 0;
#ifdef DASM_CHECKS
*szp = 0;
if (D->status != DASM_S_OK) return D->status;
{
int pc;
for (pc = 0; pc*sizeof(int) < D->pcsize; pc++)
if (D->pclabels[pc] > 0) return DASM_S_UNDEF_PC|pc;
}
#endif
{ /* Handle globals not defined in this translation unit. */
int idx;
for (idx = 10; idx*sizeof(int) < D->lgsize; idx++) {
int n = D->lglabels[idx];
/* Undefined label: Collapse rel chain and replace with marker (< 0). */
while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; }
}
}
/* Combine all code sections. No support for data sections (yet). */
for (secnum = 0; secnum < D->maxsection; secnum++) {
dasm_Section *sec = D->sections + secnum;
int *b = sec->rbuf;
int pos = DASM_SEC2POS(secnum);
int lastpos = sec->pos;
while (pos != lastpos) {
dasm_ActList p = D->actionlist + b[pos++];
while (1) {
unsigned int ins = *p++;
unsigned int action = (ins >> 16);
switch (action) {
case DASM_STOP: case DASM_SECTION: goto stop;
case DASM_ESC: p++; break;
case DASM_REL_EXT: break;
case DASM_ALIGN: ofs -= (b[pos++] + ofs) & (ins & 255); break;
case DASM_REL_LG: case DASM_REL_PC: pos++; break;
case DASM_LABEL_LG: case DASM_LABEL_PC: b[pos++] += ofs; break;
case DASM_IMM: case DASM_IMM6: case DASM_IMM12: case DASM_IMM13W:
case DASM_IMML: case DASM_IMMV: case DASM_VREG: pos++; break;
case DASM_IMM13X: case DASM_REL_A: pos += 2; break;
}
}
stop: (void)0;
}
ofs += sec->ofs; /* Next section starts right after current section. */
}
D->codesize = ofs; /* Total size of all code sections */
*szp = ofs;
return DASM_S_OK;
}
#ifdef DASM_ADD_VENEER
#define CK_REL(x, o) \
do { if (!(x) && !(n = DASM_ADD_VENEER(D, buffer, ins, b, cp, o))) \
return DASM_S_RANGE_REL|(p-D->actionlist-1); \
} while (0)
#else
#define CK_REL(x, o) CK(x, RANGE_REL)
#endif
#ifdef DASM_CHECKS
#define CK(x, st) \
do { if (!(x)) return DASM_S_##st|(p-D->actionlist-1); } while (0)
#else
#define CK(x, st) ((void)0)
#endif
/* Pass 3: Encode sections. */
int dasm_encode(Dst_DECL, void *buffer)
{
dasm_State *D = Dst_REF;
char *base = (char *)buffer;
unsigned int *cp = (unsigned int *)buffer;
int secnum;
/* Encode all code sections. No support for data sections (yet). */
for (secnum = 0; secnum < D->maxsection; secnum++) {
dasm_Section *sec = D->sections + secnum;
int *b = sec->buf;
int *endb = sec->rbuf + sec->pos;
while (b != endb) {
dasm_ActList p = D->actionlist + *b++;
while (1) {
unsigned int ins = *p++;
unsigned int action = (ins >> 16);
int n = (action >= DASM_ALIGN && action < DASM__MAX) ? *b++ : 0;
switch (action) {
case DASM_STOP: case DASM_SECTION: goto stop;
case DASM_ESC: *cp++ = *p++; break;
case DASM_REL_EXT:
n = DASM_EXTERN(Dst, (unsigned char *)cp, (ins&2047), !(ins&2048));
goto patchrel;
case DASM_ALIGN:
ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0xe1a00000;
break;
case DASM_REL_LG:
if (n < 0) {
ptrdiff_t na = (ptrdiff_t)D->globals[-n] - (ptrdiff_t)cp + 4;
n = (int)na;
CK_REL((ptrdiff_t)n == na, na);
goto patchrel;
}
/* fallthrough */
case DASM_REL_PC:
CK(n >= 0, UNDEF_PC);
n = *DASM_POS2PTR(D, n) - (int)((char *)cp - base) + 4;
patchrel:
if (!(ins & 0xf800)) { /* B, BL */
CK_REL((n & 3) == 0 && ((n+0x08000000) >> 28) == 0, n);
cp[-1] |= ((n >> 2) & 0x03ffffff);
} else if ((ins & 0x800)) { /* B.cond, CBZ, CBNZ, LDR* literal */
CK_REL((n & 3) == 0 && ((n+0x00100000) >> 21) == 0, n);
cp[-1] |= ((n << 3) & 0x00ffffe0);
} else if ((ins & 0x3000) == 0x2000) { /* ADR */
CK_REL(((n+0x00100000) >> 21) == 0, n);
cp[-1] |= ((n << 3) & 0x00ffffe0) | ((n & 3) << 29);
} else if ((ins & 0x3000) == 0x3000) { /* ADRP */
cp[-1] |= ((n >> 9) & 0x00ffffe0) | (((n >> 12) & 3) << 29);
} else if ((ins & 0x1000)) { /* TBZ, TBNZ */
CK_REL((n & 3) == 0 && ((n+0x00008000) >> 16) == 0, n);
cp[-1] |= ((n << 3) & 0x0007ffe0);
} else if ((ins & 0x8000)) { /* absolute */
cp[0] = (unsigned int)((ptrdiff_t)cp - 4 + n);
cp[1] = (unsigned int)(((ptrdiff_t)cp - 4 + n) >> 32);
cp += 2;
}
break;
case DASM_REL_A: {
ptrdiff_t na = (((ptrdiff_t)(*b++) << 32) | (unsigned int)n);
if ((ins & 0x3000) == 0x3000) { /* ADRP */
ins &= ~0x1000;
na = (na >> 12) - (((ptrdiff_t)cp - 4) >> 12);
} else {
na = na - (ptrdiff_t)cp + 4;
}
n = (int)na;
CK_REL((ptrdiff_t)n == na, na);
goto patchrel;
}
case DASM_LABEL_LG:
ins &= 2047; if (ins >= 20) D->globals[ins-10] = (void *)(base + n);
break;
case DASM_LABEL_PC: break;
case DASM_IMM:
cp[-1] |= (n & ((1<<((ins>>5)&31))-1)) << (ins&31);
break;
case DASM_IMM6:
cp[-1] |= ((n&31) << 19) | ((n&32) << 26);
break;
case DASM_IMM12:
cp[-1] |= (dasm_imm12((unsigned int)n) << 10);
break;
case DASM_IMM13W:
cp[-1] |= (dasm_imm13(n, n) << 10);
break;
case DASM_IMM13X:
cp[-1] |= (dasm_imm13(n, *b++) << 10);
break;
case DASM_IMML: {
int scale = (ins & 3);
cp[-1] |= (!(n & ((1<<scale)-1)) && (unsigned int)(n>>scale) < 4096) ?
((n << (10-scale)) | 0x01000000) : ((n & 511) << 12);
break;
}
case DASM_IMMV:
*cp++ = n;
break;
case DASM_VREG:
cp[-1] |= (n & 0x1f) << (ins & 0x1f);
break;
default: *cp++ = ins; break;
}
}
stop: (void)0;
}
}
if (base + D->codesize != (char *)cp) /* Check for phase errors. */
return DASM_S_PHASE;
return DASM_S_OK;
}
#undef CK
/* Get PC label offset. */
int dasm_getpclabel(Dst_DECL, unsigned int pc)
{
dasm_State *D = Dst_REF;
if (pc*sizeof(int) < D->pcsize) {
int pos = D->pclabels[pc];
if (pos < 0) return *DASM_POS2PTR(D, -pos);
if (pos > 0) return -1; /* Undefined. */
}
return -2; /* Unused or out of range. */
}
#ifdef DASM_CHECKS
/* Optional sanity checker to call between isolated encoding steps. */
int dasm_checkstep(Dst_DECL, int secmatch)
{
dasm_State *D = Dst_REF;
if (D->status == DASM_S_OK) {
int i;
for (i = 1; i <= 9; i++) {
if (D->lglabels[i] > 0) { D->status = DASM_S_UNDEF_LG|i; break; }
D->lglabels[i] = 0;
}
}
if (D->status == DASM_S_OK && secmatch >= 0 &&
D->section != &D->sections[secmatch])
D->status = DASM_S_MATCH_SEC|(D->section-D->sections);
return D->status;
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,424 +0,0 @@
/*
** DynASM MIPS encoding engine.
** Copyright (C) 2005-2021 Mike Pall. All rights reserved.
** Released under the MIT license. See dynasm.lua for full copyright notice.
*/
#include <stddef.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#define DASM_ARCH "mips"
#ifndef DASM_EXTERN
#define DASM_EXTERN(a,b,c,d) 0
#endif
/* Action definitions. */
enum {
DASM_STOP, DASM_SECTION, DASM_ESC, DASM_REL_EXT,
/* The following actions need a buffer position. */
DASM_ALIGN, DASM_REL_LG, DASM_LABEL_LG,
/* The following actions also have an argument. */
DASM_REL_PC, DASM_LABEL_PC, DASM_IMM, DASM_IMMS,
DASM__MAX
};
/* Maximum number of section buffer positions for a single dasm_put() call. */
#define DASM_MAXSECPOS 25
/* DynASM encoder status codes. Action list offset or number are or'ed in. */
#define DASM_S_OK 0x00000000
#define DASM_S_NOMEM 0x01000000
#define DASM_S_PHASE 0x02000000
#define DASM_S_MATCH_SEC 0x03000000
#define DASM_S_RANGE_I 0x11000000
#define DASM_S_RANGE_SEC 0x12000000
#define DASM_S_RANGE_LG 0x13000000
#define DASM_S_RANGE_PC 0x14000000
#define DASM_S_RANGE_REL 0x15000000
#define DASM_S_UNDEF_LG 0x21000000
#define DASM_S_UNDEF_PC 0x22000000
/* Macros to convert positions (8 bit section + 24 bit index). */
#define DASM_POS2IDX(pos) ((pos)&0x00ffffff)
#define DASM_POS2BIAS(pos) ((pos)&0xff000000)
#define DASM_SEC2POS(sec) ((sec)<<24)
#define DASM_POS2SEC(pos) ((pos)>>24)
#define DASM_POS2PTR(D, pos) (D->sections[DASM_POS2SEC(pos)].rbuf + (pos))
/* Action list type. */
typedef const unsigned int *dasm_ActList;
/* Per-section structure. */
typedef struct dasm_Section {
int *rbuf; /* Biased buffer pointer (negative section bias). */
int *buf; /* True buffer pointer. */
size_t bsize; /* Buffer size in bytes. */
int pos; /* Biased buffer position. */
int epos; /* End of biased buffer position - max single put. */
int ofs; /* Byte offset into section. */
} dasm_Section;
/* Core structure holding the DynASM encoding state. */
struct dasm_State {
size_t psize; /* Allocated size of this structure. */
dasm_ActList actionlist; /* Current actionlist pointer. */
int *lglabels; /* Local/global chain/pos ptrs. */
size_t lgsize;
int *pclabels; /* PC label chains/pos ptrs. */
size_t pcsize;
void **globals; /* Array of globals (bias -10). */
dasm_Section *section; /* Pointer to active section. */
size_t codesize; /* Total size of all code sections. */
int maxsection; /* 0 <= sectionidx < maxsection. */
int status; /* Status code. */
dasm_Section sections[1]; /* All sections. Alloc-extended. */
};
/* The size of the core structure depends on the max. number of sections. */
#define DASM_PSZ(ms) (sizeof(dasm_State)+(ms-1)*sizeof(dasm_Section))
/* Initialize DynASM state. */
void dasm_init(Dst_DECL, int maxsection)
{
dasm_State *D;
size_t psz = 0;
int i;
Dst_REF = NULL;
DASM_M_GROW(Dst, struct dasm_State, Dst_REF, psz, DASM_PSZ(maxsection));
D = Dst_REF;
D->psize = psz;
D->lglabels = NULL;
D->lgsize = 0;
D->pclabels = NULL;
D->pcsize = 0;
D->globals = NULL;
D->maxsection = maxsection;
for (i = 0; i < maxsection; i++) {
D->sections[i].buf = NULL; /* Need this for pass3. */
D->sections[i].rbuf = D->sections[i].buf - DASM_SEC2POS(i);
D->sections[i].bsize = 0;
D->sections[i].epos = 0; /* Wrong, but is recalculated after resize. */
}
}
/* Free DynASM state. */
void dasm_free(Dst_DECL)
{
dasm_State *D = Dst_REF;
int i;
for (i = 0; i < D->maxsection; i++)
if (D->sections[i].buf)
DASM_M_FREE(Dst, D->sections[i].buf, D->sections[i].bsize);
if (D->pclabels) DASM_M_FREE(Dst, D->pclabels, D->pcsize);
if (D->lglabels) DASM_M_FREE(Dst, D->lglabels, D->lgsize);
DASM_M_FREE(Dst, D, D->psize);
}
/* Setup global label array. Must be called before dasm_setup(). */
void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl)
{
dasm_State *D = Dst_REF;
D->globals = gl - 10; /* Negative bias to compensate for locals. */
DASM_M_GROW(Dst, int, D->lglabels, D->lgsize, (10+maxgl)*sizeof(int));
}
/* Grow PC label array. Can be called after dasm_setup(), too. */
void dasm_growpc(Dst_DECL, unsigned int maxpc)
{
dasm_State *D = Dst_REF;
size_t osz = D->pcsize;
DASM_M_GROW(Dst, int, D->pclabels, D->pcsize, maxpc*sizeof(int));
memset((void *)(((unsigned char *)D->pclabels)+osz), 0, D->pcsize-osz);
}
/* Setup encoder. */
void dasm_setup(Dst_DECL, const void *actionlist)
{
dasm_State *D = Dst_REF;
int i;
D->actionlist = (dasm_ActList)actionlist;
D->status = DASM_S_OK;
D->section = &D->sections[0];
memset((void *)D->lglabels, 0, D->lgsize);
if (D->pclabels) memset((void *)D->pclabels, 0, D->pcsize);
for (i = 0; i < D->maxsection; i++) {
D->sections[i].pos = DASM_SEC2POS(i);
D->sections[i].ofs = 0;
}
}
#ifdef DASM_CHECKS
#define CK(x, st) \
do { if (!(x)) { \
D->status = DASM_S_##st|(p-D->actionlist-1); return; } } while (0)
#define CKPL(kind, st) \
do { if ((size_t)((char *)pl-(char *)D->kind##labels) >= D->kind##size) { \
D->status = DASM_S_RANGE_##st|(p-D->actionlist-1); return; } } while (0)
#else
#define CK(x, st) ((void)0)
#define CKPL(kind, st) ((void)0)
#endif
/* Pass 1: Store actions and args, link branches/labels, estimate offsets. */
void dasm_put(Dst_DECL, int start, ...)
{
va_list ap;
dasm_State *D = Dst_REF;
dasm_ActList p = D->actionlist + start;
dasm_Section *sec = D->section;
int pos = sec->pos, ofs = sec->ofs;
int *b;
if (pos >= sec->epos) {
DASM_M_GROW(Dst, int, sec->buf, sec->bsize,
sec->bsize + 2*DASM_MAXSECPOS*sizeof(int));
sec->rbuf = sec->buf - DASM_POS2BIAS(pos);
sec->epos = (int)sec->bsize/sizeof(int) - DASM_MAXSECPOS+DASM_POS2BIAS(pos);
}
b = sec->rbuf;
b[pos++] = start;
va_start(ap, start);
while (1) {
unsigned int ins = *p++;
unsigned int action = (ins >> 16) - 0xff00;
if (action >= DASM__MAX) {
ofs += 4;
} else {
int *pl, n = action >= DASM_REL_PC ? va_arg(ap, int) : 0;
switch (action) {
case DASM_STOP: goto stop;
case DASM_SECTION:
n = (ins & 255); CK(n < D->maxsection, RANGE_SEC);
D->section = &D->sections[n]; goto stop;
case DASM_ESC: p++; ofs += 4; break;
case DASM_REL_EXT: break;
case DASM_ALIGN: ofs += (ins & 255); b[pos++] = ofs; break;
case DASM_REL_LG:
n = (ins & 2047) - 10; pl = D->lglabels + n;
/* Bkwd rel or global. */
if (n >= 0) { CK(n>=10||*pl<0, RANGE_LG); CKPL(lg, LG); goto putrel; }
pl += 10; n = *pl;
if (n < 0) n = 0; /* Start new chain for fwd rel if label exists. */
goto linkrel;
case DASM_REL_PC:
pl = D->pclabels + n; CKPL(pc, PC);
putrel:
n = *pl;
if (n < 0) { /* Label exists. Get label pos and store it. */
b[pos] = -n;
} else {
linkrel:
b[pos] = n; /* Else link to rel chain, anchored at label. */
*pl = pos;
}
pos++;
break;
case DASM_LABEL_LG:
pl = D->lglabels + (ins & 2047) - 10; CKPL(lg, LG); goto putlabel;
case DASM_LABEL_PC:
pl = D->pclabels + n; CKPL(pc, PC);
putlabel:
n = *pl; /* n > 0: Collapse rel chain and replace with label pos. */
while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = pos;
}
*pl = -pos; /* Label exists now. */
b[pos++] = ofs; /* Store pass1 offset estimate. */
break;
case DASM_IMM: case DASM_IMMS:
#ifdef DASM_CHECKS
CK((n & ((1<<((ins>>10)&31))-1)) == 0, RANGE_I);
#endif
n >>= ((ins>>10)&31);
#ifdef DASM_CHECKS
if (ins & 0x8000)
CK(((n + (1<<(((ins>>5)&31)-1)))>>((ins>>5)&31)) == 0, RANGE_I);
else
CK((n>>((ins>>5)&31)) == 0, RANGE_I);
#endif
b[pos++] = n;
break;
}
}
}
stop:
va_end(ap);
sec->pos = pos;
sec->ofs = ofs;
}
#undef CK
/* Pass 2: Link sections, shrink aligns, fix label offsets. */
int dasm_link(Dst_DECL, size_t *szp)
{
dasm_State *D = Dst_REF;
int secnum;
int ofs = 0;
#ifdef DASM_CHECKS
*szp = 0;
if (D->status != DASM_S_OK) return D->status;
{
int pc;
for (pc = 0; pc*sizeof(int) < D->pcsize; pc++)
if (D->pclabels[pc] > 0) return DASM_S_UNDEF_PC|pc;
}
#endif
{ /* Handle globals not defined in this translation unit. */
int idx;
for (idx = 10; idx*sizeof(int) < D->lgsize; idx++) {
int n = D->lglabels[idx];
/* Undefined label: Collapse rel chain and replace with marker (< 0). */
while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; }
}
}
/* Combine all code sections. No support for data sections (yet). */
for (secnum = 0; secnum < D->maxsection; secnum++) {
dasm_Section *sec = D->sections + secnum;
int *b = sec->rbuf;
int pos = DASM_SEC2POS(secnum);
int lastpos = sec->pos;
while (pos != lastpos) {
dasm_ActList p = D->actionlist + b[pos++];
while (1) {
unsigned int ins = *p++;
unsigned int action = (ins >> 16) - 0xff00;
switch (action) {
case DASM_STOP: case DASM_SECTION: goto stop;
case DASM_ESC: p++; break;
case DASM_REL_EXT: break;
case DASM_ALIGN: ofs -= (b[pos++] + ofs) & (ins & 255); break;
case DASM_REL_LG: case DASM_REL_PC: pos++; break;
case DASM_LABEL_LG: case DASM_LABEL_PC: b[pos++] += ofs; break;
case DASM_IMM: case DASM_IMMS: pos++; break;
}
}
stop: (void)0;
}
ofs += sec->ofs; /* Next section starts right after current section. */
}
D->codesize = ofs; /* Total size of all code sections */
*szp = ofs;
return DASM_S_OK;
}
#ifdef DASM_CHECKS
#define CK(x, st) \
do { if (!(x)) return DASM_S_##st|(p-D->actionlist-1); } while (0)
#else
#define CK(x, st) ((void)0)
#endif
/* Pass 3: Encode sections. */
int dasm_encode(Dst_DECL, void *buffer)
{
dasm_State *D = Dst_REF;
char *base = (char *)buffer;
unsigned int *cp = (unsigned int *)buffer;
int secnum;
/* Encode all code sections. No support for data sections (yet). */
for (secnum = 0; secnum < D->maxsection; secnum++) {
dasm_Section *sec = D->sections + secnum;
int *b = sec->buf;
int *endb = sec->rbuf + sec->pos;
while (b != endb) {
dasm_ActList p = D->actionlist + *b++;
while (1) {
unsigned int ins = *p++;
unsigned int action = (ins >> 16) - 0xff00;
int n = (action >= DASM_ALIGN && action < DASM__MAX) ? *b++ : 0;
switch (action) {
case DASM_STOP: case DASM_SECTION: goto stop;
case DASM_ESC: *cp++ = *p++; break;
case DASM_REL_EXT:
n = DASM_EXTERN(Dst, (unsigned char *)cp, (ins & 2047), 1);
goto patchrel;
case DASM_ALIGN:
ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0x60000000;
break;
case DASM_REL_LG:
if (n < 0) {
n = (int)((ptrdiff_t)D->globals[-n] - (ptrdiff_t)cp);
goto patchrel;
}
/* fallthrough */
case DASM_REL_PC:
CK(n >= 0, UNDEF_PC);
n = *DASM_POS2PTR(D, n);
if (ins & 2048)
n = (n + (int)(size_t)base) & 0x0fffffff;
else
n = n - (int)((char *)cp - base);
patchrel: {
unsigned int e = 16 + ((ins >> 12) & 15);
CK((n & 3) == 0 &&
((n + ((ins & 2048) ? 0 : (1<<(e+1)))) >> (e+2)) == 0, RANGE_REL);
cp[-1] |= ((n>>2) & ((1<<e)-1));
}
break;
case DASM_LABEL_LG:
ins &= 2047; if (ins >= 20) D->globals[ins-10] = (void *)(base + n);
break;
case DASM_LABEL_PC: break;
case DASM_IMMS:
cp[-1] |= ((n>>3) & 4); n &= 0x1f;
/* fallthrough */
case DASM_IMM:
cp[-1] |= (n & ((1<<((ins>>5)&31))-1)) << (ins&31);
break;
default: *cp++ = ins; break;
}
}
stop: (void)0;
}
}
if (base + D->codesize != (char *)cp) /* Check for phase errors. */
return DASM_S_PHASE;
return DASM_S_OK;
}
#undef CK
/* Get PC label offset. */
int dasm_getpclabel(Dst_DECL, unsigned int pc)
{
dasm_State *D = Dst_REF;
if (pc*sizeof(int) < D->pcsize) {
int pos = D->pclabels[pc];
if (pos < 0) return *DASM_POS2PTR(D, -pos);
if (pos > 0) return -1; /* Undefined. */
}
return -2; /* Unused or out of range. */
}
#ifdef DASM_CHECKS
/* Optional sanity checker to call between isolated encoding steps. */
int dasm_checkstep(Dst_DECL, int secmatch)
{
dasm_State *D = Dst_REF;
if (D->status == DASM_S_OK) {
int i;
for (i = 1; i <= 9; i++) {
if (D->lglabels[i] > 0) { D->status = DASM_S_UNDEF_LG|i; break; }
D->lglabels[i] = 0;
}
}
if (D->status == DASM_S_OK && secmatch >= 0 &&
D->section != &D->sections[secmatch])
D->status = DASM_S_MATCH_SEC|(D->section-D->sections);
return D->status;
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,12 +0,0 @@
------------------------------------------------------------------------------
-- DynASM MIPS64 module.
--
-- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
-- See dynasm.lua for full copyright notice.
------------------------------------------------------------------------------
-- This module just sets 64 bit mode for the combined MIPS/MIPS64 module.
-- All the interesting stuff is there.
------------------------------------------------------------------------------
mips64 = true -- Using a global is an ugly, but effective solution.
return require("dasm_mips")

View file

@ -1,423 +0,0 @@
/*
** DynASM PPC/PPC64 encoding engine.
** Copyright (C) 2005-2021 Mike Pall. All rights reserved.
** Released under the MIT license. See dynasm.lua for full copyright notice.
*/
#include <stddef.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#define DASM_ARCH "ppc"
#ifndef DASM_EXTERN
#define DASM_EXTERN(a,b,c,d) 0
#endif
/* Action definitions. */
enum {
DASM_STOP, DASM_SECTION, DASM_ESC, DASM_REL_EXT,
/* The following actions need a buffer position. */
DASM_ALIGN, DASM_REL_LG, DASM_LABEL_LG,
/* The following actions also have an argument. */
DASM_REL_PC, DASM_LABEL_PC, DASM_IMM, DASM_IMMSH,
DASM__MAX
};
/* Maximum number of section buffer positions for a single dasm_put() call. */
#define DASM_MAXSECPOS 25
/* DynASM encoder status codes. Action list offset or number are or'ed in. */
#define DASM_S_OK 0x00000000
#define DASM_S_NOMEM 0x01000000
#define DASM_S_PHASE 0x02000000
#define DASM_S_MATCH_SEC 0x03000000
#define DASM_S_RANGE_I 0x11000000
#define DASM_S_RANGE_SEC 0x12000000
#define DASM_S_RANGE_LG 0x13000000
#define DASM_S_RANGE_PC 0x14000000
#define DASM_S_RANGE_REL 0x15000000
#define DASM_S_UNDEF_LG 0x21000000
#define DASM_S_UNDEF_PC 0x22000000
/* Macros to convert positions (8 bit section + 24 bit index). */
#define DASM_POS2IDX(pos) ((pos)&0x00ffffff)
#define DASM_POS2BIAS(pos) ((pos)&0xff000000)
#define DASM_SEC2POS(sec) ((sec)<<24)
#define DASM_POS2SEC(pos) ((pos)>>24)
#define DASM_POS2PTR(D, pos) (D->sections[DASM_POS2SEC(pos)].rbuf + (pos))
/* Action list type. */
typedef const unsigned int *dasm_ActList;
/* Per-section structure. */
typedef struct dasm_Section {
int *rbuf; /* Biased buffer pointer (negative section bias). */
int *buf; /* True buffer pointer. */
size_t bsize; /* Buffer size in bytes. */
int pos; /* Biased buffer position. */
int epos; /* End of biased buffer position - max single put. */
int ofs; /* Byte offset into section. */
} dasm_Section;
/* Core structure holding the DynASM encoding state. */
struct dasm_State {
size_t psize; /* Allocated size of this structure. */
dasm_ActList actionlist; /* Current actionlist pointer. */
int *lglabels; /* Local/global chain/pos ptrs. */
size_t lgsize;
int *pclabels; /* PC label chains/pos ptrs. */
size_t pcsize;
void **globals; /* Array of globals (bias -10). */
dasm_Section *section; /* Pointer to active section. */
size_t codesize; /* Total size of all code sections. */
int maxsection; /* 0 <= sectionidx < maxsection. */
int status; /* Status code. */
dasm_Section sections[1]; /* All sections. Alloc-extended. */
};
/* The size of the core structure depends on the max. number of sections. */
#define DASM_PSZ(ms) (sizeof(dasm_State)+(ms-1)*sizeof(dasm_Section))
/* Initialize DynASM state. */
void dasm_init(Dst_DECL, int maxsection)
{
dasm_State *D;
size_t psz = 0;
int i;
Dst_REF = NULL;
DASM_M_GROW(Dst, struct dasm_State, Dst_REF, psz, DASM_PSZ(maxsection));
D = Dst_REF;
D->psize = psz;
D->lglabels = NULL;
D->lgsize = 0;
D->pclabels = NULL;
D->pcsize = 0;
D->globals = NULL;
D->maxsection = maxsection;
for (i = 0; i < maxsection; i++) {
D->sections[i].buf = NULL; /* Need this for pass3. */
D->sections[i].rbuf = D->sections[i].buf - DASM_SEC2POS(i);
D->sections[i].bsize = 0;
D->sections[i].epos = 0; /* Wrong, but is recalculated after resize. */
}
}
/* Free DynASM state. */
void dasm_free(Dst_DECL)
{
dasm_State *D = Dst_REF;
int i;
for (i = 0; i < D->maxsection; i++)
if (D->sections[i].buf)
DASM_M_FREE(Dst, D->sections[i].buf, D->sections[i].bsize);
if (D->pclabels) DASM_M_FREE(Dst, D->pclabels, D->pcsize);
if (D->lglabels) DASM_M_FREE(Dst, D->lglabels, D->lgsize);
DASM_M_FREE(Dst, D, D->psize);
}
/* Setup global label array. Must be called before dasm_setup(). */
void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl)
{
dasm_State *D = Dst_REF;
D->globals = gl - 10; /* Negative bias to compensate for locals. */
DASM_M_GROW(Dst, int, D->lglabels, D->lgsize, (10+maxgl)*sizeof(int));
}
/* Grow PC label array. Can be called after dasm_setup(), too. */
void dasm_growpc(Dst_DECL, unsigned int maxpc)
{
dasm_State *D = Dst_REF;
size_t osz = D->pcsize;
DASM_M_GROW(Dst, int, D->pclabels, D->pcsize, maxpc*sizeof(int));
memset((void *)(((unsigned char *)D->pclabels)+osz), 0, D->pcsize-osz);
}
/* Setup encoder. */
void dasm_setup(Dst_DECL, const void *actionlist)
{
dasm_State *D = Dst_REF;
int i;
D->actionlist = (dasm_ActList)actionlist;
D->status = DASM_S_OK;
D->section = &D->sections[0];
memset((void *)D->lglabels, 0, D->lgsize);
if (D->pclabels) memset((void *)D->pclabels, 0, D->pcsize);
for (i = 0; i < D->maxsection; i++) {
D->sections[i].pos = DASM_SEC2POS(i);
D->sections[i].ofs = 0;
}
}
#ifdef DASM_CHECKS
#define CK(x, st) \
do { if (!(x)) { \
D->status = DASM_S_##st|(p-D->actionlist-1); return; } } while (0)
#define CKPL(kind, st) \
do { if ((size_t)((char *)pl-(char *)D->kind##labels) >= D->kind##size) { \
D->status = DASM_S_RANGE_##st|(p-D->actionlist-1); return; } } while (0)
#else
#define CK(x, st) ((void)0)
#define CKPL(kind, st) ((void)0)
#endif
/* Pass 1: Store actions and args, link branches/labels, estimate offsets. */
void dasm_put(Dst_DECL, int start, ...)
{
va_list ap;
dasm_State *D = Dst_REF;
dasm_ActList p = D->actionlist + start;
dasm_Section *sec = D->section;
int pos = sec->pos, ofs = sec->ofs;
int *b;
if (pos >= sec->epos) {
DASM_M_GROW(Dst, int, sec->buf, sec->bsize,
sec->bsize + 2*DASM_MAXSECPOS*sizeof(int));
sec->rbuf = sec->buf - DASM_POS2BIAS(pos);
sec->epos = (int)sec->bsize/sizeof(int) - DASM_MAXSECPOS+DASM_POS2BIAS(pos);
}
b = sec->rbuf;
b[pos++] = start;
va_start(ap, start);
while (1) {
unsigned int ins = *p++;
unsigned int action = (ins >> 16);
if (action >= DASM__MAX) {
ofs += 4;
} else {
int *pl, n = action >= DASM_REL_PC ? va_arg(ap, int) : 0;
switch (action) {
case DASM_STOP: goto stop;
case DASM_SECTION:
n = (ins & 255); CK(n < D->maxsection, RANGE_SEC);
D->section = &D->sections[n]; goto stop;
case DASM_ESC: p++; ofs += 4; break;
case DASM_REL_EXT: break;
case DASM_ALIGN: ofs += (ins & 255); b[pos++] = ofs; break;
case DASM_REL_LG:
n = (ins & 2047) - 10; pl = D->lglabels + n;
/* Bkwd rel or global. */
if (n >= 0) { CK(n>=10||*pl<0, RANGE_LG); CKPL(lg, LG); goto putrel; }
pl += 10; n = *pl;
if (n < 0) n = 0; /* Start new chain for fwd rel if label exists. */
goto linkrel;
case DASM_REL_PC:
pl = D->pclabels + n; CKPL(pc, PC);
putrel:
n = *pl;
if (n < 0) { /* Label exists. Get label pos and store it. */
b[pos] = -n;
} else {
linkrel:
b[pos] = n; /* Else link to rel chain, anchored at label. */
*pl = pos;
}
pos++;
break;
case DASM_LABEL_LG:
pl = D->lglabels + (ins & 2047) - 10; CKPL(lg, LG); goto putlabel;
case DASM_LABEL_PC:
pl = D->pclabels + n; CKPL(pc, PC);
putlabel:
n = *pl; /* n > 0: Collapse rel chain and replace with label pos. */
while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = pos;
}
*pl = -pos; /* Label exists now. */
b[pos++] = ofs; /* Store pass1 offset estimate. */
break;
case DASM_IMM:
#ifdef DASM_CHECKS
CK((n & ((1<<((ins>>10)&31))-1)) == 0, RANGE_I);
#endif
n >>= ((ins>>10)&31);
#ifdef DASM_CHECKS
if (ins & 0x8000)
CK(((n + (1<<(((ins>>5)&31)-1)))>>((ins>>5)&31)) == 0, RANGE_I);
else
CK((n>>((ins>>5)&31)) == 0, RANGE_I);
#endif
b[pos++] = n;
break;
case DASM_IMMSH:
CK((n >> 6) == 0, RANGE_I);
b[pos++] = n;
break;
}
}
}
stop:
va_end(ap);
sec->pos = pos;
sec->ofs = ofs;
}
#undef CK
/* Pass 2: Link sections, shrink aligns, fix label offsets. */
int dasm_link(Dst_DECL, size_t *szp)
{
dasm_State *D = Dst_REF;
int secnum;
int ofs = 0;
#ifdef DASM_CHECKS
*szp = 0;
if (D->status != DASM_S_OK) return D->status;
{
int pc;
for (pc = 0; pc*sizeof(int) < D->pcsize; pc++)
if (D->pclabels[pc] > 0) return DASM_S_UNDEF_PC|pc;
}
#endif
{ /* Handle globals not defined in this translation unit. */
int idx;
for (idx = 10; idx*sizeof(int) < D->lgsize; idx++) {
int n = D->lglabels[idx];
/* Undefined label: Collapse rel chain and replace with marker (< 0). */
while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; }
}
}
/* Combine all code sections. No support for data sections (yet). */
for (secnum = 0; secnum < D->maxsection; secnum++) {
dasm_Section *sec = D->sections + secnum;
int *b = sec->rbuf;
int pos = DASM_SEC2POS(secnum);
int lastpos = sec->pos;
while (pos != lastpos) {
dasm_ActList p = D->actionlist + b[pos++];
while (1) {
unsigned int ins = *p++;
unsigned int action = (ins >> 16);
switch (action) {
case DASM_STOP: case DASM_SECTION: goto stop;
case DASM_ESC: p++; break;
case DASM_REL_EXT: break;
case DASM_ALIGN: ofs -= (b[pos++] + ofs) & (ins & 255); break;
case DASM_REL_LG: case DASM_REL_PC: pos++; break;
case DASM_LABEL_LG: case DASM_LABEL_PC: b[pos++] += ofs; break;
case DASM_IMM: case DASM_IMMSH: pos++; break;
}
}
stop: (void)0;
}
ofs += sec->ofs; /* Next section starts right after current section. */
}
D->codesize = ofs; /* Total size of all code sections */
*szp = ofs;
return DASM_S_OK;
}
#ifdef DASM_CHECKS
#define CK(x, st) \
do { if (!(x)) return DASM_S_##st|(p-D->actionlist-1); } while (0)
#else
#define CK(x, st) ((void)0)
#endif
/* Pass 3: Encode sections. */
int dasm_encode(Dst_DECL, void *buffer)
{
dasm_State *D = Dst_REF;
char *base = (char *)buffer;
unsigned int *cp = (unsigned int *)buffer;
int secnum;
/* Encode all code sections. No support for data sections (yet). */
for (secnum = 0; secnum < D->maxsection; secnum++) {
dasm_Section *sec = D->sections + secnum;
int *b = sec->buf;
int *endb = sec->rbuf + sec->pos;
while (b != endb) {
dasm_ActList p = D->actionlist + *b++;
while (1) {
unsigned int ins = *p++;
unsigned int action = (ins >> 16);
int n = (action >= DASM_ALIGN && action < DASM__MAX) ? *b++ : 0;
switch (action) {
case DASM_STOP: case DASM_SECTION: goto stop;
case DASM_ESC: *cp++ = *p++; break;
case DASM_REL_EXT:
n = DASM_EXTERN(Dst, (unsigned char *)cp, (ins & 2047), 1) - 4;
goto patchrel;
case DASM_ALIGN:
ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0x60000000;
break;
case DASM_REL_LG:
if (n < 0) {
n = (int)((ptrdiff_t)D->globals[-n] - (ptrdiff_t)cp);
goto patchrel;
}
/* fallthrough */
case DASM_REL_PC:
CK(n >= 0, UNDEF_PC);
n = *DASM_POS2PTR(D, n) - (int)((char *)cp - base);
patchrel:
CK((n & 3) == 0 &&
(((n+4) + ((ins & 2048) ? 0x00008000 : 0x02000000)) >>
((ins & 2048) ? 16 : 26)) == 0, RANGE_REL);
cp[-1] |= ((n+4) & ((ins & 2048) ? 0x0000fffc: 0x03fffffc));
break;
case DASM_LABEL_LG:
ins &= 2047; if (ins >= 20) D->globals[ins-10] = (void *)(base + n);
break;
case DASM_LABEL_PC: break;
case DASM_IMM:
cp[-1] |= (n & ((1<<((ins>>5)&31))-1)) << (ins&31);
break;
case DASM_IMMSH:
cp[-1] |= (ins & 1) ? ((n&31)<<11)|((n&32)>>4) : ((n&31)<<6)|(n&32);
break;
default: *cp++ = ins; break;
}
}
stop: (void)0;
}
}
if (base + D->codesize != (char *)cp) /* Check for phase errors. */
return DASM_S_PHASE;
return DASM_S_OK;
}
#undef CK
/* Get PC label offset. */
int dasm_getpclabel(Dst_DECL, unsigned int pc)
{
dasm_State *D = Dst_REF;
if (pc*sizeof(int) < D->pcsize) {
int pos = D->pclabels[pc];
if (pos < 0) return *DASM_POS2PTR(D, -pos);
if (pos > 0) return -1; /* Undefined. */
}
return -2; /* Unused or out of range. */
}
#ifdef DASM_CHECKS
/* Optional sanity checker to call between isolated encoding steps. */
int dasm_checkstep(Dst_DECL, int secmatch)
{
dasm_State *D = Dst_REF;
if (D->status == DASM_S_OK) {
int i;
for (i = 1; i <= 9; i++) {
if (D->lglabels[i] > 0) { D->status = DASM_S_UNDEF_LG|i; break; }
D->lglabels[i] = 0;
}
}
if (D->status == DASM_S_OK && secmatch >= 0 &&
D->section != &D->sections[secmatch])
D->status = DASM_S_MATCH_SEC|(D->section-D->sections);
return D->status;
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,83 +0,0 @@
/*
** DynASM encoding engine prototypes.
** Copyright (C) 2005-2021 Mike Pall. All rights reserved.
** Released under the MIT license. See dynasm.lua for full copyright notice.
*/
#ifndef _DASM_PROTO_H
#define _DASM_PROTO_H
#include <stddef.h>
#include <stdarg.h>
#define DASM_IDENT "DynASM 1.5.0"
#define DASM_VERSION 10500 /* 1.5.0 */
#ifndef Dst_DECL
#define Dst_DECL dasm_State **Dst
#endif
#ifndef Dst_REF
#define Dst_REF (*Dst)
#endif
#ifndef DASM_FDEF
#define DASM_FDEF extern
#endif
#ifndef DASM_M_GROW
#define DASM_M_GROW(ctx, t, p, sz, need) \
do { \
size_t _sz = (sz), _need = (need); \
if (_sz < _need) { \
if (_sz < 16) _sz = 16; \
while (_sz < _need) _sz += _sz; \
(p) = (t *)realloc((p), _sz); \
if ((p) == NULL) exit(1); \
(sz) = _sz; \
} \
} while(0)
#endif
#ifndef DASM_M_FREE
#define DASM_M_FREE(ctx, p, sz) free(p)
#endif
/* Internal DynASM encoder state. */
typedef struct dasm_State dasm_State;
/* Initialize and free DynASM state. */
DASM_FDEF void dasm_init(Dst_DECL, int maxsection);
DASM_FDEF void dasm_free(Dst_DECL);
/* Setup global array. Must be called before dasm_setup(). */
DASM_FDEF void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl);
/* Grow PC label array. Can be called after dasm_setup(), too. */
DASM_FDEF void dasm_growpc(Dst_DECL, unsigned int maxpc);
/* Setup encoder. */
DASM_FDEF void dasm_setup(Dst_DECL, const void *actionlist);
/* Feed encoder with actions. Calls are generated by pre-processor. */
DASM_FDEF void dasm_put(Dst_DECL, int start, ...);
/* Link sections and return the resulting size. */
DASM_FDEF int dasm_link(Dst_DECL, size_t *szp);
/* Encode sections into buffer. */
DASM_FDEF int dasm_encode(Dst_DECL, void *buffer);
/* Get PC label offset. */
DASM_FDEF int dasm_getpclabel(Dst_DECL, unsigned int pc);
#ifdef DASM_CHECKS
/* Optional sanity checker to call between isolated encoding steps. */
DASM_FDEF int dasm_checkstep(Dst_DECL, int secmatch);
#else
#define dasm_checkstep(a, b) 0
#endif
#endif /* _DASM_PROTO_H */

View file

@ -1,12 +0,0 @@
------------------------------------------------------------------------------
-- DynASM x64 module.
--
-- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
-- See dynasm.lua for full copyright notice.
------------------------------------------------------------------------------
-- This module just sets 64 bit mode for the combined x86/x64 module.
-- All the interesting stuff is there.
------------------------------------------------------------------------------
x64 = true -- Using a global is an ugly, but effective solution.
return require("dasm_x86")

View file

@ -1,540 +0,0 @@
/*
** DynASM x86 encoding engine.
** Copyright (C) 2005-2021 Mike Pall. All rights reserved.
** Released under the MIT license. See dynasm.lua for full copyright notice.
*/
#include <stddef.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#define DASM_ARCH "x86"
#ifndef DASM_EXTERN
#define DASM_EXTERN(a,b,c,d) 0
#endif
/* Action definitions. DASM_STOP must be 255. */
enum {
DASM_DISP = 233,
DASM_IMM_S, DASM_IMM_B, DASM_IMM_W, DASM_IMM_D, DASM_IMM_WB, DASM_IMM_DB,
DASM_VREG, DASM_SPACE, DASM_SETLABEL, DASM_REL_A, DASM_REL_LG, DASM_REL_PC,
DASM_IMM_LG, DASM_IMM_PC, DASM_LABEL_LG, DASM_LABEL_PC, DASM_ALIGN,
DASM_EXTERN, DASM_ESC, DASM_MARK, DASM_SECTION, DASM_STOP
};
/* Maximum number of section buffer positions for a single dasm_put() call. */
#define DASM_MAXSECPOS 25
/* DynASM encoder status codes. Action list offset or number are or'ed in. */
#define DASM_S_OK 0x00000000
#define DASM_S_NOMEM 0x01000000
#define DASM_S_PHASE 0x02000000
#define DASM_S_MATCH_SEC 0x03000000
#define DASM_S_RANGE_I 0x11000000
#define DASM_S_RANGE_SEC 0x12000000
#define DASM_S_RANGE_LG 0x13000000
#define DASM_S_RANGE_PC 0x14000000
#define DASM_S_RANGE_VREG 0x15000000
#define DASM_S_UNDEF_L 0x21000000
#define DASM_S_UNDEF_PC 0x22000000
/* Macros to convert positions (8 bit section + 24 bit index). */
#define DASM_POS2IDX(pos) ((pos)&0x00ffffff)
#define DASM_POS2BIAS(pos) ((pos)&0xff000000)
#define DASM_SEC2POS(sec) ((sec)<<24)
#define DASM_POS2SEC(pos) ((pos)>>24)
#define DASM_POS2PTR(D, pos) (D->sections[DASM_POS2SEC(pos)].rbuf + (pos))
/* Action list type. */
typedef const unsigned char *dasm_ActList;
/* Per-section structure. */
typedef struct dasm_Section {
int *rbuf; /* Biased buffer pointer (negative section bias). */
int *buf; /* True buffer pointer. */
size_t bsize; /* Buffer size in bytes. */
int pos; /* Biased buffer position. */
int epos; /* End of biased buffer position - max single put. */
int ofs; /* Byte offset into section. */
} dasm_Section;
/* Core structure holding the DynASM encoding state. */
struct dasm_State {
size_t psize; /* Allocated size of this structure. */
dasm_ActList actionlist; /* Current actionlist pointer. */
int *lglabels; /* Local/global chain/pos ptrs. */
size_t lgsize;
int *pclabels; /* PC label chains/pos ptrs. */
size_t pcsize;
void **globals; /* Array of globals (bias -10). */
dasm_Section *section; /* Pointer to active section. */
size_t codesize; /* Total size of all code sections. */
int maxsection; /* 0 <= sectionidx < maxsection. */
int status; /* Status code. */
dasm_Section sections[1]; /* All sections. Alloc-extended. */
};
/* The size of the core structure depends on the max. number of sections. */
#define DASM_PSZ(ms) (sizeof(dasm_State)+(ms-1)*sizeof(dasm_Section))
/* Perform potentially overflowing pointer operations in a way that avoids UB. */
#define DASM_PTR_SUB(p1, off) ((void *) ((uintptr_t) (p1) - sizeof(*p1) * (uintptr_t) (off)))
#define DASM_PTR_ADD(p1, off) ((void *) ((uintptr_t) (p1) + sizeof(*p1) * (uintptr_t) (off)))
/* Initialize DynASM state. */
void dasm_init(Dst_DECL, int maxsection)
{
dasm_State *D;
size_t psz = 0;
int i;
Dst_REF = NULL;
DASM_M_GROW(Dst, struct dasm_State, Dst_REF, psz, DASM_PSZ(maxsection));
D = Dst_REF;
D->psize = psz;
D->lglabels = NULL;
D->lgsize = 0;
D->pclabels = NULL;
D->pcsize = 0;
D->globals = NULL;
D->maxsection = maxsection;
for (i = 0; i < maxsection; i++) {
D->sections[i].buf = NULL; /* Need this for pass3. */
D->sections[i].rbuf = DASM_PTR_SUB(D->sections[i].buf, DASM_SEC2POS(i));
D->sections[i].bsize = 0;
D->sections[i].epos = 0; /* Wrong, but is recalculated after resize. */
}
}
/* Free DynASM state. */
void dasm_free(Dst_DECL)
{
dasm_State *D = Dst_REF;
int i;
for (i = 0; i < D->maxsection; i++)
if (D->sections[i].buf)
DASM_M_FREE(Dst, D->sections[i].buf, D->sections[i].bsize);
if (D->pclabels) DASM_M_FREE(Dst, D->pclabels, D->pcsize);
if (D->lglabels) DASM_M_FREE(Dst, D->lglabels, D->lgsize);
DASM_M_FREE(Dst, D, D->psize);
}
/* Setup global label array. Must be called before dasm_setup(). */
void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl)
{
dasm_State *D = Dst_REF;
#ifdef __GNUC__
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Warray-bounds"
#endif
D->globals = gl - 10; /* Negative bias to compensate for locals. */
#ifdef __GNUC__
# pragma GCC diagnostic pop
#endif
DASM_M_GROW(Dst, int, D->lglabels, D->lgsize, (10+maxgl)*sizeof(int));
}
/* Grow PC label array. Can be called after dasm_setup(), too. */
void dasm_growpc(Dst_DECL, unsigned int maxpc)
{
dasm_State *D = Dst_REF;
size_t osz = D->pcsize;
DASM_M_GROW(Dst, int, D->pclabels, D->pcsize, maxpc*sizeof(int));
memset((void *)(((unsigned char *)D->pclabels)+osz), 0, D->pcsize-osz);
}
/* Setup encoder. */
void dasm_setup(Dst_DECL, const void *actionlist)
{
dasm_State *D = Dst_REF;
int i;
D->actionlist = (dasm_ActList)actionlist;
D->status = DASM_S_OK;
D->section = &D->sections[0];
memset((void *)D->lglabels, 0, D->lgsize);
if (D->pclabels) memset((void *)D->pclabels, 0, D->pcsize);
for (i = 0; i < D->maxsection; i++) {
D->sections[i].pos = DASM_SEC2POS(i);
D->sections[i].ofs = 0;
}
}
#ifdef DASM_CHECKS
#define CK(x, st) \
do { if (!(x)) { \
D->status = DASM_S_##st|(int)(p-D->actionlist-1); return; } } while (0)
#define CKPL(kind, st) \
do { if ((size_t)((char *)pl-(char *)D->kind##labels) >= D->kind##size) { \
D->status=DASM_S_RANGE_##st|(int)(p-D->actionlist-1); return; } } while (0)
#else
#define CK(x, st) ((void)0)
#define CKPL(kind, st) ((void)0)
#endif
/* Pass 1: Store actions and args, link branches/labels, estimate offsets. */
void dasm_put(Dst_DECL, int start, ...)
{
va_list ap;
dasm_State *D = Dst_REF;
dasm_ActList p = D->actionlist + start;
dasm_Section *sec = D->section;
int pos = sec->pos, ofs = sec->ofs, mrm = -1;
int *b;
if (pos >= sec->epos) {
DASM_M_GROW(Dst, int, sec->buf, sec->bsize,
sec->bsize + 2*DASM_MAXSECPOS*sizeof(int));
sec->rbuf = sec->buf - DASM_POS2BIAS(pos);
sec->epos = (int)sec->bsize/sizeof(int) - DASM_MAXSECPOS+DASM_POS2BIAS(pos);
}
b = sec->rbuf;
b[pos++] = start;
va_start(ap, start);
while (1) {
int action = *p++;
if (action < DASM_DISP) {
ofs++;
} else if (action <= DASM_REL_A) {
int n = va_arg(ap, int);
b[pos++] = n;
switch (action) {
case DASM_DISP:
if (n == 0) { if (mrm < 0) mrm = p[-2]; if ((mrm&7) != 5) break; }
/* fallthrough */
case DASM_IMM_DB: if ((((unsigned)n+128)&-256) == 0) goto ob; /* fallthrough */
case DASM_REL_A: /* Assumes ptrdiff_t is int. !x64 */
case DASM_IMM_D: ofs += 4; break;
case DASM_IMM_S: CK(((n+128)&-256) == 0, RANGE_I); goto ob;
case DASM_IMM_B: CK((n&-256) == 0, RANGE_I); ob: ofs++; break;
case DASM_IMM_WB: if (((n+128)&-256) == 0) goto ob; /* fallthrough */
case DASM_IMM_W: CK((n&-65536) == 0, RANGE_I); ofs += 2; break;
case DASM_SPACE: p++; ofs += n; break;
case DASM_SETLABEL: b[pos-2] = -0x40000000; break; /* Neg. label ofs. */
case DASM_VREG: CK((n&-16) == 0 && (n != 4 || (*p>>5) != 2), RANGE_VREG);
if (*p < 0x40 && p[1] == DASM_DISP) mrm = n;
if (*p < 0x20 && (n&7) == 4) ofs++;
switch ((*p++ >> 3) & 3) {
case 3: n |= b[pos-3]; /* fallthrough */
case 2: n |= b[pos-2]; /* fallthrough */
case 1: if (n <= 7) { b[pos-1] |= 0x10; ofs--; }
}
continue;
}
mrm = -1;
} else {
int *pl, n;
switch (action) {
case DASM_REL_LG:
case DASM_IMM_LG:
n = *p++; pl = D->lglabels + n;
/* Bkwd rel or global. */
if (n <= 246) { CK(n>=10||*pl<0, RANGE_LG); CKPL(lg, LG); goto putrel; }
pl -= 246; n = *pl;
if (n < 0) n = 0; /* Start new chain for fwd rel if label exists. */
goto linkrel;
case DASM_REL_PC:
case DASM_IMM_PC: pl = D->pclabels + va_arg(ap, int); CKPL(pc, PC);
putrel:
n = *pl;
if (n < 0) { /* Label exists. Get label pos and store it. */
b[pos] = -n;
} else {
linkrel:
b[pos] = n; /* Else link to rel chain, anchored at label. */
*pl = pos;
}
pos++;
ofs += 4; /* Maximum offset needed. */
if (action == DASM_REL_LG || action == DASM_REL_PC) {
b[pos++] = ofs; /* Store pass1 offset estimate. */
} else if (sizeof(ptrdiff_t) == 8) {
ofs += 4;
}
break;
case DASM_LABEL_LG: pl = D->lglabels + *p++; CKPL(lg, LG); goto putlabel;
case DASM_LABEL_PC: pl = D->pclabels + va_arg(ap, int); CKPL(pc, PC);
putlabel:
n = *pl; /* n > 0: Collapse rel chain and replace with label pos. */
while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = pos; }
*pl = -pos; /* Label exists now. */
b[pos++] = ofs; /* Store pass1 offset estimate. */
break;
case DASM_ALIGN:
ofs += *p++; /* Maximum alignment needed (arg is 2**n-1). */
b[pos++] = ofs; /* Store pass1 offset estimate. */
break;
case DASM_EXTERN: p += 2; ofs += 4; break;
case DASM_ESC: p++; ofs++; break;
case DASM_MARK: mrm = p[-2]; break;
case DASM_SECTION:
n = *p; CK(n < D->maxsection, RANGE_SEC); D->section = &D->sections[n];
case DASM_STOP: goto stop;
}
}
}
stop:
va_end(ap);
sec->pos = pos;
sec->ofs = ofs;
}
#undef CK
/* Pass 2: Link sections, shrink branches/aligns, fix label offsets. */
int dasm_link(Dst_DECL, size_t *szp)
{
dasm_State *D = Dst_REF;
int secnum;
int ofs = 0;
#ifdef DASM_CHECKS
*szp = 0;
if (D->status != DASM_S_OK) return D->status;
{
int pc;
for (pc = 0; pc*sizeof(int) < D->pcsize; pc++)
if (D->pclabels[pc] > 0) return DASM_S_UNDEF_PC|pc;
}
#endif
{ /* Handle globals not defined in this translation unit. */
int idx;
for (idx = 10; idx*sizeof(int) < D->lgsize; idx++) {
int n = D->lglabels[idx];
/* Undefined label: Collapse rel chain and replace with marker (< 0). */
while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; }
}
}
/* Combine all code sections. No support for data sections (yet). */
for (secnum = 0; secnum < D->maxsection; secnum++) {
dasm_Section *sec = D->sections + secnum;
int *b = sec->rbuf;
int pos = DASM_SEC2POS(secnum);
int lastpos = sec->pos;
while (pos != lastpos) {
dasm_ActList p = D->actionlist + b[pos++];
int op = 0;
while (1) {
int action = *p++;
switch (action) {
case DASM_REL_LG: p++;
/* fallthrough */
case DASM_REL_PC: {
int shrink = op == 0xe9 ? 3 : ((op&0xf0) == 0x80 ? 4 : 0);
if (shrink) { /* Shrinkable branch opcode? */
int lofs, lpos = b[pos];
if (lpos < 0) goto noshrink; /* Ext global? */
lofs = *DASM_POS2PTR(D, lpos);
if (lpos > pos) { /* Fwd label: add cumulative section offsets. */
int i;
for (i = secnum; i < DASM_POS2SEC(lpos); i++)
lofs += D->sections[i].ofs;
} else {
lofs -= ofs; /* Bkwd label: unfix offset. */
}
lofs -= b[pos+1]; /* Short branch ok? */
if (lofs >= -128-shrink && lofs <= 127) ofs -= shrink; /* Yes. */
else { noshrink: shrink = 0; } /* No, cannot shrink op. */
}
b[pos+1] = shrink;
pos += 2;
break;
}
/* fallthrough */
case DASM_SPACE: case DASM_IMM_LG: case DASM_VREG: p++;
case DASM_DISP: case DASM_IMM_S: case DASM_IMM_B: case DASM_IMM_W:
case DASM_IMM_D: case DASM_IMM_WB: case DASM_IMM_DB:
case DASM_SETLABEL: case DASM_REL_A: case DASM_IMM_PC: pos++; break;
case DASM_LABEL_LG: p++;
/* fallthrough */
case DASM_LABEL_PC: b[pos++] += ofs; break; /* Fix label offset. */
case DASM_ALIGN: ofs -= (b[pos++]+ofs)&*p++; break; /* Adjust ofs. */
case DASM_EXTERN: p += 2; break;
case DASM_ESC: op = *p++; break;
case DASM_MARK: break;
case DASM_SECTION: case DASM_STOP: goto stop;
default: op = action; break;
}
}
stop: (void)0;
}
ofs += sec->ofs; /* Next section starts right after current section. */
}
D->codesize = ofs; /* Total size of all code sections */
*szp = ofs;
return DASM_S_OK;
}
#define dasmb(x) *cp++ = (unsigned char)(x)
#ifndef DASM_ALIGNED_WRITES
typedef ZEND_SET_ALIGNED(1, unsigned short unaligned_short);
typedef ZEND_SET_ALIGNED(1, unsigned int unaligned_int);
typedef ZEND_SET_ALIGNED(1, unsigned long long unaligned_long_long);
#define dasmw(x) \
do { *((unaligned_short *)cp) = (unsigned short)(x); cp+=2; } while (0)
#define dasmd(x) \
do { *((unaligned_int *)cp) = (unsigned int)(x); cp+=4; } while (0)
#define dasmq(x) \
do { *((unaligned_long_long *)cp) = (unsigned long long)(x); cp+=8; } while (0)
#else
#define dasmw(x) do { dasmb(x); dasmb((x)>>8); } while (0)
#define dasmd(x) do { dasmw(x); dasmw((x)>>16); } while (0)
#define dasmq(x) do { dasmd(x); dasmd((x)>>32); } while (0)
#endif
static unsigned char *dasma_(unsigned char *cp, ptrdiff_t x)
{
if (sizeof(ptrdiff_t) == 8)
dasmq((unsigned long long)x);
else
dasmd((unsigned int)x);
return cp;
}
#define dasma(x) (cp = dasma_(cp, (x)))
/* Pass 3: Encode sections. */
int dasm_encode(Dst_DECL, void *buffer)
{
dasm_State *D = Dst_REF;
unsigned char *base = (unsigned char *)buffer;
unsigned char *cp = base;
int secnum;
/* Encode all code sections. No support for data sections (yet). */
for (secnum = 0; secnum < D->maxsection; secnum++) {
dasm_Section *sec = D->sections + secnum;
int *b = sec->buf;
int *endb = DASM_PTR_ADD(sec->rbuf, sec->pos);
while (b != endb) {
dasm_ActList p = D->actionlist + *b++;
unsigned char *mark = NULL;
while (1) {
int action = *p++;
int n = (action >= DASM_DISP && action <= DASM_ALIGN) ? *b++ : 0;
switch (action) {
case DASM_DISP: if (!mark) mark = cp; {
unsigned char *mm = mark;
if (*p != DASM_IMM_DB && *p != DASM_IMM_WB) mark = NULL;
if (n == 0) { int mrm = mm[-1]&7; if (mrm == 4) mrm = mm[0]&7;
if (mrm != 5) { mm[-1] -= 0x80; break; } }
if ((((unsigned)n+128) & -256) != 0) goto wd; else mm[-1] -= 0x40;
}
/* fallthrough */
case DASM_IMM_S: case DASM_IMM_B: wb: dasmb(n); break;
case DASM_IMM_DB: if ((((unsigned)n+128)&-256) == 0) {
db: if (!mark) mark = cp; mark[-2] += 2; mark = NULL; goto wb;
} else mark = NULL;
/* fallthrough */
case DASM_IMM_D: wd: dasmd(n); break;
case DASM_IMM_WB: if ((((unsigned)n+128)&-256) == 0) goto db; else mark = NULL;
/* fallthrough */
case DASM_IMM_W: dasmw(n); break;
case DASM_VREG: {
int t = *p++;
unsigned char *ex = cp - (t&7);
if ((n & 8) && t < 0xa0) {
if (*ex & 0x80) ex[1] ^= 0x20 << (t>>6); else *ex ^= 1 << (t>>6);
n &= 7;
} else if (n & 0x10) {
if (*ex & 0x80) {
*ex = 0xc5; ex[1] = (ex[1] & 0x80) | ex[2]; ex += 2;
}
while (++ex < cp) ex[-1] = *ex;
if (mark) mark--;
cp--;
n &= 7;
}
if (t >= 0xc0) n <<= 4;
else if (t >= 0x40) n <<= 3;
else if (n == 4 && t < 0x20) { cp[-1] ^= n; *cp++ = 0x20; }
cp[-1] ^= n;
break;
}
case DASM_REL_LG: p++; if (n >= 0) goto rel_pc;
b++; n = (int)(ptrdiff_t)D->globals[-n];
/* fallthrough */
case DASM_REL_A: rel_a:
n -= (unsigned int)(ptrdiff_t)(cp+4); goto wd; /* !x64 */
case DASM_REL_PC: rel_pc: {
int shrink = *b++;
int *pb = DASM_POS2PTR(D, n); if (*pb < 0) { n = pb[1]; goto rel_a; }
n = *pb - ((int)(cp-base) + 4-shrink);
if (shrink == 0) goto wd;
if (shrink == 4) { cp--; cp[-1] = *cp-0x10; } else cp[-1] = 0xeb;
goto wb;
}
case DASM_IMM_LG:
p++;
if (n < 0) { dasma((ptrdiff_t)D->globals[-n]); break; }
/* fallthrough */
case DASM_IMM_PC: {
int *pb = DASM_POS2PTR(D, n);
dasma(*pb < 0 ? (ptrdiff_t)pb[1] : (*pb + (ptrdiff_t)base));
break;
}
case DASM_LABEL_LG: {
int idx = *p++;
if (idx >= 10)
D->globals[idx] = (void *)(base + (*p == DASM_SETLABEL ? *b : n));
break;
}
case DASM_LABEL_PC: case DASM_SETLABEL: break;
case DASM_SPACE: { int fill = *p++; while (n--) *cp++ = fill; break; }
case DASM_ALIGN:
n = *p++;
while (((cp-base) & n)) *cp++ = 0x90; /* nop */
break;
case DASM_EXTERN: n = DASM_EXTERN(Dst, cp, p[1], *p); p += 2; goto wd;
case DASM_MARK: mark = cp; break;
case DASM_ESC: action = *p++;
/* fallthrough */
default: *cp++ = action; break;
case DASM_SECTION: case DASM_STOP: goto stop;
}
}
stop: (void)0;
}
}
if (base + D->codesize != cp) /* Check for phase errors. */
return DASM_S_PHASE;
return DASM_S_OK;
}
/* Get PC label offset. */
int dasm_getpclabel(Dst_DECL, unsigned int pc)
{
dasm_State *D = Dst_REF;
if (pc*sizeof(int) < D->pcsize) {
int pos = D->pclabels[pc];
if (pos < 0) return *DASM_POS2PTR(D, -pos);
if (pos > 0) return -1; /* Undefined. */
}
return -2; /* Unused or out of range. */
}
#ifdef DASM_CHECKS
/* Optional sanity checker to call between isolated encoding steps. */
int dasm_checkstep(Dst_DECL, int secmatch)
{
dasm_State *D = Dst_REF;
if (D->status == DASM_S_OK) {
int i;
for (i = 1; i <= 9; i++) {
if (D->lglabels[i] > 0) { D->status = DASM_S_UNDEF_L|i; break; }
D->lglabels[i] = 0;
}
}
if (D->status == DASM_S_OK && secmatch >= 0 &&
D->section != &D->sections[secmatch])
D->status = DASM_S_MATCH_SEC|(int)(D->section-D->sections);
return D->status;
}
#endif

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,22 +0,0 @@
Copyright (c) 2002-2012, Vivek Thampi <vivek.mt@gmail.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

File diff suppressed because it is too large Load diff

View file

@ -1,197 +0,0 @@
/* udis86 - libudis86/decode.h
*
* Copyright (c) 2002-2009 Vivek Thampi
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef UD_DECODE_H
#define UD_DECODE_H
#include "types.h"
#include "udint.h"
#include "itab.h"
#define MAX_INSN_LENGTH 15
/* itab prefix bits */
#define P_none ( 0 )
#define P_inv64 ( 1 << 0 )
#define P_INV64(n) ( ( n >> 0 ) & 1 )
#define P_def64 ( 1 << 1 )
#define P_DEF64(n) ( ( n >> 1 ) & 1 )
#define P_oso ( 1 << 2 )
#define P_OSO(n) ( ( n >> 2 ) & 1 )
#define P_aso ( 1 << 3 )
#define P_ASO(n) ( ( n >> 3 ) & 1 )
#define P_rexb ( 1 << 4 )
#define P_REXB(n) ( ( n >> 4 ) & 1 )
#define P_rexw ( 1 << 5 )
#define P_REXW(n) ( ( n >> 5 ) & 1 )
#define P_rexr ( 1 << 6 )
#define P_REXR(n) ( ( n >> 6 ) & 1 )
#define P_rexx ( 1 << 7 )
#define P_REXX(n) ( ( n >> 7 ) & 1 )
#define P_seg ( 1 << 8 )
#define P_SEG(n) ( ( n >> 8 ) & 1 )
#define P_vexl ( 1 << 9 )
#define P_VEXL(n) ( ( n >> 9 ) & 1 )
#define P_vexw ( 1 << 10 )
#define P_VEXW(n) ( ( n >> 10 ) & 1 )
#define P_str ( 1 << 11 )
#define P_STR(n) ( ( n >> 11 ) & 1 )
#define P_strz ( 1 << 12 )
#define P_STR_ZF(n) ( ( n >> 12 ) & 1 )
/* operand type constants -- order is important! */
enum ud_operand_code {
OP_NONE,
OP_A, OP_E, OP_M, OP_G,
OP_I, OP_F,
OP_R0, OP_R1, OP_R2, OP_R3,
OP_R4, OP_R5, OP_R6, OP_R7,
OP_AL, OP_CL, OP_DL,
OP_AX, OP_CX, OP_DX,
OP_eAX, OP_eCX, OP_eDX,
OP_rAX, OP_rCX, OP_rDX,
OP_ES, OP_CS, OP_SS, OP_DS,
OP_FS, OP_GS,
OP_ST0, OP_ST1, OP_ST2, OP_ST3,
OP_ST4, OP_ST5, OP_ST6, OP_ST7,
OP_J, OP_S, OP_O,
OP_I1, OP_I3, OP_sI,
OP_V, OP_W, OP_Q, OP_P,
OP_U, OP_N, OP_MU, OP_H,
OP_L,
OP_R, OP_C, OP_D,
OP_MR
} UD_ATTR_PACKED;
/*
* Operand size constants
*
* Symbolic constants for various operand sizes. Some of these constants
* are given a value equal to the width of the data (SZ_B == 8), such
* that they maybe used interchangeably in the internals. Modifying them
* will most certainly break things!
*/
typedef uint16_t ud_operand_size_t;
#define SZ_NA 0
#define SZ_Z 1
#define SZ_V 2
#define SZ_Y 3
#define SZ_X 4
#define SZ_RDQ 7
#define SZ_B 8
#define SZ_W 16
#define SZ_D 32
#define SZ_Q 64
#define SZ_T 80
#define SZ_O 12
#define SZ_DQ 128 /* double quad */
#define SZ_QQ 256 /* quad quad */
/*
* Complex size types; that encode sizes for operands of type MR (memory or
* register); for internal use only. Id space above 256.
*/
#define SZ_BD ((SZ_B << 8) | SZ_D)
#define SZ_BV ((SZ_B << 8) | SZ_V)
#define SZ_WD ((SZ_W << 8) | SZ_D)
#define SZ_WV ((SZ_W << 8) | SZ_V)
#define SZ_WY ((SZ_W << 8) | SZ_Y)
#define SZ_DY ((SZ_D << 8) | SZ_Y)
#define SZ_WO ((SZ_W << 8) | SZ_O)
#define SZ_DO ((SZ_D << 8) | SZ_O)
#define SZ_QO ((SZ_Q << 8) | SZ_O)
/* resolve complex size type.
*/
static UD_INLINE ud_operand_size_t
Mx_mem_size(ud_operand_size_t size)
{
return (size >> 8) & 0xff;
}
static UD_INLINE ud_operand_size_t
Mx_reg_size(ud_operand_size_t size)
{
return size & 0xff;
}
/* A single operand of an entry in the instruction table.
* (internal use only)
*/
struct ud_itab_entry_operand
{
enum ud_operand_code type;
ud_operand_size_t size;
};
/* A single entry in an instruction table.
*(internal use only)
*/
struct ud_itab_entry
{
enum ud_mnemonic_code mnemonic;
struct ud_itab_entry_operand operand1;
struct ud_itab_entry_operand operand2;
struct ud_itab_entry_operand operand3;
struct ud_itab_entry_operand operand4;
uint32_t prefix;
};
struct ud_lookup_table_list_entry {
const uint16_t *table;
enum ud_table_type type;
const char *meta;
};
extern struct ud_itab_entry ud_itab[];
extern struct ud_lookup_table_list_entry ud_lookup_table_list[];
#endif /* UD_DECODE_H */
/* vim:cindent
* vim:expandtab
* vim:ts=4
* vim:sw=4
*/

View file

@ -1,113 +0,0 @@
/* udis86 - libudis86/extern.h
*
* Copyright (c) 2002-2009, 2013 Vivek Thampi
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef UD_EXTERN_H
#define UD_EXTERN_H
#ifdef __cplusplus
extern "C" {
#endif
#include "types.h"
#if defined(_MSC_VER) && defined(_USRDLL)
# ifdef LIBUDIS86_EXPORTS
# define LIBUDIS86_DLLEXTERN __declspec(dllexport)
# else
# define LIBUDIS86_DLLEXTERN __declspec(dllimport)
# endif
#else
# define LIBUDIS86_DLLEXTERN
#endif
/* ============================= PUBLIC API ================================= */
extern LIBUDIS86_DLLEXTERN void ud_init(struct ud*);
extern LIBUDIS86_DLLEXTERN void ud_set_mode(struct ud*, uint8_t);
extern LIBUDIS86_DLLEXTERN void ud_set_pc(struct ud*, uint64_t);
extern LIBUDIS86_DLLEXTERN void ud_set_input_hook(struct ud*, int (*)(struct ud*));
extern LIBUDIS86_DLLEXTERN void ud_set_input_buffer(struct ud*, const uint8_t*, size_t);
#ifndef __UD_STANDALONE__
extern LIBUDIS86_DLLEXTERN void ud_set_input_file(struct ud*, FILE*);
#endif /* __UD_STANDALONE__ */
extern LIBUDIS86_DLLEXTERN void ud_set_vendor(struct ud*, unsigned);
extern LIBUDIS86_DLLEXTERN void ud_set_syntax(struct ud*, void (*)(struct ud*));
extern LIBUDIS86_DLLEXTERN void ud_input_skip(struct ud*, size_t);
extern LIBUDIS86_DLLEXTERN int ud_input_end(const struct ud*);
extern LIBUDIS86_DLLEXTERN unsigned int ud_decode(struct ud*);
extern LIBUDIS86_DLLEXTERN unsigned int ud_disassemble(struct ud*);
extern LIBUDIS86_DLLEXTERN void ud_translate_intel(struct ud*);
extern LIBUDIS86_DLLEXTERN void ud_translate_att(struct ud*);
extern LIBUDIS86_DLLEXTERN const char* ud_insn_asm(const struct ud* u);
extern LIBUDIS86_DLLEXTERN const uint8_t* ud_insn_ptr(const struct ud* u);
extern LIBUDIS86_DLLEXTERN uint64_t ud_insn_off(const struct ud*);
extern LIBUDIS86_DLLEXTERN const char* ud_insn_hex(struct ud*);
extern LIBUDIS86_DLLEXTERN unsigned int ud_insn_len(const struct ud* u);
extern LIBUDIS86_DLLEXTERN const struct ud_operand* ud_insn_opr(const struct ud *u, unsigned int n);
extern LIBUDIS86_DLLEXTERN int ud_opr_is_sreg(const struct ud_operand *opr);
extern LIBUDIS86_DLLEXTERN int ud_opr_is_gpr(const struct ud_operand *opr);
extern LIBUDIS86_DLLEXTERN enum ud_mnemonic_code ud_insn_mnemonic(const struct ud *u);
extern LIBUDIS86_DLLEXTERN const char* ud_lookup_mnemonic(enum ud_mnemonic_code c);
extern LIBUDIS86_DLLEXTERN void ud_set_user_opaque_data(struct ud*, void*);
extern LIBUDIS86_DLLEXTERN void* ud_get_user_opaque_data(const struct ud*);
extern LIBUDIS86_DLLEXTERN void ud_set_asm_buffer(struct ud *u, char *buf, size_t size);
extern LIBUDIS86_DLLEXTERN void ud_set_sym_resolver(struct ud *u,
const char* (*resolver)(struct ud*,
uint64_t addr,
int64_t *offset));
/* ========================================================================== */
#ifdef __cplusplus
}
#endif
#endif /* UD_EXTERN_H */

File diff suppressed because it is too large Load diff

View file

@ -1,939 +0,0 @@
#ifndef UD_ITAB_H
#define UD_ITAB_H
/* itab.h -- generated by udis86:scripts/ud_itab.py, do no edit */
/* ud_table_type -- lookup table types (see decode.c) */
enum ud_table_type {
UD_TAB__OPC_VEX,
UD_TAB__OPC_TABLE,
UD_TAB__OPC_X87,
UD_TAB__OPC_MOD,
UD_TAB__OPC_RM,
UD_TAB__OPC_OSIZE,
UD_TAB__OPC_MODE,
UD_TAB__OPC_VEX_L,
UD_TAB__OPC_3DNOW,
UD_TAB__OPC_REG,
UD_TAB__OPC_ASIZE,
UD_TAB__OPC_VEX_W,
UD_TAB__OPC_SSE,
UD_TAB__OPC_VENDOR
};
/* ud_mnemonic -- mnemonic constants */
enum ud_mnemonic_code {
UD_Iaaa,
UD_Iaad,
UD_Iaam,
UD_Iaas,
UD_Iadc,
UD_Iadd,
UD_Iaddpd,
UD_Iaddps,
UD_Iaddsd,
UD_Iaddss,
UD_Iaddsubpd,
UD_Iaddsubps,
UD_Iaesdec,
UD_Iaesdeclast,
UD_Iaesenc,
UD_Iaesenclast,
UD_Iaesimc,
UD_Iaeskeygenassist,
UD_Iand,
UD_Iandnpd,
UD_Iandnps,
UD_Iandpd,
UD_Iandps,
UD_Iarpl,
UD_Iblendpd,
UD_Iblendps,
UD_Iblendvpd,
UD_Iblendvps,
UD_Ibound,
UD_Ibsf,
UD_Ibsr,
UD_Ibswap,
UD_Ibt,
UD_Ibtc,
UD_Ibtr,
UD_Ibts,
UD_Icall,
UD_Icbw,
UD_Icdq,
UD_Icdqe,
UD_Iclc,
UD_Icld,
UD_Iclflush,
UD_Iclgi,
UD_Icli,
UD_Iclts,
UD_Icmc,
UD_Icmova,
UD_Icmovae,
UD_Icmovb,
UD_Icmovbe,
UD_Icmovg,
UD_Icmovge,
UD_Icmovl,
UD_Icmovle,
UD_Icmovno,
UD_Icmovnp,
UD_Icmovns,
UD_Icmovnz,
UD_Icmovo,
UD_Icmovp,
UD_Icmovs,
UD_Icmovz,
UD_Icmp,
UD_Icmppd,
UD_Icmpps,
UD_Icmpsb,
UD_Icmpsd,
UD_Icmpsq,
UD_Icmpss,
UD_Icmpsw,
UD_Icmpxchg,
UD_Icmpxchg16b,
UD_Icmpxchg8b,
UD_Icomisd,
UD_Icomiss,
UD_Icpuid,
UD_Icqo,
UD_Icrc32,
UD_Icvtdq2pd,
UD_Icvtdq2ps,
UD_Icvtpd2dq,
UD_Icvtpd2pi,
UD_Icvtpd2ps,
UD_Icvtpi2pd,
UD_Icvtpi2ps,
UD_Icvtps2dq,
UD_Icvtps2pd,
UD_Icvtps2pi,
UD_Icvtsd2si,
UD_Icvtsd2ss,
UD_Icvtsi2sd,
UD_Icvtsi2ss,
UD_Icvtss2sd,
UD_Icvtss2si,
UD_Icvttpd2dq,
UD_Icvttpd2pi,
UD_Icvttps2dq,
UD_Icvttps2pi,
UD_Icvttsd2si,
UD_Icvttss2si,
UD_Icwd,
UD_Icwde,
UD_Idaa,
UD_Idas,
UD_Idec,
UD_Idiv,
UD_Idivpd,
UD_Idivps,
UD_Idivsd,
UD_Idivss,
UD_Idppd,
UD_Idpps,
UD_Iemms,
UD_Ienter,
UD_Iextractps,
UD_If2xm1,
UD_Ifabs,
UD_Ifadd,
UD_Ifaddp,
UD_Ifbld,
UD_Ifbstp,
UD_Ifchs,
UD_Ifclex,
UD_Ifcmovb,
UD_Ifcmovbe,
UD_Ifcmove,
UD_Ifcmovnb,
UD_Ifcmovnbe,
UD_Ifcmovne,
UD_Ifcmovnu,
UD_Ifcmovu,
UD_Ifcom,
UD_Ifcom2,
UD_Ifcomi,
UD_Ifcomip,
UD_Ifcomp,
UD_Ifcomp3,
UD_Ifcomp5,
UD_Ifcompp,
UD_Ifcos,
UD_Ifdecstp,
UD_Ifdiv,
UD_Ifdivp,
UD_Ifdivr,
UD_Ifdivrp,
UD_Ifemms,
UD_Iffree,
UD_Iffreep,
UD_Ifiadd,
UD_Ificom,
UD_Ificomp,
UD_Ifidiv,
UD_Ifidivr,
UD_Ifild,
UD_Ifimul,
UD_Ifincstp,
UD_Ifist,
UD_Ifistp,
UD_Ifisttp,
UD_Ifisub,
UD_Ifisubr,
UD_Ifld,
UD_Ifld1,
UD_Ifldcw,
UD_Ifldenv,
UD_Ifldl2e,
UD_Ifldl2t,
UD_Ifldlg2,
UD_Ifldln2,
UD_Ifldpi,
UD_Ifldz,
UD_Ifmul,
UD_Ifmulp,
UD_Ifndisi,
UD_Ifneni,
UD_Ifninit,
UD_Ifnop,
UD_Ifnsave,
UD_Ifnsetpm,
UD_Ifnstcw,
UD_Ifnstenv,
UD_Ifnstsw,
UD_Ifpatan,
UD_Ifprem,
UD_Ifprem1,
UD_Ifptan,
UD_Ifrndint,
UD_Ifrstor,
UD_Ifrstpm,
UD_Ifscale,
UD_Ifsin,
UD_Ifsincos,
UD_Ifsqrt,
UD_Ifst,
UD_Ifstp,
UD_Ifstp1,
UD_Ifstp8,
UD_Ifstp9,
UD_Ifsub,
UD_Ifsubp,
UD_Ifsubr,
UD_Ifsubrp,
UD_Iftst,
UD_Ifucom,
UD_Ifucomi,
UD_Ifucomip,
UD_Ifucomp,
UD_Ifucompp,
UD_Ifxam,
UD_Ifxch,
UD_Ifxch4,
UD_Ifxch7,
UD_Ifxrstor,
UD_Ifxsave,
UD_Ifxtract,
UD_Ifyl2x,
UD_Ifyl2xp1,
UD_Igetsec,
UD_Ihaddpd,
UD_Ihaddps,
UD_Ihlt,
UD_Ihsubpd,
UD_Ihsubps,
UD_Iidiv,
UD_Iimul,
UD_Iin,
UD_Iinc,
UD_Iinsb,
UD_Iinsd,
UD_Iinsertps,
UD_Iinsw,
UD_Iint,
UD_Iint1,
UD_Iint3,
UD_Iinto,
UD_Iinvd,
UD_Iinvept,
UD_Iinvlpg,
UD_Iinvlpga,
UD_Iinvvpid,
UD_Iiretd,
UD_Iiretq,
UD_Iiretw,
UD_Ija,
UD_Ijae,
UD_Ijb,
UD_Ijbe,
UD_Ijcxz,
UD_Ijecxz,
UD_Ijg,
UD_Ijge,
UD_Ijl,
UD_Ijle,
UD_Ijmp,
UD_Ijno,
UD_Ijnp,
UD_Ijns,
UD_Ijnz,
UD_Ijo,
UD_Ijp,
UD_Ijrcxz,
UD_Ijs,
UD_Ijz,
UD_Ilahf,
UD_Ilar,
UD_Ilddqu,
UD_Ildmxcsr,
UD_Ilds,
UD_Ilea,
UD_Ileave,
UD_Iles,
UD_Ilfence,
UD_Ilfs,
UD_Ilgdt,
UD_Ilgs,
UD_Ilidt,
UD_Illdt,
UD_Ilmsw,
UD_Ilock,
UD_Ilodsb,
UD_Ilodsd,
UD_Ilodsq,
UD_Ilodsw,
UD_Iloop,
UD_Iloope,
UD_Iloopne,
UD_Ilsl,
UD_Ilss,
UD_Iltr,
UD_Imaskmovdqu,
UD_Imaskmovq,
UD_Imaxpd,
UD_Imaxps,
UD_Imaxsd,
UD_Imaxss,
UD_Imfence,
UD_Iminpd,
UD_Iminps,
UD_Iminsd,
UD_Iminss,
UD_Imonitor,
UD_Imontmul,
UD_Imov,
UD_Imovapd,
UD_Imovaps,
UD_Imovbe,
UD_Imovd,
UD_Imovddup,
UD_Imovdq2q,
UD_Imovdqa,
UD_Imovdqu,
UD_Imovhlps,
UD_Imovhpd,
UD_Imovhps,
UD_Imovlhps,
UD_Imovlpd,
UD_Imovlps,
UD_Imovmskpd,
UD_Imovmskps,
UD_Imovntdq,
UD_Imovntdqa,
UD_Imovnti,
UD_Imovntpd,
UD_Imovntps,
UD_Imovntq,
UD_Imovq,
UD_Imovq2dq,
UD_Imovsb,
UD_Imovsd,
UD_Imovshdup,
UD_Imovsldup,
UD_Imovsq,
UD_Imovss,
UD_Imovsw,
UD_Imovsx,
UD_Imovsxd,
UD_Imovupd,
UD_Imovups,
UD_Imovzx,
UD_Impsadbw,
UD_Imul,
UD_Imulpd,
UD_Imulps,
UD_Imulsd,
UD_Imulss,
UD_Imwait,
UD_Ineg,
UD_Inop,
UD_Inot,
UD_Ior,
UD_Iorpd,
UD_Iorps,
UD_Iout,
UD_Ioutsb,
UD_Ioutsd,
UD_Ioutsw,
UD_Ipabsb,
UD_Ipabsd,
UD_Ipabsw,
UD_Ipackssdw,
UD_Ipacksswb,
UD_Ipackusdw,
UD_Ipackuswb,
UD_Ipaddb,
UD_Ipaddd,
UD_Ipaddq,
UD_Ipaddsb,
UD_Ipaddsw,
UD_Ipaddusb,
UD_Ipaddusw,
UD_Ipaddw,
UD_Ipalignr,
UD_Ipand,
UD_Ipandn,
UD_Ipavgb,
UD_Ipavgusb,
UD_Ipavgw,
UD_Ipblendvb,
UD_Ipblendw,
UD_Ipclmulqdq,
UD_Ipcmpeqb,
UD_Ipcmpeqd,
UD_Ipcmpeqq,
UD_Ipcmpeqw,
UD_Ipcmpestri,
UD_Ipcmpestrm,
UD_Ipcmpgtb,
UD_Ipcmpgtd,
UD_Ipcmpgtq,
UD_Ipcmpgtw,
UD_Ipcmpistri,
UD_Ipcmpistrm,
UD_Ipextrb,
UD_Ipextrd,
UD_Ipextrq,
UD_Ipextrw,
UD_Ipf2id,
UD_Ipf2iw,
UD_Ipfacc,
UD_Ipfadd,
UD_Ipfcmpeq,
UD_Ipfcmpge,
UD_Ipfcmpgt,
UD_Ipfmax,
UD_Ipfmin,
UD_Ipfmul,
UD_Ipfnacc,
UD_Ipfpnacc,
UD_Ipfrcp,
UD_Ipfrcpit1,
UD_Ipfrcpit2,
UD_Ipfrsqit1,
UD_Ipfrsqrt,
UD_Ipfsub,
UD_Ipfsubr,
UD_Iphaddd,
UD_Iphaddsw,
UD_Iphaddw,
UD_Iphminposuw,
UD_Iphsubd,
UD_Iphsubsw,
UD_Iphsubw,
UD_Ipi2fd,
UD_Ipi2fw,
UD_Ipinsrb,
UD_Ipinsrd,
UD_Ipinsrq,
UD_Ipinsrw,
UD_Ipmaddubsw,
UD_Ipmaddwd,
UD_Ipmaxsb,
UD_Ipmaxsd,
UD_Ipmaxsw,
UD_Ipmaxub,
UD_Ipmaxud,
UD_Ipmaxuw,
UD_Ipminsb,
UD_Ipminsd,
UD_Ipminsw,
UD_Ipminub,
UD_Ipminud,
UD_Ipminuw,
UD_Ipmovmskb,
UD_Ipmovsxbd,
UD_Ipmovsxbq,
UD_Ipmovsxbw,
UD_Ipmovsxdq,
UD_Ipmovsxwd,
UD_Ipmovsxwq,
UD_Ipmovzxbd,
UD_Ipmovzxbq,
UD_Ipmovzxbw,
UD_Ipmovzxdq,
UD_Ipmovzxwd,
UD_Ipmovzxwq,
UD_Ipmuldq,
UD_Ipmulhrsw,
UD_Ipmulhrw,
UD_Ipmulhuw,
UD_Ipmulhw,
UD_Ipmulld,
UD_Ipmullw,
UD_Ipmuludq,
UD_Ipop,
UD_Ipopa,
UD_Ipopad,
UD_Ipopcnt,
UD_Ipopfd,
UD_Ipopfq,
UD_Ipopfw,
UD_Ipor,
UD_Iprefetch,
UD_Iprefetchnta,
UD_Iprefetcht0,
UD_Iprefetcht1,
UD_Iprefetcht2,
UD_Ipsadbw,
UD_Ipshufb,
UD_Ipshufd,
UD_Ipshufhw,
UD_Ipshuflw,
UD_Ipshufw,
UD_Ipsignb,
UD_Ipsignd,
UD_Ipsignw,
UD_Ipslld,
UD_Ipslldq,
UD_Ipsllq,
UD_Ipsllw,
UD_Ipsrad,
UD_Ipsraw,
UD_Ipsrld,
UD_Ipsrldq,
UD_Ipsrlq,
UD_Ipsrlw,
UD_Ipsubb,
UD_Ipsubd,
UD_Ipsubq,
UD_Ipsubsb,
UD_Ipsubsw,
UD_Ipsubusb,
UD_Ipsubusw,
UD_Ipsubw,
UD_Ipswapd,
UD_Iptest,
UD_Ipunpckhbw,
UD_Ipunpckhdq,
UD_Ipunpckhqdq,
UD_Ipunpckhwd,
UD_Ipunpcklbw,
UD_Ipunpckldq,
UD_Ipunpcklqdq,
UD_Ipunpcklwd,
UD_Ipush,
UD_Ipusha,
UD_Ipushad,
UD_Ipushfd,
UD_Ipushfq,
UD_Ipushfw,
UD_Ipxor,
UD_Ircl,
UD_Ircpps,
UD_Ircpss,
UD_Ircr,
UD_Irdmsr,
UD_Irdpmc,
UD_Irdrand,
UD_Irdtsc,
UD_Irdtscp,
UD_Irep,
UD_Irepne,
UD_Iret,
UD_Iretf,
UD_Irol,
UD_Iror,
UD_Iroundpd,
UD_Iroundps,
UD_Iroundsd,
UD_Iroundss,
UD_Irsm,
UD_Irsqrtps,
UD_Irsqrtss,
UD_Isahf,
UD_Isalc,
UD_Isar,
UD_Isbb,
UD_Iscasb,
UD_Iscasd,
UD_Iscasq,
UD_Iscasw,
UD_Iseta,
UD_Isetae,
UD_Isetb,
UD_Isetbe,
UD_Isetg,
UD_Isetge,
UD_Isetl,
UD_Isetle,
UD_Isetno,
UD_Isetnp,
UD_Isetns,
UD_Isetnz,
UD_Iseto,
UD_Isetp,
UD_Isets,
UD_Isetz,
UD_Isfence,
UD_Isgdt,
UD_Ishl,
UD_Ishld,
UD_Ishr,
UD_Ishrd,
UD_Ishufpd,
UD_Ishufps,
UD_Isidt,
UD_Iskinit,
UD_Isldt,
UD_Ismsw,
UD_Isqrtpd,
UD_Isqrtps,
UD_Isqrtsd,
UD_Isqrtss,
UD_Istc,
UD_Istd,
UD_Istgi,
UD_Isti,
UD_Istmxcsr,
UD_Istosb,
UD_Istosd,
UD_Istosq,
UD_Istosw,
UD_Istr,
UD_Isub,
UD_Isubpd,
UD_Isubps,
UD_Isubsd,
UD_Isubss,
UD_Iswapgs,
UD_Isyscall,
UD_Isysenter,
UD_Isysexit,
UD_Isysret,
UD_Itest,
UD_Iucomisd,
UD_Iucomiss,
UD_Iud2,
UD_Iunpckhpd,
UD_Iunpckhps,
UD_Iunpcklpd,
UD_Iunpcklps,
UD_Ivaddpd,
UD_Ivaddps,
UD_Ivaddsd,
UD_Ivaddss,
UD_Ivaddsubpd,
UD_Ivaddsubps,
UD_Ivaesdec,
UD_Ivaesdeclast,
UD_Ivaesenc,
UD_Ivaesenclast,
UD_Ivaesimc,
UD_Ivaeskeygenassist,
UD_Ivandnpd,
UD_Ivandnps,
UD_Ivandpd,
UD_Ivandps,
UD_Ivblendpd,
UD_Ivblendps,
UD_Ivblendvpd,
UD_Ivblendvps,
UD_Ivbroadcastsd,
UD_Ivbroadcastss,
UD_Ivcmppd,
UD_Ivcmpps,
UD_Ivcmpsd,
UD_Ivcmpss,
UD_Ivcomisd,
UD_Ivcomiss,
UD_Ivcvtdq2pd,
UD_Ivcvtdq2ps,
UD_Ivcvtpd2dq,
UD_Ivcvtpd2ps,
UD_Ivcvtps2dq,
UD_Ivcvtps2pd,
UD_Ivcvtsd2si,
UD_Ivcvtsd2ss,
UD_Ivcvtsi2sd,
UD_Ivcvtsi2ss,
UD_Ivcvtss2sd,
UD_Ivcvtss2si,
UD_Ivcvttpd2dq,
UD_Ivcvttps2dq,
UD_Ivcvttsd2si,
UD_Ivcvttss2si,
UD_Ivdivpd,
UD_Ivdivps,
UD_Ivdivsd,
UD_Ivdivss,
UD_Ivdppd,
UD_Ivdpps,
UD_Iverr,
UD_Iverw,
UD_Ivextractf128,
UD_Ivextractps,
UD_Ivhaddpd,
UD_Ivhaddps,
UD_Ivhsubpd,
UD_Ivhsubps,
UD_Ivinsertf128,
UD_Ivinsertps,
UD_Ivlddqu,
UD_Ivmaskmovdqu,
UD_Ivmaskmovpd,
UD_Ivmaskmovps,
UD_Ivmaxpd,
UD_Ivmaxps,
UD_Ivmaxsd,
UD_Ivmaxss,
UD_Ivmcall,
UD_Ivmclear,
UD_Ivminpd,
UD_Ivminps,
UD_Ivminsd,
UD_Ivminss,
UD_Ivmlaunch,
UD_Ivmload,
UD_Ivmmcall,
UD_Ivmovapd,
UD_Ivmovaps,
UD_Ivmovd,
UD_Ivmovddup,
UD_Ivmovdqa,
UD_Ivmovdqu,
UD_Ivmovhlps,
UD_Ivmovhpd,
UD_Ivmovhps,
UD_Ivmovlhps,
UD_Ivmovlpd,
UD_Ivmovlps,
UD_Ivmovmskpd,
UD_Ivmovmskps,
UD_Ivmovntdq,
UD_Ivmovntdqa,
UD_Ivmovntpd,
UD_Ivmovntps,
UD_Ivmovq,
UD_Ivmovsd,
UD_Ivmovshdup,
UD_Ivmovsldup,
UD_Ivmovss,
UD_Ivmovupd,
UD_Ivmovups,
UD_Ivmpsadbw,
UD_Ivmptrld,
UD_Ivmptrst,
UD_Ivmread,
UD_Ivmresume,
UD_Ivmrun,
UD_Ivmsave,
UD_Ivmulpd,
UD_Ivmulps,
UD_Ivmulsd,
UD_Ivmulss,
UD_Ivmwrite,
UD_Ivmxoff,
UD_Ivmxon,
UD_Ivorpd,
UD_Ivorps,
UD_Ivpabsb,
UD_Ivpabsd,
UD_Ivpabsw,
UD_Ivpackssdw,
UD_Ivpacksswb,
UD_Ivpackusdw,
UD_Ivpackuswb,
UD_Ivpaddb,
UD_Ivpaddd,
UD_Ivpaddq,
UD_Ivpaddsb,
UD_Ivpaddsw,
UD_Ivpaddusb,
UD_Ivpaddusw,
UD_Ivpaddw,
UD_Ivpalignr,
UD_Ivpand,
UD_Ivpandn,
UD_Ivpavgb,
UD_Ivpavgw,
UD_Ivpblendvb,
UD_Ivpblendw,
UD_Ivpclmulqdq,
UD_Ivpcmpeqb,
UD_Ivpcmpeqd,
UD_Ivpcmpeqq,
UD_Ivpcmpeqw,
UD_Ivpcmpestri,
UD_Ivpcmpestrm,
UD_Ivpcmpgtb,
UD_Ivpcmpgtd,
UD_Ivpcmpgtq,
UD_Ivpcmpgtw,
UD_Ivpcmpistri,
UD_Ivpcmpistrm,
UD_Ivperm2f128,
UD_Ivpermilpd,
UD_Ivpermilps,
UD_Ivpextrb,
UD_Ivpextrd,
UD_Ivpextrq,
UD_Ivpextrw,
UD_Ivphaddd,
UD_Ivphaddsw,
UD_Ivphaddw,
UD_Ivphminposuw,
UD_Ivphsubd,
UD_Ivphsubsw,
UD_Ivphsubw,
UD_Ivpinsrb,
UD_Ivpinsrd,
UD_Ivpinsrq,
UD_Ivpinsrw,
UD_Ivpmaddubsw,
UD_Ivpmaddwd,
UD_Ivpmaxsb,
UD_Ivpmaxsd,
UD_Ivpmaxsw,
UD_Ivpmaxub,
UD_Ivpmaxud,
UD_Ivpmaxuw,
UD_Ivpminsb,
UD_Ivpminsd,
UD_Ivpminsw,
UD_Ivpminub,
UD_Ivpminud,
UD_Ivpminuw,
UD_Ivpmovmskb,
UD_Ivpmovsxbd,
UD_Ivpmovsxbq,
UD_Ivpmovsxbw,
UD_Ivpmovsxwd,
UD_Ivpmovsxwq,
UD_Ivpmovzxbd,
UD_Ivpmovzxbq,
UD_Ivpmovzxbw,
UD_Ivpmovzxdq,
UD_Ivpmovzxwd,
UD_Ivpmovzxwq,
UD_Ivpmuldq,
UD_Ivpmulhrsw,
UD_Ivpmulhuw,
UD_Ivpmulhw,
UD_Ivpmulld,
UD_Ivpmullw,
UD_Ivpor,
UD_Ivpsadbw,
UD_Ivpshufb,
UD_Ivpshufd,
UD_Ivpshufhw,
UD_Ivpshuflw,
UD_Ivpsignb,
UD_Ivpsignd,
UD_Ivpsignw,
UD_Ivpslld,
UD_Ivpslldq,
UD_Ivpsllq,
UD_Ivpsllw,
UD_Ivpsrad,
UD_Ivpsraw,
UD_Ivpsrld,
UD_Ivpsrldq,
UD_Ivpsrlq,
UD_Ivpsrlw,
UD_Ivpsubb,
UD_Ivpsubd,
UD_Ivpsubq,
UD_Ivpsubsb,
UD_Ivpsubsw,
UD_Ivpsubusb,
UD_Ivpsubusw,
UD_Ivpsubw,
UD_Ivptest,
UD_Ivpunpckhbw,
UD_Ivpunpckhdq,
UD_Ivpunpckhqdq,
UD_Ivpunpckhwd,
UD_Ivpunpcklbw,
UD_Ivpunpckldq,
UD_Ivpunpcklqdq,
UD_Ivpunpcklwd,
UD_Ivpxor,
UD_Ivrcpps,
UD_Ivrcpss,
UD_Ivroundpd,
UD_Ivroundps,
UD_Ivroundsd,
UD_Ivroundss,
UD_Ivrsqrtps,
UD_Ivrsqrtss,
UD_Ivshufpd,
UD_Ivshufps,
UD_Ivsqrtpd,
UD_Ivsqrtps,
UD_Ivsqrtsd,
UD_Ivsqrtss,
UD_Ivstmxcsr,
UD_Ivsubpd,
UD_Ivsubps,
UD_Ivsubsd,
UD_Ivsubss,
UD_Ivtestpd,
UD_Ivtestps,
UD_Ivucomisd,
UD_Ivucomiss,
UD_Ivunpckhpd,
UD_Ivunpckhps,
UD_Ivunpcklpd,
UD_Ivunpcklps,
UD_Ivxorpd,
UD_Ivxorps,
UD_Ivzeroall,
UD_Ivzeroupper,
UD_Iwait,
UD_Iwbinvd,
UD_Iwrmsr,
UD_Ixadd,
UD_Ixchg,
UD_Ixcryptcbc,
UD_Ixcryptcfb,
UD_Ixcryptctr,
UD_Ixcryptecb,
UD_Ixcryptofb,
UD_Ixgetbv,
UD_Ixlatb,
UD_Ixor,
UD_Ixorpd,
UD_Ixorps,
UD_Ixrstor,
UD_Ixsave,
UD_Ixsetbv,
UD_Ixsha1,
UD_Ixsha256,
UD_Ixstore,
UD_Iinvalid,
UD_I3dnow,
UD_Inone,
UD_Idb,
UD_Ipause,
UD_MAX_MNEMONIC_CODE
};
extern const char * ud_mnemonics_str[];
#endif /* UD_ITAB_H */

View file

@ -1,228 +0,0 @@
/* udis86 - libudis86/syn-att.c
*
* Copyright (c) 2002-2009 Vivek Thampi
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "types.h"
#include "extern.h"
#include "decode.h"
#include "itab.h"
#include "syn.h"
#include "udint.h"
/* -----------------------------------------------------------------------------
* opr_cast() - Prints an operand cast.
* -----------------------------------------------------------------------------
*/
static void
opr_cast(struct ud* u, struct ud_operand* op)
{
switch(op->size) {
case 16 : case 32 :
ud_asmprintf(u, "*"); break;
default: break;
}
}
/* -----------------------------------------------------------------------------
* gen_operand() - Generates assembly output for each operand.
* -----------------------------------------------------------------------------
*/
static void
gen_operand(struct ud* u, struct ud_operand* op)
{
switch(op->type) {
case UD_OP_CONST:
ud_asmprintf(u, "$0x%x", op->lval.udword);
break;
case UD_OP_REG:
ud_asmprintf(u, "%%%s", ud_reg_tab[op->base - UD_R_AL]);
break;
case UD_OP_MEM:
if (u->br_far) {
opr_cast(u, op);
}
if (u->pfx_seg) {
ud_asmprintf(u, "%%%s:", ud_reg_tab[u->pfx_seg - UD_R_AL]);
}
if (op->offset != 0) {
ud_syn_print_mem_disp(u, op, 0);
}
if (op->base) {
ud_asmprintf(u, "(%%%s", ud_reg_tab[op->base - UD_R_AL]);
}
if (op->index) {
if (op->base) {
ud_asmprintf(u, ",");
} else {
ud_asmprintf(u, "(");
}
ud_asmprintf(u, "%%%s", ud_reg_tab[op->index - UD_R_AL]);
}
if (op->scale) {
ud_asmprintf(u, ",%d", op->scale);
}
if (op->base || op->index) {
ud_asmprintf(u, ")");
}
break;
case UD_OP_IMM:
ud_asmprintf(u, "$");
ud_syn_print_imm(u, op);
break;
case UD_OP_JIMM:
ud_syn_print_addr(u, ud_syn_rel_target(u, op));
break;
case UD_OP_PTR:
switch (op->size) {
case 32:
ud_asmprintf(u, "$0x%x, $0x%x", op->lval.ptr.seg,
op->lval.ptr.off & 0xFFFF);
break;
case 48:
ud_asmprintf(u, "$0x%x, $0x%x", op->lval.ptr.seg,
op->lval.ptr.off);
break;
}
break;
default: return;
}
}
/* =============================================================================
* translates to AT&T syntax
* =============================================================================
*/
extern void
ud_translate_att(struct ud *u)
{
int size = 0;
int star = 0;
/* check if P_OSO prefix is used */
if (! P_OSO(u->itab_entry->prefix) && u->pfx_opr) {
switch (u->dis_mode) {
case 16:
ud_asmprintf(u, "o32 ");
break;
case 32:
case 64:
ud_asmprintf(u, "o16 ");
break;
}
}
/* check if P_ASO prefix was used */
if (! P_ASO(u->itab_entry->prefix) && u->pfx_adr) {
switch (u->dis_mode) {
case 16:
ud_asmprintf(u, "a32 ");
break;
case 32:
ud_asmprintf(u, "a16 ");
break;
case 64:
ud_asmprintf(u, "a32 ");
break;
}
}
if (u->pfx_lock)
ud_asmprintf(u, "lock ");
if (u->pfx_rep) {
ud_asmprintf(u, "rep ");
} else if (u->pfx_repe) {
ud_asmprintf(u, "repe ");
} else if (u->pfx_repne) {
ud_asmprintf(u, "repne ");
}
/* special instructions */
switch (u->mnemonic) {
case UD_Iretf:
ud_asmprintf(u, "lret ");
break;
case UD_Idb:
ud_asmprintf(u, ".byte 0x%x", u->operand[0].lval.ubyte);
return;
case UD_Ijmp:
case UD_Icall:
if (u->br_far) ud_asmprintf(u, "l");
if (u->operand[0].type == UD_OP_REG) {
star = 1;
}
ud_asmprintf(u, "%s", ud_lookup_mnemonic(u->mnemonic));
break;
case UD_Ibound:
case UD_Ienter:
if (u->operand[0].type != UD_NONE)
gen_operand(u, &u->operand[0]);
if (u->operand[1].type != UD_NONE) {
ud_asmprintf(u, ",");
gen_operand(u, &u->operand[1]);
}
return;
default:
ud_asmprintf(u, "%s", ud_lookup_mnemonic(u->mnemonic));
}
if (size == 8) {
ud_asmprintf(u, "b");
} else if (size == 16) {
ud_asmprintf(u, "w");
} else if (size == 64) {
ud_asmprintf(u, "q");
}
if (star) {
ud_asmprintf(u, " *");
} else {
ud_asmprintf(u, " ");
}
if (u->operand[3].type != UD_NONE) {
gen_operand(u, &u->operand[3]);
ud_asmprintf(u, ", ");
}
if (u->operand[2].type != UD_NONE) {
gen_operand(u, &u->operand[2]);
ud_asmprintf(u, ", ");
}
if (u->operand[1].type != UD_NONE) {
gen_operand(u, &u->operand[1]);
ud_asmprintf(u, ", ");
}
if (u->operand[0].type != UD_NONE) {
gen_operand(u, &u->operand[0]);
}
}
/*
vim: set ts=2 sw=2 expandtab
*/

View file

@ -1,224 +0,0 @@
/* udis86 - libudis86/syn-intel.c
*
* Copyright (c) 2002-2013 Vivek Thampi
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "types.h"
#include "extern.h"
#include "decode.h"
#include "itab.h"
#include "syn.h"
#include "udint.h"
/* -----------------------------------------------------------------------------
* opr_cast() - Prints an operand cast.
* -----------------------------------------------------------------------------
*/
static void
opr_cast(struct ud* u, struct ud_operand* op)
{
if (u->br_far) {
ud_asmprintf(u, "far ");
}
switch(op->size) {
case 8: ud_asmprintf(u, "byte " ); break;
case 16: ud_asmprintf(u, "word " ); break;
case 32: ud_asmprintf(u, "dword "); break;
case 64: ud_asmprintf(u, "qword "); break;
case 80: ud_asmprintf(u, "tword "); break;
case 128: ud_asmprintf(u, "oword "); break;
case 256: ud_asmprintf(u, "yword "); break;
default: break;
}
}
/* -----------------------------------------------------------------------------
* gen_operand() - Generates assembly output for each operand.
* -----------------------------------------------------------------------------
*/
static void gen_operand(struct ud* u, struct ud_operand* op, int syn_cast)
{
switch(op->type) {
case UD_OP_REG:
ud_asmprintf(u, "%s", ud_reg_tab[op->base - UD_R_AL]);
break;
case UD_OP_MEM:
if (syn_cast) {
opr_cast(u, op);
}
ud_asmprintf(u, "[");
if (u->pfx_seg) {
ud_asmprintf(u, "%s:", ud_reg_tab[u->pfx_seg - UD_R_AL]);
}
if (op->base) {
ud_asmprintf(u, "%s", ud_reg_tab[op->base - UD_R_AL]);
}
if (op->index) {
ud_asmprintf(u, "%s%s", op->base != UD_NONE? "+" : "",
ud_reg_tab[op->index - UD_R_AL]);
if (op->scale) {
ud_asmprintf(u, "*%d", op->scale);
}
}
if (op->offset != 0) {
ud_syn_print_mem_disp(u, op, (op->base != UD_NONE ||
op->index != UD_NONE) ? 1 : 0);
}
ud_asmprintf(u, "]");
break;
case UD_OP_IMM:
ud_syn_print_imm(u, op);
break;
case UD_OP_JIMM:
ud_syn_print_addr(u, ud_syn_rel_target(u, op));
break;
case UD_OP_PTR:
switch (op->size) {
case 32:
ud_asmprintf(u, "word 0x%x:0x%x", op->lval.ptr.seg,
op->lval.ptr.off & 0xFFFF);
break;
case 48:
ud_asmprintf(u, "dword 0x%x:0x%x", op->lval.ptr.seg,
op->lval.ptr.off);
break;
}
break;
case UD_OP_CONST:
if (syn_cast) opr_cast(u, op);
ud_asmprintf(u, "%d", op->lval.udword);
break;
default: return;
}
}
/* =============================================================================
* translates to intel syntax
* =============================================================================
*/
extern void
ud_translate_intel(struct ud* u)
{
/* check if P_OSO prefix is used */
if (!P_OSO(u->itab_entry->prefix) && u->pfx_opr) {
switch (u->dis_mode) {
case 16: ud_asmprintf(u, "o32 "); break;
case 32:
case 64: ud_asmprintf(u, "o16 "); break;
}
}
/* check if P_ASO prefix was used */
if (!P_ASO(u->itab_entry->prefix) && u->pfx_adr) {
switch (u->dis_mode) {
case 16: ud_asmprintf(u, "a32 "); break;
case 32: ud_asmprintf(u, "a16 "); break;
case 64: ud_asmprintf(u, "a32 "); break;
}
}
if (u->pfx_seg &&
u->operand[0].type != UD_OP_MEM &&
u->operand[1].type != UD_OP_MEM ) {
ud_asmprintf(u, "%s ", ud_reg_tab[u->pfx_seg - UD_R_AL]);
}
if (u->pfx_lock) {
ud_asmprintf(u, "lock ");
}
if (u->pfx_rep) {
ud_asmprintf(u, "rep ");
} else if (u->pfx_repe) {
ud_asmprintf(u, "repe ");
} else if (u->pfx_repne) {
ud_asmprintf(u, "repne ");
}
/* print the instruction mnemonic */
ud_asmprintf(u, "%s", ud_lookup_mnemonic(u->mnemonic));
if (u->operand[0].type != UD_NONE) {
int cast = 0;
ud_asmprintf(u, " ");
if (u->operand[0].type == UD_OP_MEM) {
if (u->operand[1].type == UD_OP_IMM ||
u->operand[1].type == UD_OP_CONST ||
u->operand[1].type == UD_NONE ||
(u->operand[0].size != u->operand[1].size)) {
cast = 1;
} else if (u->operand[1].type == UD_OP_REG &&
u->operand[1].base == UD_R_CL) {
switch (u->mnemonic) {
case UD_Ircl:
case UD_Irol:
case UD_Iror:
case UD_Ircr:
case UD_Ishl:
case UD_Ishr:
case UD_Isar:
cast = 1;
break;
default: break;
}
}
}
gen_operand(u, &u->operand[0], cast);
}
if (u->operand[1].type != UD_NONE) {
int cast = 0;
ud_asmprintf(u, ", ");
if (u->operand[1].type == UD_OP_MEM &&
u->operand[0].size != u->operand[1].size &&
!ud_opr_is_sreg(&u->operand[0])) {
cast = 1;
}
gen_operand(u, &u->operand[1], cast);
}
if (u->operand[2].type != UD_NONE) {
int cast = 0;
ud_asmprintf(u, ", ");
if (u->operand[2].type == UD_OP_MEM &&
u->operand[2].size != u->operand[1].size) {
cast = 1;
}
gen_operand(u, &u->operand[2], cast);
}
if (u->operand[3].type != UD_NONE) {
ud_asmprintf(u, ", ");
gen_operand(u, &u->operand[3], 0);
}
}
/*
vim: set ts=2 sw=2 expandtab
*/

View file

@ -1,258 +0,0 @@
/* udis86 - libudis86/syn.c
*
* Copyright (c) 2002-2013 Vivek Thampi
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "types.h"
#include "decode.h"
#include "syn.h"
#include "udint.h"
/*
* Register Table - Order Matters (types.h)!
*
*/
const char* ud_reg_tab[] =
{
"al", "cl", "dl", "bl",
"ah", "ch", "dh", "bh",
"spl", "bpl", "sil", "dil",
"r8b", "r9b", "r10b", "r11b",
"r12b", "r13b", "r14b", "r15b",
"ax", "cx", "dx", "bx",
"sp", "bp", "si", "di",
"r8w", "r9w", "r10w", "r11w",
"r12w", "r13w", "r14w", "r15w",
"eax", "ecx", "edx", "ebx",
"esp", "ebp", "esi", "edi",
"r8d", "r9d", "r10d", "r11d",
"r12d", "r13d", "r14d", "r15d",
"rax", "rcx", "rdx", "rbx",
"rsp", "rbp", "rsi", "rdi",
"r8", "r9", "r10", "r11",
"r12", "r13", "r14", "r15",
"es", "cs", "ss", "ds",
"fs", "gs",
"cr0", "cr1", "cr2", "cr3",
"cr4", "cr5", "cr6", "cr7",
"cr8", "cr9", "cr10", "cr11",
"cr12", "cr13", "cr14", "cr15",
"dr0", "dr1", "dr2", "dr3",
"dr4", "dr5", "dr6", "dr7",
"dr8", "dr9", "dr10", "dr11",
"dr12", "dr13", "dr14", "dr15",
"mm0", "mm1", "mm2", "mm3",
"mm4", "mm5", "mm6", "mm7",
"st0", "st1", "st2", "st3",
"st4", "st5", "st6", "st7",
"xmm0", "xmm1", "xmm2", "xmm3",
"xmm4", "xmm5", "xmm6", "xmm7",
"xmm8", "xmm9", "xmm10", "xmm11",
"xmm12", "xmm13", "xmm14", "xmm15",
"ymm0", "ymm1", "ymm2", "ymm3",
"ymm4", "ymm5", "ymm6", "ymm7",
"ymm8", "ymm9", "ymm10", "ymm11",
"ymm12", "ymm13", "ymm14", "ymm15",
"rip"
};
uint64_t
ud_syn_rel_target(struct ud *u, struct ud_operand *opr)
{
#if 1
const uint64_t trunc_mask = 0xffffffffffffffffull >> (64 - u->adr_mode);
#else
const uint64_t trunc_mask = 0xffffffffffffffffull >> (64 - u->opr_mode);
#endif
switch (opr->size) {
case 8 : return (u->pc + opr->lval.sbyte) & trunc_mask;
case 16: return (u->pc + opr->lval.sword) & trunc_mask;
case 32: return (u->pc + opr->lval.sdword) & trunc_mask;
default: UD_ASSERT(!"invalid relative offset size.");
return 0ull;
}
}
/*
* asmprintf
* Printf style function for printing translated assembly
* output. Returns the number of characters written and
* moves the buffer pointer forward. On an overflow,
* returns a negative number and truncates the output.
*/
int
ud_asmprintf(struct ud *u, const char *fmt, ...)
{
int ret;
int avail;
va_list ap;
va_start(ap, fmt);
avail = u->asm_buf_size - u->asm_buf_fill - 1 /* nullchar */;
ret = vsnprintf((char*) u->asm_buf + u->asm_buf_fill, avail, fmt, ap);
if (ret < 0 || ret > avail) {
u->asm_buf_fill = u->asm_buf_size - 1;
} else {
u->asm_buf_fill += ret;
}
va_end(ap);
return ret;
}
void
ud_syn_print_addr(struct ud *u, uint64_t addr)
{
const char *name = NULL;
if (u->sym_resolver) {
int64_t offset = 0;
name = u->sym_resolver(u, addr, &offset);
if (name) {
if (offset) {
ud_asmprintf(u, "%s%+" FMT64 "d", name, offset);
} else {
ud_asmprintf(u, "%s", name);
}
return;
}
}
ud_asmprintf(u, "0x%" FMT64 "x", addr);
}
void
ud_syn_print_imm(struct ud* u, const struct ud_operand *op)
{
uint64_t v;
if (op->_oprcode == OP_sI && op->size != u->opr_mode) {
if (op->size == 8) {
v = (int64_t)op->lval.sbyte;
} else {
UD_ASSERT(op->size == 32);
v = (int64_t)op->lval.sdword;
}
if (u->opr_mode < 64) {
v = v & ((1ull << u->opr_mode) - 1ull);
}
} else {
switch (op->size) {
case 8 : v = op->lval.ubyte; break;
case 16: v = op->lval.uword; break;
case 32: v = op->lval.udword; break;
case 64: v = op->lval.uqword; break;
default: UD_ASSERT(!"invalid offset"); v = 0; /* keep cc happy */
}
}
#if 1
if (u->sym_resolver) {
int64_t offset = 0;
const char *name = u->sym_resolver(u, v, &offset);
if (name) {
if (offset) {
ud_asmprintf(u, "%s%+" FMT64 "d", name, offset);
} else {
ud_asmprintf(u, "%s", name);
}
return;
}
}
#endif
ud_asmprintf(u, "0x%" FMT64 "x", v);
}
void
ud_syn_print_mem_disp(struct ud* u, const struct ud_operand *op, int sign)
{
UD_ASSERT(op->offset != 0);
if (op->base == UD_NONE && op->index == UD_NONE) {
uint64_t v;
UD_ASSERT(op->scale == UD_NONE && op->offset != 8);
/* unsigned mem-offset */
switch (op->offset) {
case 16: v = op->lval.uword; break;
case 32: v = op->lval.udword; break;
case 64: v = op->lval.uqword; break;
default: UD_ASSERT(!"invalid offset"); v = 0; /* keep cc happy */
}
#if 1
if (u->sym_resolver) {
int64_t offset = 0;
const char *name = u->sym_resolver(u, v, &offset);
if (name) {
if (offset) {
ud_asmprintf(u, "%s%+" FMT64 "d", name, offset);
} else {
ud_asmprintf(u, "%s", name);
}
return;
}
}
#endif
ud_asmprintf(u, "0x%" FMT64 "x", v);
} else {
int64_t v;
UD_ASSERT(op->offset != 64);
switch (op->offset) {
case 8 : v = op->lval.sbyte; break;
case 16: v = op->lval.sword; break;
case 32: v = op->lval.sdword; break;
default: UD_ASSERT(!"invalid offset"); v = 0; /* keep cc happy */
}
#if 1
if (u->sym_resolver) {
int64_t offset = 0;
const char *name = u->sym_resolver(u, v, &offset);
if (name) {
if (offset) {
ud_asmprintf(u, "%s%+" FMT64 "d", name, offset);
} else {
ud_asmprintf(u, "%s", name);
}
return;
}
}
#endif
if (v < 0) {
ud_asmprintf(u, "-0x%" FMT64 "x", -v);
} else if (v > 0) {
ud_asmprintf(u, "%s0x%" FMT64 "x", sign? "+" : "", v);
}
}
}
/*
vim: set ts=2 sw=2 expandtab
*/

View file

@ -1,53 +0,0 @@
/* udis86 - libudis86/syn.h
*
* Copyright (c) 2002-2009
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef UD_SYN_H
#define UD_SYN_H
#include "types.h"
#ifndef __UD_STANDALONE__
# include <stdarg.h>
#endif /* __UD_STANDALONE__ */
extern const char* ud_reg_tab[];
uint64_t ud_syn_rel_target(struct ud*, struct ud_operand*);
#ifdef __GNUC__
int ud_asmprintf(struct ud *u, const char *fmt, ...)
__attribute__ ((format (printf, 2, 3)));
#else
int ud_asmprintf(struct ud *u, const char *fmt, ...);
#endif
void ud_syn_print_addr(struct ud *u, uint64_t addr);
void ud_syn_print_imm(struct ud* u, const struct ud_operand *op);
void ud_syn_print_mem_disp(struct ud* u, const struct ud_operand *, int sign);
#endif /* UD_SYN_H */
/*
vim: set ts=2 sw=2 expandtab
*/

View file

@ -1,260 +0,0 @@
/* udis86 - libudis86/types.h
*
* Copyright (c) 2002-2013 Vivek Thampi
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef UD_TYPES_H
#define UD_TYPES_H
#ifdef __KERNEL__
/*
* -D__KERNEL__ is automatically passed on the command line when
* building something as part of the Linux kernel. Assume standalone
* mode.
*/
# include <linux/kernel.h>
# include <linux/string.h>
# ifndef __UD_STANDALONE__
# define __UD_STANDALONE__ 1
# endif
#endif /* __KERNEL__ */
#if !defined(__UD_STANDALONE__)
# include <stdint.h>
# include <stdio.h>
#endif
/* gcc specific extensions */
#ifdef __GNUC__
# define UD_ATTR_PACKED __attribute__((packed))
#else
# define UD_ATTR_PACKED
#endif /* UD_ATTR_PACKED */
/* -----------------------------------------------------------------------------
* All possible "types" of objects in udis86. Order is Important!
* -----------------------------------------------------------------------------
*/
enum ud_type
{
UD_NONE,
/* 8 bit GPRs */
UD_R_AL, UD_R_CL, UD_R_DL, UD_R_BL,
UD_R_AH, UD_R_CH, UD_R_DH, UD_R_BH,
UD_R_SPL, UD_R_BPL, UD_R_SIL, UD_R_DIL,
UD_R_R8B, UD_R_R9B, UD_R_R10B, UD_R_R11B,
UD_R_R12B, UD_R_R13B, UD_R_R14B, UD_R_R15B,
/* 16 bit GPRs */
UD_R_AX, UD_R_CX, UD_R_DX, UD_R_BX,
UD_R_SP, UD_R_BP, UD_R_SI, UD_R_DI,
UD_R_R8W, UD_R_R9W, UD_R_R10W, UD_R_R11W,
UD_R_R12W, UD_R_R13W, UD_R_R14W, UD_R_R15W,
/* 32 bit GPRs */
UD_R_EAX, UD_R_ECX, UD_R_EDX, UD_R_EBX,
UD_R_ESP, UD_R_EBP, UD_R_ESI, UD_R_EDI,
UD_R_R8D, UD_R_R9D, UD_R_R10D, UD_R_R11D,
UD_R_R12D, UD_R_R13D, UD_R_R14D, UD_R_R15D,
/* 64 bit GPRs */
UD_R_RAX, UD_R_RCX, UD_R_RDX, UD_R_RBX,
UD_R_RSP, UD_R_RBP, UD_R_RSI, UD_R_RDI,
UD_R_R8, UD_R_R9, UD_R_R10, UD_R_R11,
UD_R_R12, UD_R_R13, UD_R_R14, UD_R_R15,
/* segment registers */
UD_R_ES, UD_R_CS, UD_R_SS, UD_R_DS,
UD_R_FS, UD_R_GS,
/* control registers*/
UD_R_CR0, UD_R_CR1, UD_R_CR2, UD_R_CR3,
UD_R_CR4, UD_R_CR5, UD_R_CR6, UD_R_CR7,
UD_R_CR8, UD_R_CR9, UD_R_CR10, UD_R_CR11,
UD_R_CR12, UD_R_CR13, UD_R_CR14, UD_R_CR15,
/* debug registers */
UD_R_DR0, UD_R_DR1, UD_R_DR2, UD_R_DR3,
UD_R_DR4, UD_R_DR5, UD_R_DR6, UD_R_DR7,
UD_R_DR8, UD_R_DR9, UD_R_DR10, UD_R_DR11,
UD_R_DR12, UD_R_DR13, UD_R_DR14, UD_R_DR15,
/* mmx registers */
UD_R_MM0, UD_R_MM1, UD_R_MM2, UD_R_MM3,
UD_R_MM4, UD_R_MM5, UD_R_MM6, UD_R_MM7,
/* x87 registers */
UD_R_ST0, UD_R_ST1, UD_R_ST2, UD_R_ST3,
UD_R_ST4, UD_R_ST5, UD_R_ST6, UD_R_ST7,
/* extended multimedia registers */
UD_R_XMM0, UD_R_XMM1, UD_R_XMM2, UD_R_XMM3,
UD_R_XMM4, UD_R_XMM5, UD_R_XMM6, UD_R_XMM7,
UD_R_XMM8, UD_R_XMM9, UD_R_XMM10, UD_R_XMM11,
UD_R_XMM12, UD_R_XMM13, UD_R_XMM14, UD_R_XMM15,
/* 256B multimedia registers */
UD_R_YMM0, UD_R_YMM1, UD_R_YMM2, UD_R_YMM3,
UD_R_YMM4, UD_R_YMM5, UD_R_YMM6, UD_R_YMM7,
UD_R_YMM8, UD_R_YMM9, UD_R_YMM10, UD_R_YMM11,
UD_R_YMM12, UD_R_YMM13, UD_R_YMM14, UD_R_YMM15,
UD_R_RIP,
/* Operand Types */
UD_OP_REG, UD_OP_MEM, UD_OP_PTR, UD_OP_IMM,
UD_OP_JIMM, UD_OP_CONST
};
#include "itab.h"
union ud_lval {
int8_t sbyte;
uint8_t ubyte;
int16_t sword;
uint16_t uword;
int32_t sdword;
uint32_t udword;
int64_t sqword;
uint64_t uqword;
struct {
uint16_t seg;
uint32_t off;
} ptr;
};
/* -----------------------------------------------------------------------------
* struct ud_operand - Disassembled instruction Operand.
* -----------------------------------------------------------------------------
*/
struct ud_operand {
enum ud_type type;
uint16_t size;
enum ud_type base;
enum ud_type index;
uint8_t scale;
uint8_t offset;
union ud_lval lval;
/*
* internal use only
*/
uint64_t _legacy; /* this will be removed in 1.8 */
uint8_t _oprcode;
};
/* -----------------------------------------------------------------------------
* struct ud - The udis86 object.
* -----------------------------------------------------------------------------
*/
struct ud
{
/*
* input buffering
*/
int (*inp_hook) (struct ud*);
#ifndef __UD_STANDALONE__
FILE* inp_file;
#endif
const uint8_t* inp_buf;
size_t inp_buf_size;
size_t inp_buf_index;
uint8_t inp_curr;
size_t inp_ctr;
uint8_t inp_sess[64];
int inp_end;
int inp_peek;
void (*translator)(struct ud*);
uint64_t insn_offset;
char insn_hexcode[64];
/*
* Assembly output buffer
*/
char *asm_buf;
size_t asm_buf_size;
size_t asm_buf_fill;
char asm_buf_int[128];
/*
* Symbol resolver for use in the translation phase.
*/
const char* (*sym_resolver)(struct ud*, uint64_t addr, int64_t *offset);
uint8_t dis_mode;
uint64_t pc;
uint8_t vendor;
enum ud_mnemonic_code mnemonic;
struct ud_operand operand[4];
uint8_t error;
uint8_t _rex;
uint8_t pfx_rex;
uint8_t pfx_seg;
uint8_t pfx_opr;
uint8_t pfx_adr;
uint8_t pfx_lock;
uint8_t pfx_str;
uint8_t pfx_rep;
uint8_t pfx_repe;
uint8_t pfx_repne;
uint8_t opr_mode;
uint8_t adr_mode;
uint8_t br_far;
uint8_t br_near;
uint8_t have_modrm;
uint8_t modrm;
uint8_t modrm_offset;
uint8_t vex_op;
uint8_t vex_b1;
uint8_t vex_b2;
uint8_t primary_opcode;
void * user_opaque_data;
struct ud_itab_entry * itab_entry;
struct ud_lookup_table_list_entry *le;
};
/* -----------------------------------------------------------------------------
* Type-definitions
* -----------------------------------------------------------------------------
*/
typedef enum ud_type ud_type_t;
typedef enum ud_mnemonic_code ud_mnemonic_code_t;
typedef struct ud ud_t;
typedef struct ud_operand ud_operand_t;
#define UD_SYN_INTEL ud_translate_intel
#define UD_SYN_ATT ud_translate_att
#define UD_EOI (-1)
#define UD_INP_CACHE_SZ 32
#define UD_VENDOR_AMD 0
#define UD_VENDOR_INTEL 1
#define UD_VENDOR_ANY 2
#endif
/*
vim: set ts=2 sw=2 expandtab
*/

View file

@ -1,99 +0,0 @@
/* udis86 - libudis86/udint.h -- definitions for internal use only
*
* Copyright (c) 2002-2009 Vivek Thampi
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _UDINT_H_
#define _UDINT_H_
#include "types.h"
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#if defined(UD_DEBUG) && HAVE_ASSERT_H
# include <assert.h>
# define UD_ASSERT(_x) assert(_x)
#else
# define UD_ASSERT(_x)
#endif /* !HAVE_ASSERT_H */
#if defined(UD_DEBUG)
#define UDERR(u, msg) \
do { \
(u)->error = 1; \
fprintf(stderr, "decode-error: %s:%d: %s", \
__FILE__, __LINE__, (msg)); \
} while (0)
#else
#define UDERR(u, m) \
do { \
(u)->error = 1; \
} while (0)
#endif /* !LOGERR */
#define UD_RETURN_ON_ERROR(u) \
do { \
if ((u)->error != 0) { \
return (u)->error; \
} \
} while (0)
#define UD_RETURN_WITH_ERROR(u, m) \
do { \
UDERR(u, m); \
return (u)->error; \
} while (0)
#ifndef __UD_STANDALONE__
# define UD_NON_STANDALONE(x) x
#else
# define UD_NON_STANDALONE(x)
#endif
/* printf formatting int64 specifier */
#ifdef FMT64
# undef FMT64
#endif
#if defined(_MSC_VER) || defined(__BORLANDC__)
# define FMT64 "I64"
#else
# if defined(__APPLE__) || defined(__OpenBSD__)
# define FMT64 "ll"
# elif defined(__amd64__) || defined(__x86_64__)
# define FMT64 "l"
# else
# define FMT64 "ll"
# endif /* !x64 */
#endif
/* define an inline macro */
#if defined(_MSC_VER) || defined(__BORLANDC__)
# define UD_INLINE __inline /* MS Visual Studio requires __inline
instead of inline for C code */
#else
# define UD_INLINE inline
#endif
#endif /* _UDINT_H_ */

View file

@ -1,458 +0,0 @@
/* udis86 - libudis86/udis86.c
*
* Copyright (c) 2002-2013 Vivek Thampi
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "udint.h"
#include "extern.h"
#include "decode.h"
#if !defined(__UD_STANDALONE__)
# if HAVE_STRING_H
# include <string.h>
# endif
#endif /* !__UD_STANDALONE__ */
static void ud_inp_init(struct ud *u);
/* =============================================================================
* ud_init
* Initializes ud_t object.
* =============================================================================
*/
extern void
ud_init(struct ud* u)
{
memset((void*)u, 0, sizeof(struct ud));
ud_set_mode(u, 16);
u->mnemonic = UD_Iinvalid;
ud_set_pc(u, 0);
#ifndef __UD_STANDALONE__
ud_set_input_file(u, stdin);
#endif /* __UD_STANDALONE__ */
ud_set_asm_buffer(u, u->asm_buf_int, sizeof(u->asm_buf_int));
}
/* =============================================================================
* ud_disassemble
* Disassembles one instruction and returns the number of
* bytes disassembled. A zero means end of disassembly.
* =============================================================================
*/
extern unsigned int
ud_disassemble(struct ud* u)
{
int len;
if (u->inp_end) {
return 0;
}
if ((len = ud_decode(u)) > 0) {
if (u->translator != NULL) {
u->asm_buf[0] = '\0';
u->translator(u);
}
}
return len;
}
/* =============================================================================
* ud_set_mode() - Set Disassemly Mode.
* =============================================================================
*/
extern void
ud_set_mode(struct ud* u, uint8_t m)
{
switch(m) {
case 16:
case 32:
case 64: u->dis_mode = m ; return;
default: u->dis_mode = 16; return;
}
}
/* =============================================================================
* ud_set_vendor() - Set vendor.
* =============================================================================
*/
extern void
ud_set_vendor(struct ud* u, unsigned v)
{
switch(v) {
case UD_VENDOR_INTEL:
u->vendor = v;
break;
case UD_VENDOR_ANY:
u->vendor = v;
break;
default:
u->vendor = UD_VENDOR_AMD;
}
}
/* =============================================================================
* ud_set_pc() - Sets code origin.
* =============================================================================
*/
extern void
ud_set_pc(struct ud* u, uint64_t o)
{
u->pc = o;
}
/* =============================================================================
* ud_set_syntax() - Sets the output syntax.
* =============================================================================
*/
extern void
ud_set_syntax(struct ud* u, void (*t)(struct ud*))
{
u->translator = t;
}
/* =============================================================================
* ud_insn() - returns the disassembled instruction
* =============================================================================
*/
const char*
ud_insn_asm(const struct ud* u)
{
return u->asm_buf;
}
/* =============================================================================
* ud_insn_offset() - Returns the offset.
* =============================================================================
*/
uint64_t
ud_insn_off(const struct ud* u)
{
return u->insn_offset;
}
/* =============================================================================
* ud_insn_hex() - Returns hex form of disassembled instruction.
* =============================================================================
*/
const char*
ud_insn_hex(struct ud* u)
{
u->insn_hexcode[0] = 0;
if (!u->error) {
unsigned int i;
const unsigned char *src_ptr = ud_insn_ptr(u);
char* src_hex;
src_hex = (char*) u->insn_hexcode;
/* for each byte used to decode instruction */
for (i = 0; i < ud_insn_len(u) && i < sizeof(u->insn_hexcode) / 2;
++i, ++src_ptr) {
sprintf(src_hex, "%02x", *src_ptr & 0xFF);
src_hex += 2;
}
}
return u->insn_hexcode;
}
/* =============================================================================
* ud_insn_ptr
* Returns a pointer to buffer containing the bytes that were
* disassembled.
* =============================================================================
*/
extern const uint8_t*
ud_insn_ptr(const struct ud* u)
{
return (u->inp_buf == NULL) ?
u->inp_sess : u->inp_buf + (u->inp_buf_index - u->inp_ctr);
}
/* =============================================================================
* ud_insn_len
* Returns the count of bytes disassembled.
* =============================================================================
*/
extern unsigned int
ud_insn_len(const struct ud* u)
{
return u->inp_ctr;
}
/* =============================================================================
* ud_insn_get_opr
* Return the operand struct representing the nth operand of
* the currently disassembled instruction. Returns NULL if
* there's no such operand.
* =============================================================================
*/
const struct ud_operand*
ud_insn_opr(const struct ud *u, unsigned int n)
{
if (n > 3 || u->operand[n].type == UD_NONE) {
return NULL;
} else {
return &u->operand[n];
}
}
/* =============================================================================
* ud_opr_is_sreg
* Returns non-zero if the given operand is of a segment register type.
* =============================================================================
*/
int
ud_opr_is_sreg(const struct ud_operand *opr)
{
return opr->type == UD_OP_REG &&
opr->base >= UD_R_ES &&
opr->base <= UD_R_GS;
}
/* =============================================================================
* ud_opr_is_sreg
* Returns non-zero if the given operand is of a general purpose
* register type.
* =============================================================================
*/
int
ud_opr_is_gpr(const struct ud_operand *opr)
{
return opr->type == UD_OP_REG &&
opr->base >= UD_R_AL &&
opr->base <= UD_R_R15;
}
/* =============================================================================
* ud_set_user_opaque_data
* ud_get_user_opaque_data
* Get/set user opaqute data pointer
* =============================================================================
*/
void
ud_set_user_opaque_data(struct ud * u, void* opaque)
{
u->user_opaque_data = opaque;
}
void*
ud_get_user_opaque_data(const struct ud *u)
{
return u->user_opaque_data;
}
/* =============================================================================
* ud_set_asm_buffer
* Allow the user to set an assembler output buffer. If `buf` is NULL,
* we switch back to the internal buffer.
* =============================================================================
*/
void
ud_set_asm_buffer(struct ud *u, char *buf, size_t size)
{
if (buf == NULL) {
ud_set_asm_buffer(u, u->asm_buf_int, sizeof(u->asm_buf_int));
} else {
u->asm_buf = buf;
u->asm_buf_size = size;
}
}
/* =============================================================================
* ud_set_sym_resolver
* Set symbol resolver for relative targets used in the translation
* phase.
*
* The resolver is a function that takes a uint64_t address and returns a
* symbolic name for the that address. The function also takes a second
* argument pointing to an integer that the client can optionally set to a
* non-zero value for offsetted targets. (symbol+offset) The function may
* also return NULL, in which case the translator only prints the target
* address.
*
* The function pointer maybe NULL which resets symbol resolution.
* =============================================================================
*/
void
ud_set_sym_resolver(struct ud *u, const char* (*resolver)(struct ud*,
uint64_t addr,
int64_t *offset))
{
u->sym_resolver = resolver;
}
/* =============================================================================
* ud_insn_mnemonic
* Return the current instruction mnemonic.
* =============================================================================
*/
enum ud_mnemonic_code
ud_insn_mnemonic(const struct ud *u)
{
return u->mnemonic;
}
/* =============================================================================
* ud_lookup_mnemonic
* Looks up mnemonic code in the mnemonic string table.
* Returns NULL if the mnemonic code is invalid.
* =============================================================================
*/
const char*
ud_lookup_mnemonic(enum ud_mnemonic_code c)
{
if (c < UD_MAX_MNEMONIC_CODE) {
return ud_mnemonics_str[c];
} else {
return "???";
}
}
/*
* ud_inp_init
* Initializes the input system.
*/
static void
ud_inp_init(struct ud *u)
{
u->inp_hook = NULL;
u->inp_buf = NULL;
u->inp_buf_size = 0;
u->inp_buf_index = 0;
u->inp_curr = 0;
u->inp_ctr = 0;
u->inp_end = 0;
u->inp_peek = UD_EOI;
UD_NON_STANDALONE(u->inp_file = NULL);
}
/* =============================================================================
* ud_inp_set_hook
* Sets input hook.
* =============================================================================
*/
void
ud_set_input_hook(register struct ud* u, int (*hook)(struct ud*))
{
ud_inp_init(u);
u->inp_hook = hook;
}
/* =============================================================================
* ud_inp_set_buffer
* Set buffer as input.
* =============================================================================
*/
void
ud_set_input_buffer(register struct ud* u, const uint8_t* buf, size_t len)
{
ud_inp_init(u);
u->inp_buf = buf;
u->inp_buf_size = len;
u->inp_buf_index = 0;
}
#ifndef __UD_STANDALONE__
/* =============================================================================
* ud_input_set_file
* Set FILE as input.
* =============================================================================
*/
static int
inp_file_hook(struct ud* u)
{
return fgetc(u->inp_file);
}
void
ud_set_input_file(register struct ud* u, FILE* f)
{
ud_inp_init(u);
u->inp_hook = inp_file_hook;
u->inp_file = f;
}
#endif /* __UD_STANDALONE__ */
/* =============================================================================
* ud_input_skip
* Skip n input bytes.
* ============================================================================
*/
void
ud_input_skip(struct ud* u, size_t n)
{
if (u->inp_end) {
return;
}
if (u->inp_buf == NULL) {
while (n--) {
int c = u->inp_hook(u);
if (c == UD_EOI) {
goto eoi;
}
}
return;
} else {
if (n > u->inp_buf_size ||
u->inp_buf_index > u->inp_buf_size - n) {
u->inp_buf_index = u->inp_buf_size;
goto eoi;
}
u->inp_buf_index += n;
return;
}
eoi:
u->inp_end = 1;
UDERR(u, "cannot skip, eoi received\b");
return;
}
/* =============================================================================
* ud_input_end
* Returns non-zero on end-of-input.
* =============================================================================
*/
int
ud_input_end(const struct ud *u)
{
return u->inp_end;
}
/* vim:set ts=2 sw=2 expandtab */

View file

@ -1,596 +0,0 @@
/* <copyright>
This file is provided under a dual BSD/GPLv2 license. When using or
redistributing this file, you may do so under either license.
GPL LICENSE SUMMARY
Copyright (c) 2005-2014 Intel Corporation. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of version 2 of the GNU General Public License as
published by the Free Software Foundation.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution
in the file called LICENSE.GPL.
Contact Information:
http://software.intel.com/en-us/articles/intel-vtune-amplifier-xe/
BSD LICENSE
Copyright (c) 2005-2014 Intel Corporation. All rights reserved.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name of Intel Corporation nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
</copyright> */
#ifndef _ITTNOTIFY_CONFIG_H_
#define _ITTNOTIFY_CONFIG_H_
/** @cond exclude_from_documentation */
#ifndef ITT_OS_WIN
# define ITT_OS_WIN 1
#endif /* ITT_OS_WIN */
#ifndef ITT_OS_LINUX
# define ITT_OS_LINUX 2
#endif /* ITT_OS_LINUX */
#ifndef ITT_OS_MAC
# define ITT_OS_MAC 3
#endif /* ITT_OS_MAC */
#ifndef ITT_OS_FREEBSD
# define ITT_OS_FREEBSD 4
#endif /* ITT_OS_FREEBSD */
#ifndef ITT_OS
# if defined WIN32 || defined _WIN32
# define ITT_OS ITT_OS_WIN
# elif defined( __APPLE__ ) && defined( __MACH__ )
# define ITT_OS ITT_OS_MAC
# elif defined( __FreeBSD__ )
# define ITT_OS ITT_OS_FREEBSD
# else
# define ITT_OS ITT_OS_LINUX
# endif
#endif /* ITT_OS */
#ifndef ITT_PLATFORM_WIN
# define ITT_PLATFORM_WIN 1
#endif /* ITT_PLATFORM_WIN */
#ifndef ITT_PLATFORM_POSIX
# define ITT_PLATFORM_POSIX 2
#endif /* ITT_PLATFORM_POSIX */
#ifndef ITT_PLATFORM_MAC
# define ITT_PLATFORM_MAC 3
#endif /* ITT_PLATFORM_MAC */
#ifndef ITT_PLATFORM_FREEBSD
# define ITT_PLATFORM_FREEBSD 4
#endif /* ITT_PLATFORM_FREEBSD */
#ifndef ITT_PLATFORM
# if ITT_OS==ITT_OS_WIN
# define ITT_PLATFORM ITT_PLATFORM_WIN
# elif ITT_OS==ITT_OS_MAC
# define ITT_PLATFORM ITT_PLATFORM_MAC
# elif ITT_OS==ITT_OS_FREEBSD
# define ITT_PLATFORM ITT_PLATFORM_FREEBSD
# else
# define ITT_PLATFORM ITT_PLATFORM_POSIX
# endif
#endif /* ITT_PLATFORM */
#if defined(_UNICODE) && !defined(UNICODE)
#define UNICODE
#endif
#include <stddef.h>
#if ITT_PLATFORM==ITT_PLATFORM_WIN
#include <tchar.h>
#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
#include <stdint.h>
#if defined(UNICODE) || defined(_UNICODE)
#include <wchar.h>
#endif /* UNICODE || _UNICODE */
#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
#ifndef ITTAPI_CDECL
# if ITT_PLATFORM==ITT_PLATFORM_WIN
# define ITTAPI_CDECL __cdecl
# else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
# if defined _M_IX86 || defined __i386__
# define ITTAPI_CDECL __attribute__ ((cdecl))
# else /* _M_IX86 || __i386__ */
# define ITTAPI_CDECL /* actual only on x86 platform */
# endif /* _M_IX86 || __i386__ */
# endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
#endif /* ITTAPI_CDECL */
#ifndef STDCALL
# if ITT_PLATFORM==ITT_PLATFORM_WIN
# define STDCALL __stdcall
# else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
# if defined _M_IX86 || defined __i386__
# define STDCALL __attribute__ ((stdcall))
# else /* _M_IX86 || __i386__ */
# define STDCALL /* supported only on x86 platform */
# endif /* _M_IX86 || __i386__ */
# endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
#endif /* STDCALL */
#define ITTAPI ITTAPI_CDECL
#define LIBITTAPI ITTAPI_CDECL
/* TODO: Temporary for compatibility! */
#define ITTAPI_CALL ITTAPI_CDECL
#define LIBITTAPI_CALL ITTAPI_CDECL
#if ITT_PLATFORM==ITT_PLATFORM_WIN
/* use __forceinline (VC++ specific) */
#define ITT_INLINE __forceinline
#define ITT_INLINE_ATTRIBUTE /* nothing */
#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
/*
* Generally, functions are not inlined unless optimization is specified.
* For functions declared inline, this attribute inlines the function even
* if no optimization level was specified.
*/
#ifdef __STRICT_ANSI__
#define ITT_INLINE static
#define ITT_INLINE_ATTRIBUTE __attribute__((unused))
#else /* __STRICT_ANSI__ */
#define ITT_INLINE static inline
#define ITT_INLINE_ATTRIBUTE __attribute__((always_inline, unused))
#endif /* __STRICT_ANSI__ */
#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
/** @endcond */
#ifndef ITT_ARCH_IA32
# define ITT_ARCH_IA32 1
#endif /* ITT_ARCH_IA32 */
#ifndef ITT_ARCH_IA32E
# define ITT_ARCH_IA32E 2
#endif /* ITT_ARCH_IA32E */
#ifndef ITT_ARCH_ARM
# define ITT_ARCH_ARM 4
#endif /* ITT_ARCH_ARM */
#ifndef ITT_ARCH_PPC64
# define ITT_ARCH_PPC64 5
#endif /* ITT_ARCH_PPC64 */
#ifndef ITT_ARCH
# if defined _M_IX86 || defined __i386__
# define ITT_ARCH ITT_ARCH_IA32
# elif defined _M_X64 || defined _M_AMD64 || defined __x86_64__
# define ITT_ARCH ITT_ARCH_IA32E
# elif defined _M_IA64 || defined __ia64__
# define ITT_ARCH ITT_ARCH_IA64
# elif defined _M_ARM || defined __arm__
# define ITT_ARCH ITT_ARCH_ARM
# elif defined __powerpc64__
# define ITT_ARCH ITT_ARCH_PPC64
# endif
#endif
#ifdef __cplusplus
# define ITT_EXTERN_C extern "C"
# define ITT_EXTERN_C_BEGIN extern "C" {
# define ITT_EXTERN_C_END }
#else
# define ITT_EXTERN_C /* nothing */
# define ITT_EXTERN_C_BEGIN /* nothing */
# define ITT_EXTERN_C_END /* nothing */
#endif /* __cplusplus */
#define ITT_TO_STR_AUX(x) #x
#define ITT_TO_STR(x) ITT_TO_STR_AUX(x)
#define __ITT_BUILD_ASSERT(expr, suffix) do { \
static char __itt_build_check_##suffix[(expr) ? 1 : -1]; \
__itt_build_check_##suffix[0] = 0; \
} while(0)
#define _ITT_BUILD_ASSERT(expr, suffix) __ITT_BUILD_ASSERT((expr), suffix)
#define ITT_BUILD_ASSERT(expr) _ITT_BUILD_ASSERT((expr), __LINE__)
#define ITT_MAGIC { 0xED, 0xAB, 0xAB, 0xEC, 0x0D, 0xEE, 0xDA, 0x30 }
/* Replace with snapshot date YYYYMMDD for promotion build. */
#define API_VERSION_BUILD 20151119
#ifndef API_VERSION_NUM
#define API_VERSION_NUM 0.0.0
#endif /* API_VERSION_NUM */
#define API_VERSION "ITT-API-Version " ITT_TO_STR(API_VERSION_NUM) \
" (" ITT_TO_STR(API_VERSION_BUILD) ")"
/* OS communication functions */
#if ITT_PLATFORM==ITT_PLATFORM_WIN
#include <windows.h>
typedef HMODULE lib_t;
typedef DWORD TIDT;
typedef CRITICAL_SECTION mutex_t;
#define MUTEX_INITIALIZER { 0 }
#define strong_alias(name, aliasname) /* empty for Windows */
#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
#include <dlfcn.h>
#if defined(UNICODE) || defined(_UNICODE)
#include <wchar.h>
#endif /* UNICODE */
#ifndef _GNU_SOURCE
#define _GNU_SOURCE 1 /* need for PTHREAD_MUTEX_RECURSIVE */
#endif /* _GNU_SOURCE */
#ifndef __USE_UNIX98
#define __USE_UNIX98 1 /* need for PTHREAD_MUTEX_RECURSIVE, on SLES11.1 with gcc 4.3.4 wherein pthread.h missing dependency on __USE_XOPEN2K8 */
#endif /*__USE_UNIX98*/
#include <pthread.h>
typedef void* lib_t;
typedef pthread_t TIDT;
typedef pthread_mutex_t mutex_t;
#define MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
#define _strong_alias(name, aliasname) \
extern __typeof (name) aliasname __attribute__ ((alias (#name)));
#define strong_alias(name, aliasname) _strong_alias(name, aliasname)
#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
#if ITT_PLATFORM==ITT_PLATFORM_WIN
#define __itt_get_proc(lib, name) GetProcAddress(lib, name)
#define __itt_mutex_init(mutex) InitializeCriticalSection(mutex)
#define __itt_mutex_lock(mutex) EnterCriticalSection(mutex)
#define __itt_mutex_unlock(mutex) LeaveCriticalSection(mutex)
#define __itt_load_lib(name) LoadLibraryA(name)
#define __itt_unload_lib(handle) FreeLibrary(handle)
#define __itt_system_error() (int)GetLastError()
#define __itt_fstrcmp(s1, s2) lstrcmpA(s1, s2)
#define __itt_fstrnlen(s, l) strnlen_s(s, l)
#define __itt_fstrcpyn(s1, b, s2, l) strncpy_s(s1, b, s2, l)
#define __itt_fstrdup(s) _strdup(s)
#define __itt_thread_id() GetCurrentThreadId()
#define __itt_thread_yield() SwitchToThread()
#ifndef ITT_SIMPLE_INIT
ITT_INLINE long
__itt_interlocked_increment(volatile long* ptr) ITT_INLINE_ATTRIBUTE;
ITT_INLINE long __itt_interlocked_increment(volatile long* ptr)
{
return InterlockedIncrement(ptr);
}
#endif /* ITT_SIMPLE_INIT */
#else /* ITT_PLATFORM!=ITT_PLATFORM_WIN */
#define __itt_get_proc(lib, name) dlsym(lib, name)
#define __itt_mutex_init(mutex) {\
pthread_mutexattr_t mutex_attr; \
int error_code = pthread_mutexattr_init(&mutex_attr); \
if (error_code) \
__itt_report_error(__itt_error_system, "pthread_mutexattr_init", \
error_code); \
error_code = pthread_mutexattr_settype(&mutex_attr, \
PTHREAD_MUTEX_RECURSIVE); \
if (error_code) \
__itt_report_error(__itt_error_system, "pthread_mutexattr_settype", \
error_code); \
error_code = pthread_mutex_init(mutex, &mutex_attr); \
if (error_code) \
__itt_report_error(__itt_error_system, "pthread_mutex_init", \
error_code); \
error_code = pthread_mutexattr_destroy(&mutex_attr); \
if (error_code) \
__itt_report_error(__itt_error_system, "pthread_mutexattr_destroy", \
error_code); \
}
#define __itt_mutex_lock(mutex) pthread_mutex_lock(mutex)
#define __itt_mutex_unlock(mutex) pthread_mutex_unlock(mutex)
#define __itt_load_lib(name) dlopen(name, RTLD_LAZY)
#define __itt_unload_lib(handle) dlclose(handle)
#define __itt_system_error() errno
#define __itt_fstrcmp(s1, s2) strcmp(s1, s2)
/* makes customer code define safe APIs for SDL_STRNLEN_S and SDL_STRNCPY_S */
#ifdef SDL_STRNLEN_S
#define __itt_fstrnlen(s, l) SDL_STRNLEN_S(s, l)
#else
#define __itt_fstrnlen(s, l) strlen(s)
#endif /* SDL_STRNLEN_S */
#ifdef SDL_STRNCPY_S
#define __itt_fstrcpyn(s1, b, s2, l) SDL_STRNCPY_S(s1, b, s2, l)
#else
#define __itt_fstrcpyn(s1, b, s2, l) strncpy(s1, s2, l)
#endif /* SDL_STRNCPY_S */
#define __itt_fstrdup(s) strdup(s)
#define __itt_thread_id() pthread_self()
#define __itt_thread_yield() sched_yield()
#if ITT_ARCH==ITT_ARCH_IA64
#ifdef __INTEL_COMPILER
#define __TBB_machine_fetchadd4(addr, val) __fetchadd4_acq((void *)addr, val)
#else /* __INTEL_COMPILER */
/* TODO: Add Support for not Intel compilers for IA-64 architecture */
#endif /* __INTEL_COMPILER */
#elif ITT_ARCH==ITT_ARCH_IA32 || ITT_ARCH==ITT_ARCH_IA32E /* ITT_ARCH!=ITT_ARCH_IA64 */
ITT_INLINE long
__TBB_machine_fetchadd4(volatile void* ptr, long addend) ITT_INLINE_ATTRIBUTE;
ITT_INLINE long __TBB_machine_fetchadd4(volatile void* ptr, long addend)
{
long result;
__asm__ __volatile__("lock\nxadd %0,%1"
: "=r"(result),"=m"(*(int*)ptr)
: "0"(addend), "m"(*(int*)ptr)
: "memory");
return result;
}
#elif ITT_ARCH==ITT_ARCH_ARM || ITT_ARCH==ITT_ARCH_PPC64
#define __TBB_machine_fetchadd4(addr, val) __sync_fetch_and_add(addr, val)
#endif /* ITT_ARCH==ITT_ARCH_IA64 */
#ifndef ITT_SIMPLE_INIT
ITT_INLINE long
__itt_interlocked_increment(volatile long* ptr) ITT_INLINE_ATTRIBUTE;
ITT_INLINE long __itt_interlocked_increment(volatile long* ptr)
{
return __TBB_machine_fetchadd4(ptr, 1) + 1L;
}
#endif /* ITT_SIMPLE_INIT */
#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
typedef enum {
__itt_collection_normal = 0,
__itt_collection_paused = 1
} __itt_collection_state;
typedef enum {
__itt_thread_normal = 0,
__itt_thread_ignored = 1
} __itt_thread_state;
#pragma pack(push, 8)
typedef struct ___itt_thread_info
{
const char* nameA; /*!< Copy of original name in ASCII. */
#if defined(UNICODE) || defined(_UNICODE)
const wchar_t* nameW; /*!< Copy of original name in UNICODE. */
#else /* UNICODE || _UNICODE */
void* nameW;
#endif /* UNICODE || _UNICODE */
TIDT tid;
__itt_thread_state state; /*!< Thread state (paused or normal) */
int extra1; /*!< Reserved to the runtime */
void* extra2; /*!< Reserved to the runtime */
struct ___itt_thread_info* next;
} __itt_thread_info;
#include "ittnotify_types.h" /* For __itt_group_id definition */
typedef struct ___itt_api_info_20101001
{
const char* name;
void** func_ptr;
void* init_func;
__itt_group_id group;
} __itt_api_info_20101001;
typedef struct ___itt_api_info
{
const char* name;
void** func_ptr;
void* init_func;
void* null_func;
__itt_group_id group;
} __itt_api_info;
typedef struct __itt_counter_info
{
const char* nameA; /*!< Copy of original name in ASCII. */
#if defined(UNICODE) || defined(_UNICODE)
const wchar_t* nameW; /*!< Copy of original name in UNICODE. */
#else /* UNICODE || _UNICODE */
void* nameW;
#endif /* UNICODE || _UNICODE */
const char* domainA; /*!< Copy of original name in ASCII. */
#if defined(UNICODE) || defined(_UNICODE)
const wchar_t* domainW; /*!< Copy of original name in UNICODE. */
#else /* UNICODE || _UNICODE */
void* domainW;
#endif /* UNICODE || _UNICODE */
int type;
long index;
int extra1; /*!< Reserved to the runtime */
void* extra2; /*!< Reserved to the runtime */
struct __itt_counter_info* next;
} __itt_counter_info_t;
struct ___itt_domain;
struct ___itt_string_handle;
typedef struct ___itt_global
{
unsigned char magic[8];
unsigned long version_major;
unsigned long version_minor;
unsigned long version_build;
volatile long api_initialized;
volatile long mutex_initialized;
volatile long atomic_counter;
mutex_t mutex;
lib_t lib;
void* error_handler;
const char** dll_path_ptr;
__itt_api_info* api_list_ptr;
struct ___itt_global* next;
/* Joinable structures below */
__itt_thread_info* thread_list;
struct ___itt_domain* domain_list;
struct ___itt_string_handle* string_list;
__itt_collection_state state;
__itt_counter_info_t* counter_list;
} __itt_global;
#pragma pack(pop)
#define NEW_THREAD_INFO_W(gptr,h,h_tail,t,s,n) { \
h = (__itt_thread_info*)malloc(sizeof(__itt_thread_info)); \
if (h != NULL) { \
h->tid = t; \
h->nameA = NULL; \
h->nameW = n ? _wcsdup(n) : NULL; \
h->state = s; \
h->extra1 = 0; /* reserved */ \
h->extra2 = NULL; /* reserved */ \
h->next = NULL; \
if (h_tail == NULL) \
(gptr)->thread_list = h; \
else \
h_tail->next = h; \
} \
}
#define NEW_THREAD_INFO_A(gptr,h,h_tail,t,s,n) { \
h = (__itt_thread_info*)malloc(sizeof(__itt_thread_info)); \
if (h != NULL) { \
h->tid = t; \
h->nameA = n ? __itt_fstrdup(n) : NULL; \
h->nameW = NULL; \
h->state = s; \
h->extra1 = 0; /* reserved */ \
h->extra2 = NULL; /* reserved */ \
h->next = NULL; \
if (h_tail == NULL) \
(gptr)->thread_list = h; \
else \
h_tail->next = h; \
} \
}
#define NEW_DOMAIN_W(gptr,h,h_tail,name) { \
h = (__itt_domain*)malloc(sizeof(__itt_domain)); \
if (h != NULL) { \
h->flags = 1; /* domain is enabled by default */ \
h->nameA = NULL; \
h->nameW = name ? _wcsdup(name) : NULL; \
h->extra1 = 0; /* reserved */ \
h->extra2 = NULL; /* reserved */ \
h->next = NULL; \
if (h_tail == NULL) \
(gptr)->domain_list = h; \
else \
h_tail->next = h; \
} \
}
#define NEW_DOMAIN_A(gptr,h,h_tail,name) { \
h = (__itt_domain*)malloc(sizeof(__itt_domain)); \
if (h != NULL) { \
h->flags = 1; /* domain is enabled by default */ \
h->nameA = name ? __itt_fstrdup(name) : NULL; \
h->nameW = NULL; \
h->extra1 = 0; /* reserved */ \
h->extra2 = NULL; /* reserved */ \
h->next = NULL; \
if (h_tail == NULL) \
(gptr)->domain_list = h; \
else \
h_tail->next = h; \
} \
}
#define NEW_STRING_HANDLE_W(gptr,h,h_tail,name) { \
h = (__itt_string_handle*)malloc(sizeof(__itt_string_handle)); \
if (h != NULL) { \
h->strA = NULL; \
h->strW = name ? _wcsdup(name) : NULL; \
h->extra1 = 0; /* reserved */ \
h->extra2 = NULL; /* reserved */ \
h->next = NULL; \
if (h_tail == NULL) \
(gptr)->string_list = h; \
else \
h_tail->next = h; \
} \
}
#define NEW_STRING_HANDLE_A(gptr,h,h_tail,name) { \
h = (__itt_string_handle*)malloc(sizeof(__itt_string_handle)); \
if (h != NULL) { \
h->strA = name ? __itt_fstrdup(name) : NULL; \
h->strW = NULL; \
h->extra1 = 0; /* reserved */ \
h->extra2 = NULL; /* reserved */ \
h->next = NULL; \
if (h_tail == NULL) \
(gptr)->string_list = h; \
else \
h_tail->next = h; \
} \
}
#define NEW_COUNTER_W(gptr,h,h_tail,name,domain,type) { \
h = (__itt_counter_info_t*)malloc(sizeof(__itt_counter_info_t)); \
if (h != NULL) { \
h->nameA = NULL; \
h->nameW = name ? _wcsdup(name) : NULL; \
h->domainA = NULL; \
h->domainW = name ? _wcsdup(domain) : NULL; \
h->type = type; \
h->index = 0; \
h->next = NULL; \
if (h_tail == NULL) \
(gptr)->counter_list = h; \
else \
h_tail->next = h; \
} \
}
#define NEW_COUNTER_A(gptr,h,h_tail,name,domain,type) { \
h = (__itt_counter_info_t*)malloc(sizeof(__itt_counter_info_t)); \
if (h != NULL) { \
h->nameA = name ? __itt_fstrdup(name) : NULL; \
h->nameW = NULL; \
h->domainA = domain ? __itt_fstrdup(domain) : NULL; \
h->domainW = NULL; \
h->type = type; \
h->index = 0; \
h->next = NULL; \
if (h_tail == NULL) \
(gptr)->counter_list = h; \
else \
h_tail->next = h; \
} \
}
#endif /* _ITTNOTIFY_CONFIG_H_ */

View file

@ -1,115 +0,0 @@
/* <copyright>
This file is provided under a dual BSD/GPLv2 license. When using or
redistributing this file, you may do so under either license.
GPL LICENSE SUMMARY
Copyright (c) 2005-2014 Intel Corporation. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of version 2 of the GNU General Public License as
published by the Free Software Foundation.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution
in the file called LICENSE.GPL.
Contact Information:
http://software.intel.com/en-us/articles/intel-vtune-amplifier-xe/
BSD LICENSE
Copyright (c) 2005-2014 Intel Corporation. All rights reserved.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name of Intel Corporation nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
</copyright> */
#ifndef _ITTNOTIFY_TYPES_H_
#define _ITTNOTIFY_TYPES_H_
typedef enum ___itt_group_id
{
__itt_group_none = 0,
__itt_group_legacy = 1<<0,
__itt_group_control = 1<<1,
__itt_group_thread = 1<<2,
__itt_group_mark = 1<<3,
__itt_group_sync = 1<<4,
__itt_group_fsync = 1<<5,
__itt_group_jit = 1<<6,
__itt_group_model = 1<<7,
__itt_group_splitter_min = 1<<7,
__itt_group_counter = 1<<8,
__itt_group_frame = 1<<9,
__itt_group_stitch = 1<<10,
__itt_group_heap = 1<<11,
__itt_group_splitter_max = 1<<12,
__itt_group_structure = 1<<12,
__itt_group_suppress = 1<<13,
__itt_group_arrays = 1<<14,
__itt_group_all = -1
} __itt_group_id;
#pragma pack(push, 8)
typedef struct ___itt_group_list
{
__itt_group_id id;
const char* name;
} __itt_group_list;
#pragma pack(pop)
#define ITT_GROUP_LIST(varname) \
static __itt_group_list varname[] = { \
{ __itt_group_all, "all" }, \
{ __itt_group_control, "control" }, \
{ __itt_group_thread, "thread" }, \
{ __itt_group_mark, "mark" }, \
{ __itt_group_sync, "sync" }, \
{ __itt_group_fsync, "fsync" }, \
{ __itt_group_jit, "jit" }, \
{ __itt_group_model, "model" }, \
{ __itt_group_counter, "counter" }, \
{ __itt_group_frame, "frame" }, \
{ __itt_group_stitch, "stitch" }, \
{ __itt_group_heap, "heap" }, \
{ __itt_group_structure, "structure" }, \
{ __itt_group_suppress, "suppress" }, \
{ __itt_group_arrays, "arrays" }, \
{ __itt_group_none, NULL } \
}
#endif /* _ITTNOTIFY_TYPES_H_ */

View file

@ -1,312 +0,0 @@
/* <copyright>
This file is provided under a dual BSD/GPLv2 license. When using or
redistributing this file, you may do so under either license.
GPL LICENSE SUMMARY
Copyright (c) 2005-2014 Intel Corporation. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of version 2 of the GNU General Public License as
published by the Free Software Foundation.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution
in the file called LICENSE.GPL.
Contact Information:
http://software.intel.com/en-us/articles/intel-vtune-amplifier-xe/
BSD LICENSE
Copyright (c) 2005-2014 Intel Corporation. All rights reserved.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name of Intel Corporation nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
</copyright> */
#include "ittnotify_config.h"
#if ITT_PLATFORM==ITT_PLATFORM_WIN
#include <windows.h>
#pragma optimize("", off)
#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
#include <stdlib.h>
#include "jitprofiling.h"
static const char rcsid[] = "\n@(#) $Revision: 463960 $\n";
#define DLL_ENVIRONMENT_VAR "VS_PROFILER"
#ifndef NEW_DLL_ENVIRONMENT_VAR
#if ITT_ARCH==ITT_ARCH_IA32
#define NEW_DLL_ENVIRONMENT_VAR "INTEL_JIT_PROFILER32"
#else
#define NEW_DLL_ENVIRONMENT_VAR "INTEL_JIT_PROFILER64"
#endif
#endif /* NEW_DLL_ENVIRONMENT_VAR */
#if ITT_PLATFORM==ITT_PLATFORM_WIN
#define DEFAULT_DLLNAME "JitPI.dll"
HINSTANCE m_libHandle = NULL;
#elif ITT_PLATFORM==ITT_PLATFORM_MAC
#define DEFAULT_DLLNAME "libJitPI.dylib"
void* m_libHandle = NULL;
#else
#define DEFAULT_DLLNAME "libJitPI.so"
void* m_libHandle = NULL;
#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
/* default location of JIT profiling agent on Android */
#define ANDROID_JIT_AGENT_PATH "/data/intel/libittnotify.so"
/* the function pointers */
typedef unsigned int(JITAPI *TPInitialize)(void);
static TPInitialize FUNC_Initialize=NULL;
typedef unsigned int(JITAPI *TPNotify)(unsigned int, void*);
static TPNotify FUNC_NotifyEvent=NULL;
static iJIT_IsProfilingActiveFlags executionMode = iJIT_NOTHING_RUNNING;
/* end collector dll part. */
/* loadiJIT_Funcs() : this function is called just in the beginning
* and is responsible to load the functions from BistroJavaCollector.dll
* result:
* on success: the functions loads, iJIT_DLL_is_missing=0, return value = 1
* on failure: the functions are NULL, iJIT_DLL_is_missing=1, return value = 0
*/
static int loadiJIT_Funcs(void);
/* global representing whether the collector can't be loaded */
static int iJIT_DLL_is_missing = 0;
ITT_EXTERN_C int JITAPI
iJIT_NotifyEvent(iJIT_JVM_EVENT event_type, void *EventSpecificData)
{
int ReturnValue;
/* initialization part - the collector has not been loaded yet. */
if (!FUNC_NotifyEvent)
{
if (iJIT_DLL_is_missing)
return 0;
if (!loadiJIT_Funcs())
return 0;
}
if (event_type == iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED ||
event_type == iJVM_EVENT_TYPE_METHOD_UPDATE)
{
if (((piJIT_Method_Load)EventSpecificData)->method_id == 0)
return 0;
}
else if (event_type == iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED_V2)
{
if (((piJIT_Method_Load_V2)EventSpecificData)->method_id == 0)
return 0;
}
else if (event_type == iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED_V3)
{
if (((piJIT_Method_Load_V3)EventSpecificData)->method_id == 0)
return 0;
}
else if (event_type == iJVM_EVENT_TYPE_METHOD_INLINE_LOAD_FINISHED)
{
if (((piJIT_Method_Inline_Load)EventSpecificData)->method_id == 0 ||
((piJIT_Method_Inline_Load)EventSpecificData)->parent_method_id == 0)
return 0;
}
ReturnValue = (int)FUNC_NotifyEvent(event_type, EventSpecificData);
return ReturnValue;
}
ITT_EXTERN_C iJIT_IsProfilingActiveFlags JITAPI iJIT_IsProfilingActive(void)
{
if (!iJIT_DLL_is_missing)
{
loadiJIT_Funcs();
}
return executionMode;
}
/* This function loads the collector dll and the relevant functions.
* on success: all functions load, iJIT_DLL_is_missing = 0, return value = 1
* on failure: all functions are NULL, iJIT_DLL_is_missing = 1, return value = 0
*/
static int loadiJIT_Funcs(void)
{
static int bDllWasLoaded = 0;
char *dllName = (char*)rcsid; /* !! Just to avoid unused code elimination */
#if ITT_PLATFORM==ITT_PLATFORM_WIN
DWORD dNameLength = 0;
#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
if(bDllWasLoaded)
{
/* dll was already loaded, no need to do it for the second time */
return 1;
}
/* Assumes that the DLL will not be found */
iJIT_DLL_is_missing = 1;
FUNC_NotifyEvent = NULL;
if (m_libHandle)
{
#if ITT_PLATFORM==ITT_PLATFORM_WIN
FreeLibrary(m_libHandle);
#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
dlclose(m_libHandle);
#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
m_libHandle = NULL;
}
/* Try to get the dll name from the environment */
#if ITT_PLATFORM==ITT_PLATFORM_WIN
dNameLength = GetEnvironmentVariableA(NEW_DLL_ENVIRONMENT_VAR, NULL, 0);
if (dNameLength)
{
DWORD envret = 0;
dllName = (char*)malloc(sizeof(char) * (dNameLength + 1));
if(dllName != NULL)
{
envret = GetEnvironmentVariableA(NEW_DLL_ENVIRONMENT_VAR,
dllName, dNameLength);
if (envret)
{
/* Try to load the dll from the PATH... */
m_libHandle = LoadLibraryExA(dllName,
NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
}
free(dllName);
}
} else {
/* Try to use old VS_PROFILER variable */
dNameLength = GetEnvironmentVariableA(DLL_ENVIRONMENT_VAR, NULL, 0);
if (dNameLength)
{
DWORD envret = 0;
dllName = (char*)malloc(sizeof(char) * (dNameLength + 1));
if(dllName != NULL)
{
envret = GetEnvironmentVariableA(DLL_ENVIRONMENT_VAR,
dllName, dNameLength);
if (envret)
{
/* Try to load the dll from the PATH... */
m_libHandle = LoadLibraryA(dllName);
}
free(dllName);
}
}
}
#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
dllName = getenv(NEW_DLL_ENVIRONMENT_VAR);
if (!dllName)
dllName = getenv(DLL_ENVIRONMENT_VAR);
#if defined(__ANDROID__) || defined(ANDROID)
if (!dllName)
dllName = ANDROID_JIT_AGENT_PATH;
#endif
if (dllName)
{
/* Try to load the dll from the PATH... */
m_libHandle = dlopen(dllName, RTLD_LAZY);
}
#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
if (!m_libHandle)
{
#if ITT_PLATFORM==ITT_PLATFORM_WIN
m_libHandle = LoadLibraryA(DEFAULT_DLLNAME);
#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
m_libHandle = dlopen(DEFAULT_DLLNAME, RTLD_LAZY);
#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
}
/* if the dll wasn't loaded - exit. */
if (!m_libHandle)
{
iJIT_DLL_is_missing = 1; /* don't try to initialize
* JIT agent the second time
*/
return 0;
}
#if ITT_PLATFORM==ITT_PLATFORM_WIN
FUNC_NotifyEvent = (TPNotify)GetProcAddress(m_libHandle, "NotifyEvent");
#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
FUNC_NotifyEvent = (TPNotify)dlsym(m_libHandle, "NotifyEvent");
#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
if (!FUNC_NotifyEvent)
{
FUNC_Initialize = NULL;
return 0;
}
#if ITT_PLATFORM==ITT_PLATFORM_WIN
FUNC_Initialize = (TPInitialize)GetProcAddress(m_libHandle, "Initialize");
#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
FUNC_Initialize = (TPInitialize)dlsym(m_libHandle, "Initialize");
#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
if (!FUNC_Initialize)
{
FUNC_NotifyEvent = NULL;
return 0;
}
executionMode = (iJIT_IsProfilingActiveFlags)FUNC_Initialize();
bDllWasLoaded = 1;
iJIT_DLL_is_missing = 0; /* DLL is ok. */
return 1;
}
ITT_EXTERN_C unsigned int JITAPI iJIT_GetNewMethodID(void)
{
static unsigned int methodID = 1;
if (methodID == 0)
return 0; /* ERROR : this is not a valid value */
return methodID++;
}

View file

@ -1,694 +0,0 @@
/* <copyright>
This file is provided under a dual BSD/GPLv2 license. When using or
redistributing this file, you may do so under either license.
GPL LICENSE SUMMARY
Copyright (c) 2005-2014 Intel Corporation. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of version 2 of the GNU General Public License as
published by the Free Software Foundation.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution
in the file called LICENSE.GPL.
Contact Information:
http://software.intel.com/en-us/articles/intel-vtune-amplifier-xe/
BSD LICENSE
Copyright (c) 2005-2014 Intel Corporation. All rights reserved.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name of Intel Corporation nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
</copyright> */
#ifndef __JITPROFILING_H__
#define __JITPROFILING_H__
/**
* @brief JIT Profiling APIs
*
* The JIT Profiling API is used to report information about just-in-time
* generated code that can be used by performance tools. The user inserts
* calls in the code generator to report information before JIT-compiled
* code goes to execution. This information is collected at runtime and used
* by tools like Intel(R) VTune(TM) Amplifier to display performance metrics
* associated with JIT-compiled code.
*
* These APIs can be used to\n
* - **Profile trace-based and method-based JIT-compiled
* code**. Some examples of environments that you can profile with these APIs:
* dynamic JIT compilation of JavaScript code traces, JIT execution in OpenCL(TM)
* software technology, Java/.NET managed execution environments, and custom
* ISV JIT engines.
* @code
* #include <jitprofiling.h>
*
* if (iJIT_IsProfilingActive != iJIT_SAMPLING_ON) {
* return;
* }
*
* iJIT_Method_Load jmethod = {0};
* jmethod.method_id = iJIT_GetNewMethodID();
* jmethod.method_name = "method_name";
* jmethod.class_file_name = "class_name";
* jmethod.source_file_name = "source_file_name";
* jmethod.method_load_address = code_addr;
* jmethod.method_size = code_size;
*
* iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, (void*)&jmethod);
* iJIT_NotifyEvent(iJVM_EVENT_TYPE_SHUTDOWN, NULL);
* @endcode
*
* * Expected behavior:
* * If any iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED event overwrites an
* already reported method, then such a method becomes invalid and its
* memory region is treated as unloaded. VTune Amplifier displays the metrics
* collected by the method until it is overwritten.
* * If supplied line number information contains multiple source lines for
* the same assembly instruction (code location), then VTune Amplifier picks up
* the first line number.
* * Dynamically generated code can be associated with a module name.
* Use the iJIT_Method_Load_V2 structure.\n
* Clarification of some cases:
* * If you register a function with the same method ID multiple times,
* specifying different module names, then the VTune Amplifier picks up
* the module name registered first. If you want to distinguish the same
* function between different JIT engines, supply different method IDs for
* each function. Other symbolic information (for example, source file)
* can be identical.
*
* - **Analyze split functions** (multiple joint or disjoint code regions
* belonging to the same function) **including re-JIT**
* with potential overlapping of code regions in time, which is common in
* resource-limited environments.
* @code
* #include <jitprofiling.h>
*
* unsigned int method_id = iJIT_GetNewMethodID();
*
* iJIT_Method_Load a = {0};
* a.method_id = method_id;
* a.method_load_address = 0x100;
* a.method_size = 0x20;
*
* iJIT_Method_Load b = {0};
* b.method_id = method_id;
* b.method_load_address = 0x200;
* b.method_size = 0x30;
*
* iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, (void*)&a);
* iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, (void*)&b);
* @endcode
*
* * Expected behaviour:
* * If a iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED event overwrites an
* already reported method, then such a method becomes invalid and
* its memory region is treated as unloaded.
* * All code regions reported with the same method ID are considered as
* belonging to the same method. Symbolic information (method name,
* source file name) will be taken from the first notification, and all
* subsequent notifications with the same method ID will be processed
* only for line number table information. So, the VTune Amplifier will map
* samples to a source line using the line number table from the current
* notification while taking the source file name from the very first one.\n
* Clarification of some cases:\n
* * If you register a second code region with a different source file
* name and the same method ID, then this information will be saved and
* will not be considered as an extension of the first code region, but
* VTune Amplifier will use the source file of the first code region and map
* performance metrics incorrectly.
* * If you register a second code region with the same source file as
* for the first region and the same method ID, then the source file will be
* discarded but VTune Amplifier will map metrics to the source file correctly.
* * If you register a second code region with a null source file and
* the same method ID, then provided line number info will be associated
* with the source file of the first code region.
*
* - **Explore inline functions** including multi-level hierarchy of
* nested inline methods which shows how performance metrics are distributed through them.
* @code
* #include <jitprofiling.h>
*
* // method_id parent_id
* // [-- c --] 3000 2000
* // [---- d -----] 2001 1000
* // [---- b ----] 2000 1000
* // [------------ a ----------------] 1000 n/a
*
* iJIT_Method_Load a = {0};
* a.method_id = 1000;
*
* iJIT_Method_Inline_Load b = {0};
* b.method_id = 2000;
* b.parent_method_id = 1000;
*
* iJIT_Method_Inline_Load c = {0};
* c.method_id = 3000;
* c.parent_method_id = 2000;
*
* iJIT_Method_Inline_Load d = {0};
* d.method_id = 2001;
* d.parent_method_id = 1000;
*
* iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, (void*)&a);
* iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_INLINE_LOAD_FINISHED, (void*)&b);
* iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_INLINE_LOAD_FINISHED, (void*)&c);
* iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_INLINE_LOAD_FINISHED, (void*)&d);
* @endcode
*
* * Requirements:
* * Each inline (iJIT_Method_Inline_Load) method should be associated
* with two method IDs: one for itself; one for its immediate parent.
* * Address regions of inline methods of the same parent method cannot
* overlap each other.
* * Execution of the parent method must not be started until it and all
* its inline methods are reported.
* * Expected behaviour:
* * In case of nested inline methods an order of
* iJVM_EVENT_TYPE_METHOD_INLINE_LOAD_FINISHED events is not important.
* * If any event overwrites either inline method or top parent method,
* then the parent, including inline methods, becomes invalid and its memory
* region is treated as unloaded.
*
* **Life time of allocated data**\n
* The client sends an event notification to the agent with event-specific
* data, which is a structure. The pointers in the structure refer to memory
* allocated by the client, which responsible for releasing it. The pointers are
* used by the iJIT_NotifyEvent method to copy client's data in a trace file,
* and they are not used after the iJIT_NotifyEvent method returns.
*/
/**
* @defgroup jitapi JIT Profiling
* @ingroup internal
* @{
*/
/**
* @brief Enumerator for the types of notifications
*/
typedef enum iJIT_jvm_event
{
iJVM_EVENT_TYPE_SHUTDOWN = 2, /**<\brief Send this to shutdown the agent.
* Use NULL for event data. */
iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED = 13, /**<\brief Send when dynamic code is
* JIT compiled and loaded into
* memory by the JIT engine, but
* before the code is executed.
* Use iJIT_Method_Load as event
* data. */
/** @cond exclude_from_documentation */
iJVM_EVENT_TYPE_METHOD_UNLOAD_START, /**<\brief Send when compiled dynamic
* code is being unloaded from memory.
* Use iJIT_Method_Load as event data.*/
/** @endcond */
iJVM_EVENT_TYPE_METHOD_UPDATE, /**<\brief Send to provide new content for
* a previously reported dynamic code.
* The previous content will be invalidated
* starting from the time of the notification.
* Use iJIT_Method_Load as event data but
* required fields are following:
* - method_id identify the code to update.
* - method_load_address specify start address
* within identified code range
* where update should be started.
* - method_size specify length of updated code
* range. */
iJVM_EVENT_TYPE_METHOD_INLINE_LOAD_FINISHED, /**<\brief Send when an inline dynamic
* code is JIT compiled and loaded
* into memory by the JIT engine,
* but before the parent code region
* starts executing.
* Use iJIT_Method_Inline_Load as event data.*/
/** @cond exclude_from_documentation */
iJVM_EVENT_TYPE_METHOD_UPDATE_V2,
/** @endcond */
iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED_V2 = 21, /**<\brief Send when a dynamic code is
* JIT compiled and loaded into
* memory by the JIT engine, but
* before the code is executed.
* Use iJIT_Method_Load_V2 as event data. */
iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED_V3 /**<\brief Send when a dynamic code is
* JIT compiled and loaded into
* memory by the JIT engine, but
* before the code is executed.
* Use iJIT_Method_Load_V3 as event data. */
} iJIT_JVM_EVENT;
/**
* @brief Enumerator for the agent's mode
*/
typedef enum _iJIT_IsProfilingActiveFlags
{
iJIT_NOTHING_RUNNING = 0x0000, /**<\brief The agent is not running;
* iJIT_NotifyEvent calls will
* not be processed. */
iJIT_SAMPLING_ON = 0x0001, /**<\brief The agent is running and
* ready to process notifications. */
} iJIT_IsProfilingActiveFlags;
/**
* @brief Description of a single entry in the line number information of a code region.
* @details A table of line number entries gives information about how the reported code region
* is mapped to source file.
* Intel(R) VTune(TM) Amplifier uses line number information to attribute
* the samples (virtual address) to a line number. \n
* It is acceptable to report different code addresses for the same source line:
* @code
* Offset LineNumber
* 1 2
* 12 4
* 15 2
* 18 1
* 21 30
*
* VTune Amplifier constructs the following table using the client data
*
* Code subrange Line number
* 0-1 2
* 1-12 4
* 12-15 2
* 15-18 1
* 18-21 30
* @endcode
*/
typedef struct _LineNumberInfo
{
unsigned int Offset; /**<\brief Offset from the beginning of the code region. */
unsigned int LineNumber; /**<\brief Matching source line number offset (from beginning of source file). */
} *pLineNumberInfo, LineNumberInfo;
/**
* @brief Enumerator for the code architecture.
*/
typedef enum _iJIT_CodeArchitecture
{
iJIT_CA_NATIVE = 0, /**<\brief Native to the process architecture that is calling it. */
iJIT_CA_32, /**<\brief 32-bit machine code. */
iJIT_CA_64 /**<\brief 64-bit machine code. */
} iJIT_CodeArchitecture;
#pragma pack(push, 8)
/**
* @brief Description of a JIT-compiled method
* @details When you use the iJIT_Method_Load structure to describe
* the JIT compiled method, use iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED
* as an event type to report it.
*/
typedef struct _iJIT_Method_Load
{
unsigned int method_id; /**<\brief Unique method ID. Cannot be 0.
* You must either use the API function
* iJIT_GetNewMethodID to get a valid and unique
* method ID, or else manage ID uniqueness
* and correct range by yourself.\n
* You must use the same method ID for all code
* regions of the same method, otherwise different
* method IDs specify different methods. */
char* method_name; /**<\brief The name of the method. It can be optionally
* prefixed with its class name and appended with
* its complete signature. Can't be NULL. */
void* method_load_address; /**<\brief The start virtual address of the method code
* region. If NULL, data provided with
* event are not accepted. */
unsigned int method_size; /**<\brief The code size of the method in memory.
* If 0, then data provided with the event are not
* accepted. */
unsigned int line_number_size; /**<\brief The number of entries in the line number
* table.0 if none. */
pLineNumberInfo line_number_table; /**<\brief Pointer to the line numbers info
* array. Can be NULL if
* line_number_size is 0. See
* LineNumberInfo Structure for a
* description of a single entry in
* the line number info array */
unsigned int class_id; /**<\brief This field is obsolete. */
char* class_file_name; /**<\brief Class name. Can be NULL.*/
char* source_file_name; /**<\brief Source file name. Can be NULL.*/
} *piJIT_Method_Load, iJIT_Method_Load;
/**
* @brief Description of a JIT-compiled method
* @details When you use the iJIT_Method_Load_V2 structure to describe
* the JIT compiled method, use iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED_V2
* as an event type to report it.
*/
typedef struct _iJIT_Method_Load_V2
{
unsigned int method_id; /**<\brief Unique method ID. Cannot be 0.
* You must either use the API function
* iJIT_GetNewMethodID to get a valid and unique
* method ID, or else manage ID uniqueness
* and correct range by yourself.\n
* You must use the same method ID for all code
* regions of the same method, otherwise different
* method IDs specify different methods. */
char* method_name; /**<\brief The name of the method. It can be optionally
* prefixed with its class name and appended with
* its complete signature. Can't be NULL. */
void* method_load_address; /**<\brief The start virtual address of the method code
* region. If NULL, then data provided with the
* event are not accepted. */
unsigned int method_size; /**<\brief The code size of the method in memory.
* If 0, then data provided with the event are not
* accepted. */
unsigned int line_number_size; /**<\brief The number of entries in the line number
* table. 0 if none. */
pLineNumberInfo line_number_table; /**<\brief Pointer to the line numbers info
* array. Can be NULL if
* line_number_size is 0. See
* LineNumberInfo Structure for a
* description of a single entry in
* the line number info array. */
char* class_file_name; /**<\brief Class name. Can be NULL. */
char* source_file_name; /**<\brief Source file name. Can be NULL. */
char* module_name; /**<\brief Module name. Can be NULL.
The module name can be useful for distinguishing among
different JIT engines. VTune Amplifier will display
reported methods grouped by specific module. */
} *piJIT_Method_Load_V2, iJIT_Method_Load_V2;
/**
* @brief Description of a JIT-compiled method
* @details The iJIT_Method_Load_V3 structure is the same as iJIT_Method_Load_V2
* with a newly introduced 'arch' field that specifies architecture of the code region.
* When you use the iJIT_Method_Load_V3 structure to describe
* the JIT compiled method, use iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED_V3
* as an event type to report it.
*/
typedef struct _iJIT_Method_Load_V3
{
unsigned int method_id; /**<\brief Unique method ID. Cannot be 0.
* You must either use the API function
* iJIT_GetNewMethodID to get a valid and unique
* method ID, or manage ID uniqueness
* and correct range by yourself.\n
* You must use the same method ID for all code
* regions of the same method, otherwise they are
* treated as regions of different methods. */
char* method_name; /**<\brief The name of the method. It can be optionally
* prefixed with its class name and appended with
* its complete signature. Cannot be NULL. */
void* method_load_address; /**<\brief The start virtual address of the method code
* region. If NULL, then data provided with the
* event are not accepted. */
unsigned int method_size; /**<\brief The code size of the method in memory.
* If 0, then data provided with the event are not
* accepted. */
unsigned int line_number_size; /**<\brief The number of entries in the line number
* table. 0 if none. */
pLineNumberInfo line_number_table; /**<\brief Pointer to the line numbers info
* array. Can be NULL if
* line_number_size is 0. See
* LineNumberInfo Structure for a
* description of a single entry in
* the line number info array. */
char* class_file_name; /**<\brief Class name. Can be NULL. */
char* source_file_name; /**<\brief Source file name. Can be NULL. */
char* module_name; /**<\brief Module name. Can be NULL.
* The module name can be useful for distinguishing among
* different JIT engines. VTune Amplifier will display
* reported methods grouped by specific module. */
iJIT_CodeArchitecture module_arch; /**<\brief Architecture of the method's code region.
* By default, it is the same as the process
* architecture that is calling it.
* For example, you can use it if your 32-bit JIT
* engine generates 64-bit code.
*
* If JIT engine reports both 32-bit and 64-bit types
* of methods then VTune Amplifier splits the methods
* with the same module name but with different
* architectures in two different modules. VTune Amplifier
* modifies the original name provided with a 64-bit method
* version by ending it with '(64)' */
} *piJIT_Method_Load_V3, iJIT_Method_Load_V3;
/**
* @brief Description of an inline JIT-compiled method
* @details When you use the_iJIT_Method_Inline_Load structure to describe
* the JIT compiled method, use iJVM_EVENT_TYPE_METHOD_INLINE_LOAD_FINISHED
* as an event type to report it.
*/
typedef struct _iJIT_Method_Inline_Load
{
unsigned int method_id; /**<\brief Unique method ID. Cannot be 0.
* You must either use the API function
* iJIT_GetNewMethodID to get a valid and unique
* method ID, or else manage ID uniqueness
* and correct range by yourself. */
unsigned int parent_method_id; /**<\brief Unique immediate parent's method ID.
* Cannot be 0.
* You must either use the API function
* iJIT_GetNewMethodID to get a valid and unique
* method ID, or else manage ID uniqueness
* and correct range by yourself. */
char* method_name; /**<\brief The name of the method. It can be optionally
* prefixed with its class name and appended with
* its complete signature. Can't be NULL. */
void* method_load_address; /** <\brief The virtual address on which the method
* is inlined. If NULL, then data provided with
* the event are not accepted. */
unsigned int method_size; /**<\brief The code size of the method in memory.
* If 0, then data provided with the event are not
* accepted. */
unsigned int line_number_size; /**<\brief The number of entries in the line number
* table. 0 if none. */
pLineNumberInfo line_number_table; /**<\brief Pointer to the line numbers info
* array. Can be NULL if
* line_number_size is 0. See
* LineNumberInfo Structure for a
* description of a single entry in
* the line number info array */
char* class_file_name; /**<\brief Class name. Can be NULL.*/
char* source_file_name; /**<\brief Source file name. Can be NULL.*/
} *piJIT_Method_Inline_Load, iJIT_Method_Inline_Load;
/** @cond exclude_from_documentation */
/**
* @brief Description of a segment type
* @details Use the segment type to specify a type of data supplied
* with the iJVM_EVENT_TYPE_METHOD_UPDATE_V2 event to be applied to
* a certain code trace.
*/
typedef enum _iJIT_SegmentType
{
iJIT_CT_UNKNOWN = 0,
iJIT_CT_CODE, /**<\brief Executable code. */
iJIT_CT_DATA, /**<\brief Data (not executable code).
* VTune Amplifier uses the format string
* (see iJIT_Method_Update) to represent
* this data in the VTune Amplifier GUI */
iJIT_CT_KEEP, /**<\brief Use the previous markup for the trace.
* Can be used for the following
* iJVM_EVENT_TYPE_METHOD_UPDATE_V2 events,
* if the type of the previously reported segment
* type is the same. */
iJIT_CT_EOF
} iJIT_SegmentType;
/**
* @brief Description of a dynamic update of the content within JIT-compiled method
* @details The JIT engine may generate the methods that are updated at runtime
* partially by mixed (data + executable code) content. When you use the iJIT_Method_Update
* structure to describe the update of the content within a JIT-compiled method,
* use iJVM_EVENT_TYPE_METHOD_UPDATE_V2 as an event type to report it.
*
* On the first Update event, VTune Amplifier copies the original code range reported by
* the iJVM_EVENT_TYPE_METHOD_LOAD event, then modifies it with the supplied bytes and
* adds the modified range to the original method. For next update events, VTune Amplifier
* does the same but it uses the latest modified version of a code region for update.
* Eventually, VTune Amplifier GUI displays multiple code ranges for the method reported by
* the iJVM_EVENT_TYPE_METHOD_LOAD event.
* Notes:
* - Multiple update events with different types for the same trace are allowed
* but they must be reported for the same code ranges.
* Example,
* @code
* [-- data---] Allowed
* [-- code --] Allowed
* [code] Ignored
* [-- data---] Allowed
* [-- code --] Allowed
* [------------ trace ---------]
* @endcode
* - The types of previously reported events can be changed but they must be reported
* for the same code ranges.
* Example,
* @code
* [-- data---] Allowed
* [-- code --] Allowed
* [-- data---] Allowed
* [-- code --] Allowed
* [------------ trace ---------]
* @endcode
*/
typedef struct _iJIT_Method_Update
{
void* load_address; /**<\brief Start address of the update within a method */
unsigned int size; /**<\brief The update size */
iJIT_SegmentType type; /**<\brief Type of the update */
const char* data_format; /**<\brief C string that contains a format string
* that follows the same specifications as format in printf.
* The format string is used for iJIT_CT_CODE only
* and cannot be NULL.
* Format can be changed on the fly. */
} *piJIT_Method_Update, iJIT_Method_Update;
/** @endcond */
#pragma pack(pop)
/** @cond exclude_from_documentation */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#ifndef JITAPI_CDECL
# if defined WIN32 || defined _WIN32
# define JITAPI_CDECL __cdecl
# else /* defined WIN32 || defined _WIN32 */
# if defined _M_IX86 || defined __i386__
# define JITAPI_CDECL __attribute__ ((cdecl))
# else /* _M_IX86 || __i386__ */
# define JITAPI_CDECL /* actual only on x86_64 platform */
# endif /* _M_IX86 || __i386__ */
# endif /* defined WIN32 || defined _WIN32 */
#endif /* JITAPI_CDECL */
#define JITAPI JITAPI_CDECL
/** @endcond */
/**
* @brief Generates a new unique method ID.
*
* You must use this API to obtain unique and valid method IDs for methods or
* traces reported to the agent if you don't have your own mechanism to generate
* unique method IDs.
*
* @return a new unique method ID. When out of unique method IDs, this API
* returns 0, which is not an accepted value.
*/
unsigned int JITAPI iJIT_GetNewMethodID(void);
/**
* @brief Returns the current mode of the agent.
*
* @return iJIT_SAMPLING_ON, indicating that agent is running, or
* iJIT_NOTHING_RUNNING if no agent is running.
*/
iJIT_IsProfilingActiveFlags JITAPI iJIT_IsProfilingActive(void);
/**
* @brief Reports information about JIT-compiled code to the agent.
*
* The reported information is used to attribute samples obtained from any
* Intel(R) VTune(TM) Amplifier collector. This API needs to be called
* after JIT compilation and before the first entry into the JIT-compiled
* code.
*
* @param[in] event_type - type of the data sent to the agent
* @param[in] EventSpecificData - pointer to event-specific data
*
* @returns 1 on success, otherwise 0.
*/
int JITAPI iJIT_NotifyEvent(iJIT_JVM_EVENT event_type, void *EventSpecificData);
#ifdef __cplusplus
}
#endif /* __cplusplus */
/** @endcond */
/** @} jitapi group */
#endif /* __JITPROFILING_H__ */

View file

@ -1,121 +0,0 @@
/*
+----------------------------------------------------------------------+
| Zend JIT |
+----------------------------------------------------------------------+
| Copyright (c) The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| https://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: Dmitry Stogov <dmitry@php.net> |
| Xinchen Hui <laruence@php.net> |
+----------------------------------------------------------------------+
*/
#include <sys/types.h>
#include <sys/stat.h>
#if defined(__FreeBSD__) || defined(__DragonFly__)
#include <sys/sysctl.h>
#elif defined(__HAIKU__)
#include <FindDirectory.h>
#endif
#include <fcntl.h>
#include <unistd.h>
#include "zend_API.h"
#include "zend_elf.h"
static void* zend_elf_read_sect(int fd, zend_elf_sectheader *sect)
{
void *s = emalloc(sect->size);
if (lseek(fd, sect->ofs, SEEK_SET) < 0) {
efree(s);
return NULL;
}
if (read(fd, s, sect->size) != (ssize_t)sect->size) {
efree(s);
return NULL;
}
return s;
}
void zend_elf_load_symbols(void)
{
zend_elf_header hdr;
zend_elf_sectheader sect;
int i;
#if defined(__linux__)
int fd = open("/proc/self/exe", O_RDONLY);
#elif defined(__NetBSD__)
int fd = open("/proc/curproc/exe", O_RDONLY);
#elif defined(__FreeBSD__) || defined(__DragonFly__)
char path[PATH_MAX];
size_t pathlen = sizeof(path);
int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
if (sysctl(mib, 4, path, &pathlen, NULL, 0) == -1) {
return;
}
int fd = open(path, O_RDONLY);
#elif defined(__sun)
int fd = open("/proc/self/path/a.out", O_RDONLY);
#elif defined(__HAIKU__)
char path[PATH_MAX];
if (find_path(B_APP_IMAGE_SYMBOL, B_FIND_PATH_IMAGE_PATH,
NULL, path, sizeof(path)) != B_OK) {
return;
}
int fd = open(path, O_RDONLY);
#else
// To complete eventually for other ELF platforms.
// Otherwise APPLE is Mach-O
int fd = -1;
#endif
if (fd >= 0) {
if (read(fd, &hdr, sizeof(hdr)) == sizeof(hdr)
&& hdr.emagic[0] == '\177'
&& hdr.emagic[1] == 'E'
&& hdr.emagic[2] == 'L'
&& hdr.emagic[3] == 'F'
&& lseek(fd, hdr.shofs, SEEK_SET) >= 0) {
for (i = 0; i < hdr.shnum; i++) {
if (read(fd, &sect, sizeof(sect)) == sizeof(sect)
&& sect.type == ELFSECT_TYPE_SYMTAB) {
uint32_t n, count = sect.size / sizeof(zend_elf_symbol);
zend_elf_symbol *syms = zend_elf_read_sect(fd, &sect);
char *str_tbl;
if (syms) {
if (lseek(fd, hdr.shofs + sect.link * sizeof(sect), SEEK_SET) >= 0
&& read(fd, &sect, sizeof(sect)) == sizeof(sect)
&& (str_tbl = (char*)zend_elf_read_sect(fd, &sect)) != NULL) {
for (n = 0; n < count; n++) {
if (syms[n].name
&& (ELFSYM_TYPE(syms[n].info) == ELFSYM_TYPE_FUNC
/*|| ELFSYM_TYPE(syms[n].info) == ELFSYM_TYPE_DATA*/)
&& (ELFSYM_BIND(syms[n].info) == ELFSYM_BIND_LOCAL
/*|| ELFSYM_BIND(syms[n].info) == ELFSYM_BIND_GLOBAL*/)) {
zend_jit_disasm_add_symbol(str_tbl + syms[n].name, syms[n].value, syms[n].size);
}
}
efree(str_tbl);
}
efree(syms);
}
if (lseek(fd, hdr.shofs + (i + 1) * sizeof(sect), SEEK_SET) < 0) {
break;
}
}
}
}
close(fd);
}
}

View file

@ -1,115 +0,0 @@
/*
+----------------------------------------------------------------------+
| Zend JIT |
+----------------------------------------------------------------------+
| Copyright (c) The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| https://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: Dmitry Stogov <dmitry@php.net> |
| Xinchen Hui <laruence@php.net> |
+----------------------------------------------------------------------+
*/
#ifndef ZEND_ELF
#define ZEND_ELF
#if SIZEOF_SIZE_T == 8
# define ELF64
#else
# undef ELF64
#endif
typedef struct _zend_elf_header {
uint8_t emagic[4];
uint8_t eclass;
uint8_t eendian;
uint8_t eversion;
uint8_t eosabi;
uint8_t eabiversion;
uint8_t epad[7];
uint16_t type;
uint16_t machine;
uint32_t version;
uintptr_t entry;
uintptr_t phofs;
uintptr_t shofs;
uint32_t flags;
uint16_t ehsize;
uint16_t phentsize;
uint16_t phnum;
uint16_t shentsize;
uint16_t shnum;
uint16_t shstridx;
} zend_elf_header;
typedef struct zend_elf_sectheader {
uint32_t name;
uint32_t type;
uintptr_t flags;
uintptr_t addr;
uintptr_t ofs;
uintptr_t size;
uint32_t link;
uint32_t info;
uintptr_t align;
uintptr_t entsize;
} zend_elf_sectheader;
#define ELFSECT_IDX_ABS 0xfff1
enum {
ELFSECT_TYPE_PROGBITS = 1,
ELFSECT_TYPE_SYMTAB = 2,
ELFSECT_TYPE_STRTAB = 3,
ELFSECT_TYPE_NOBITS = 8,
ELFSECT_TYPE_DYNSYM = 11,
};
#define ELFSECT_FLAGS_WRITE (1 << 0)
#define ELFSECT_FLAGS_ALLOC (1 << 1)
#define ELFSECT_FLAGS_EXEC (1 << 2)
#define ELFSECT_FLAGS_TLS (1 << 10)
typedef struct zend_elf_symbol {
#ifdef ELF64
uint32_t name;
uint8_t info;
uint8_t other;
uint16_t sectidx;
uintptr_t value;
uint64_t size;
#else
uint32_t name;
uintptr_t value;
uint32_t size;
uint8_t info;
uint8_t other;
uint16_t sectidx;
#endif
} zend_elf_symbol;
#define ELFSYM_BIND(info) ((info) >> 4)
#define ELFSYM_TYPE(info) ((info) & 0xf)
#define ELFSYM_INFO(bind, type) (((bind) << 4) | (type))
enum {
ELFSYM_TYPE_DATA = 2,
ELFSYM_TYPE_FUNC = 2,
ELFSYM_TYPE_FILE = 4,
};
enum {
ELFSYM_BIND_LOCAL = 0,
ELFSYM_BIND_GLOBAL = 1,
};
void zend_elf_load_symbols(void);
#endif

File diff suppressed because it is too large Load diff

View file

@ -165,8 +165,6 @@ ZEND_EXT_API void zend_jit_deactivate(void);
ZEND_EXT_API void zend_jit_status(zval *ret); ZEND_EXT_API void zend_jit_status(zval *ret);
ZEND_EXT_API void zend_jit_restart(void); ZEND_EXT_API void zend_jit_restart(void);
#ifdef ZEND_JIT_IR
#define ZREG_LOAD (1<<0) #define ZREG_LOAD (1<<0)
#define ZREG_STORE (1<<1) #define ZREG_STORE (1<<1)
#define ZREG_LAST_USE (1<<2) #define ZREG_LAST_USE (1<<2)
@ -185,39 +183,4 @@ ZEND_EXT_API void zend_jit_restart(void);
#define ZREG_NONE -1 #define ZREG_NONE -1
#else
typedef struct _zend_lifetime_interval zend_lifetime_interval;
typedef struct _zend_life_range zend_life_range;
struct _zend_life_range {
uint32_t start;
uint32_t end;
zend_life_range *next;
};
#define ZREG_FLAGS_SHIFT 8
#define ZREG_STORE (1<<0)
#define ZREG_LOAD (1<<1)
#define ZREG_LAST_USE (1<<2)
#define ZREG_SPLIT (1<<3)
struct _zend_lifetime_interval {
int ssa_var;
union {
struct {
ZEND_ENDIAN_LOHI_3(
int8_t reg,
uint8_t flags,
uint16_t reserved
)};
uint32_t reg_flags;
};
zend_life_range range;
zend_lifetime_interval *hint;
zend_lifetime_interval *used_as_hint;
zend_lifetime_interval *list_next;
};
#endif
#endif /* HAVE_JIT_H */ #endif /* HAVE_JIT_H */

File diff suppressed because it is too large Load diff

View file

@ -1,157 +0,0 @@
/*
+----------------------------------------------------------------------+
| Zend JIT |
+----------------------------------------------------------------------+
| Copyright (c) The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| https://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: Dmitry Stogov <dmitry@php.net> |
| Hao Sun <hao.sun@arm.com> |
+----------------------------------------------------------------------+
*/
#ifndef HAVE_JIT_ARM64_H
#define HAVE_JIT_ARM64_H
typedef enum _zend_reg {
ZREG_NONE = -1,
ZREG_X0,
ZREG_X1,
ZREG_X2,
ZREG_X3,
ZREG_X4,
ZREG_X5,
ZREG_X6,
ZREG_X7,
ZREG_X8,
ZREG_X9,
ZREG_X10,
ZREG_X11,
ZREG_X12,
ZREG_X13,
ZREG_X14,
ZREG_X15,
ZREG_X16,
ZREG_X17,
ZREG_X18,
ZREG_X19,
ZREG_X20,
ZREG_X21,
ZREG_X22,
ZREG_X23,
ZREG_X24,
ZREG_X25,
ZREG_X26,
ZREG_X27,
ZREG_X28,
ZREG_X29,
ZREG_X30,
ZREG_X31,
ZREG_V0,
ZREG_V1,
ZREG_V2,
ZREG_V3,
ZREG_V4,
ZREG_V5,
ZREG_V6,
ZREG_V7,
ZREG_V8,
ZREG_V9,
ZREG_V10,
ZREG_V11,
ZREG_V12,
ZREG_V13,
ZREG_V14,
ZREG_V15,
ZREG_V16,
ZREG_V17,
ZREG_V18,
ZREG_V19,
ZREG_V20,
ZREG_V21,
ZREG_V22,
ZREG_V23,
ZREG_V24,
ZREG_V25,
ZREG_V26,
ZREG_V27,
ZREG_V28,
ZREG_V29,
ZREG_V30,
ZREG_V31,
ZREG_NUM,
ZREG_THIS, /* used for delayed FETCH_THIS deoptimization */
/* pseudo constants used by deoptimizer */
ZREG_LONG_MIN_MINUS_1,
ZREG_LONG_MIN,
ZREG_LONG_MAX,
ZREG_LONG_MAX_PLUS_1,
ZREG_NULL,
ZREG_ZVAL_TRY_ADDREF,
ZREG_ZVAL_COPY_GPR0,
} zend_reg;
typedef struct _zend_jit_registers_buf {
uint64_t gpr[32]; /* general purpose integer register */
double fpr[32]; /* floating point registers */
} zend_jit_registers_buf;
#define ZREG_RSP ZREG_X31
#define ZREG_RLR ZREG_X30
#define ZREG_RFP ZREG_X29
#define ZREG_RPR ZREG_X18
#define ZREG_FP ZREG_X27
#define ZREG_IP ZREG_X28
#define ZREG_RX ZREG_IP
#define ZREG_REG0 ZREG_X8
#define ZREG_REG1 ZREG_X9
#define ZREG_REG2 ZREG_X10
#define ZREG_FPR0 ZREG_V0
#define ZREG_FPR1 ZREG_V1
#define ZREG_TMP1 ZREG_X15
#define ZREG_TMP2 ZREG_X16
#define ZREG_TMP3 ZREG_X17
#define ZREG_FPTMP ZREG_V16
#define ZREG_COPY ZREG_REG0
#define ZREG_FIRST_FPR ZREG_V0
typedef uint64_t zend_regset;
#define ZEND_REGSET_64BIT 1
# define ZEND_REGSET_FIXED \
(ZEND_REGSET(ZREG_RSP) | ZEND_REGSET(ZREG_RLR) | ZEND_REGSET(ZREG_RFP) | \
ZEND_REGSET(ZREG_RPR) | ZEND_REGSET(ZREG_FP) | ZEND_REGSET(ZREG_IP) | \
ZEND_REGSET_INTERVAL(ZREG_TMP1, ZREG_TMP3) | ZEND_REGSET(ZREG_FPTMP))
# define ZEND_REGSET_GP \
ZEND_REGSET_DIFFERENCE(ZEND_REGSET_INTERVAL(ZREG_X0, ZREG_X30), ZEND_REGSET_FIXED)
# define ZEND_REGSET_FP \
ZEND_REGSET_DIFFERENCE(ZEND_REGSET_INTERVAL(ZREG_V0, ZREG_V31), ZEND_REGSET_FIXED)
# define ZEND_REGSET_SCRATCH \
(ZEND_REGSET_INTERVAL(ZREG_X0, ZREG_X17) | ZEND_REGSET_INTERVAL(ZREG_V0, ZREG_V7) | \
ZEND_REGSET_INTERVAL(ZREG_V16, ZREG_V31))
# define ZEND_REGSET_PRESERVED \
(ZEND_REGSET_INTERVAL(ZREG_X19, ZREG_X28) | ZEND_REGSET_INTERVAL(ZREG_V8, ZREG_V15))
#define ZEND_REGSET_LOW_PRIORITY \
(ZEND_REGSET(ZREG_REG0) | ZEND_REGSET(ZREG_REG1) | ZEND_REGSET(ZREG_FPR0) | ZEND_REGSET(ZREG_FPR1))
#endif /* ZEND_JIT_ARM64_H */

View file

@ -1,781 +0,0 @@
/*
+----------------------------------------------------------------------+
| Zend JIT |
+----------------------------------------------------------------------+
| Copyright (c) The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| https://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: Dmitry Stogov <dmitry@php.net> |
| Xinchen Hui <laruence@php.net> |
| Hao Sun <hao.sun@arm.com> |
+----------------------------------------------------------------------+
*/
#ifdef HAVE_CAPSTONE
# define HAVE_DISASM 1
# include <capstone.h>
# define HAVE_CAPSTONE_ITER 1
#elif ZEND_JIT_TARGET_X86
# define HAVE_DISASM 1
# define DISASM_INTEL_SYNTAX 0
# include "jit/libudis86/itab.c"
# include "jit/libudis86/decode.c"
# include "jit/libudis86/syn.c"
# if DISASM_INTEL_SYNTAX
# include "jit/libudis86/syn-intel.c"
# else
# include "jit/libudis86/syn-att.c"
# endif
# include "jit/libudis86/udis86.c"
#endif /* HAVE_CAPSTONE */
#ifdef HAVE_DISASM
static void zend_jit_disasm_add_symbol(const char *name,
uint64_t addr,
uint64_t size);
#ifndef _WIN32
# include "jit/zend_elf.c"
#endif
#include "zend_sort.h"
#ifndef _GNU_SOURCE
# define _GNU_SOURCE
#endif
#ifndef _WIN32
#include <dlfcn.h>
#endif
struct _sym_node {
uint64_t addr;
uint64_t end;
struct _sym_node *parent;
struct _sym_node *child[2];
unsigned char info;
char name[1];
};
static void zend_syms_rotateleft(zend_sym_node *p) {
zend_sym_node *r = p->child[1];
p->child[1] = r->child[0];
if (r->child[0]) {
r->child[0]->parent = p;
}
r->parent = p->parent;
if (p->parent == NULL) {
JIT_G(symbols) = r;
} else if (p->parent->child[0] == p) {
p->parent->child[0] = r;
} else {
p->parent->child[1] = r;
}
r->child[0] = p;
p->parent = r;
}
static void zend_syms_rotateright(zend_sym_node *p) {
zend_sym_node *l = p->child[0];
p->child[0] = l->child[1];
if (l->child[1]) {
l->child[1]->parent = p;
}
l->parent = p->parent;
if (p->parent == NULL) {
JIT_G(symbols) = l;
} else if (p->parent->child[1] == p) {
p->parent->child[1] = l;
} else {
p->parent->child[0] = l;
}
l->child[1] = p;
p->parent = l;
}
static void zend_jit_disasm_add_symbol(const char *name,
uint64_t addr,
uint64_t size)
{
zend_sym_node *sym;
size_t len = strlen(name);
sym = malloc(sizeof(zend_sym_node) + len + 1);
if (!sym) {
return;
}
sym->addr = addr;
sym->end = (addr + size - 1);
memcpy((char*)&sym->name, name, len + 1);
sym->parent = sym->child[0] = sym->child[1] = NULL;
sym->info = 1;
if (JIT_G(symbols)) {
zend_sym_node *node = JIT_G(symbols);
/* insert it into rbtree */
do {
if (sym->addr > node->addr) {
ZEND_ASSERT(sym->addr > (node->end));
if (node->child[1]) {
node = node->child[1];
} else {
node->child[1] = sym;
sym->parent = node;
break;
}
} else if (sym->addr < node->addr) {
if (node->child[0]) {
node = node->child[0];
} else {
node->child[0] = sym;
sym->parent = node;
break;
}
} else {
ZEND_ASSERT(sym->addr == node->addr);
if (strcmp(name, node->name) == 0 && sym->end < node->end) {
/* reduce size of the existing symbol */
node->end = sym->end;
}
free(sym);
return;
}
} while (1);
/* fix rbtree after instering */
while (sym && sym != JIT_G(symbols) && sym->parent->info == 1) {
if (sym->parent == sym->parent->parent->child[0]) {
node = sym->parent->parent->child[1];
if (node && node->info == 1) {
sym->parent->info = 0;
node->info = 0;
sym->parent->parent->info = 1;
sym = sym->parent->parent;
} else {
if (sym == sym->parent->child[1]) {
sym = sym->parent;
zend_syms_rotateleft(sym);
}
sym->parent->info = 0;
sym->parent->parent->info = 1;
zend_syms_rotateright(sym->parent->parent);
}
} else {
node = sym->parent->parent->child[0];
if (node && node->info == 1) {
sym->parent->info = 0;
node->info = 0;
sym->parent->parent->info = 1;
sym = sym->parent->parent;
} else {
if (sym == sym->parent->child[0]) {
sym = sym->parent;
zend_syms_rotateright(sym);
}
sym->parent->info = 0;
sym->parent->parent->info = 1;
zend_syms_rotateleft(sym->parent->parent);
}
}
}
} else {
JIT_G(symbols) = sym;
}
JIT_G(symbols)->info = 0;
}
static void zend_jit_disasm_destroy_symbols(zend_sym_node *n) {
if (n) {
if (n->child[0]) {
zend_jit_disasm_destroy_symbols(n->child[0]);
}
if (n->child[1]) {
zend_jit_disasm_destroy_symbols(n->child[1]);
}
free(n);
}
}
static const char* zend_jit_disasm_find_symbol(uint64_t addr,
int64_t *offset) {
zend_sym_node *node = JIT_G(symbols);
while (node) {
if (addr < node->addr) {
node = node->child[0];
} else if (addr > node->end) {
node = node->child[1];
} else {
*offset = addr - node->addr;
return node->name;
}
}
return NULL;
}
#ifdef HAVE_CAPSTONE
static uint64_t zend_jit_disasm_branch_target(csh cs, const cs_insn *insn)
{
unsigned int i;
#if ZEND_JIT_TARGET_X86
if (cs_insn_group(cs, insn, X86_GRP_JUMP)) {
for (i = 0; i < insn->detail->x86.op_count; i++) {
if (insn->detail->x86.operands[i].type == X86_OP_IMM) {
return insn->detail->x86.operands[i].imm;
}
}
}
#elif ZEND_JIT_TARGET_ARM64
if (cs_insn_group(cs, insn, ARM64_GRP_JUMP)
|| insn->id == ARM64_INS_BL
|| insn->id == ARM64_INS_ADR) {
for (i = 0; i < insn->detail->arm64.op_count; i++) {
if (insn->detail->arm64.operands[i].type == ARM64_OP_IMM)
return insn->detail->arm64.operands[i].imm;
}
}
#endif
return 0;
}
#endif
static const char* zend_jit_disasm_resolver(
#ifndef HAVE_CAPSTONE
struct ud *ud,
#endif
uint64_t addr,
int64_t *offset)
{
#ifndef _WIN32
# ifndef HAVE_CAPSTONE
((void)ud);
# endif
const char *name;
void *a = (void*)(uintptr_t)(addr);
Dl_info info;
name = zend_jit_disasm_find_symbol(addr, offset);
if (name) {
return name;
}
if (dladdr(a, &info)
&& info.dli_sname != NULL
&& info.dli_saddr == a) {
return info.dli_sname;
}
#else
const char *name;
name = zend_jit_disasm_find_symbol(addr, offset);
if (name) {
return name;
}
#endif
return NULL;
}
static int zend_jit_cmp_labels(Bucket *b1, Bucket *b2)
{
return ((b1->h > b2->h) > 0) ? 1 : -1;
}
static int zend_jit_disasm(const char *name,
const char *filename,
const zend_op_array *op_array,
zend_cfg *cfg,
const void *start,
size_t size)
{
const void *end = (void *)((char *)start + size);
zval zv, *z;
zend_long n, m;
HashTable labels;
uint64_t addr;
int b;
#ifdef HAVE_CAPSTONE
csh cs;
cs_insn *insn;
# ifdef HAVE_CAPSTONE_ITER
const uint8_t *cs_code;
size_t cs_size;
uint64_t cs_addr;
# else
size_t count, i;
# endif
const char *sym;
int64_t offset = 0;
char *p, *q, *r;
#else
struct ud ud;
const struct ud_operand *op;
#endif
#ifdef HAVE_CAPSTONE
# if ZEND_JIT_TARGET_X86
# if defined(__x86_64__) || defined(_WIN64)
if (cs_open(CS_ARCH_X86, CS_MODE_64, &cs) != CS_ERR_OK)
return 0;
# else
if (cs_open(CS_ARCH_X86, CS_MODE_32, &cs) != CS_ERR_OK)
return 0;
# endif
cs_option(cs, CS_OPT_DETAIL, CS_OPT_ON);
# if DISASM_INTEL_SYNTAX
cs_option(cs, CS_OPT_SYNTAX, CS_OPT_SYNTAX_INTEL);
# else
cs_option(cs, CS_OPT_SYNTAX, CS_OPT_SYNTAX_ATT);
# endif
# elif ZEND_JIT_TARGET_ARM64
if (cs_open(CS_ARCH_ARM64, CS_MODE_ARM, &cs) != CS_ERR_OK)
return 0;
cs_option(cs, CS_OPT_DETAIL, CS_OPT_ON);
cs_option(cs, CS_OPT_SYNTAX, CS_OPT_SYNTAX_ATT);
# endif
#else
ud_init(&ud);
# if defined(__x86_64__) || defined(_WIN64)
ud_set_mode(&ud, 64);
# else
ud_set_mode(&ud, 32);
# endif
# if DISASM_INTEL_SYNTAX
ud_set_syntax(&ud, UD_SYN_INTEL);
# else
ud_set_syntax(&ud, UD_SYN_ATT);
# endif
ud_set_sym_resolver(&ud, zend_jit_disasm_resolver);
#endif /* HAVE_CAPSTONE */
if (name) {
fprintf(stderr, "%s: ; (%s)\n", name, filename ? filename : "unknown");
}
#ifndef HAVE_CAPSTONE
ud_set_input_buffer(&ud, (uint8_t*)start, (uint8_t*)end - (uint8_t*)start);
ud_set_pc(&ud, (uint64_t)(uintptr_t)start);
#endif
zend_hash_init(&labels, 8, NULL, NULL, 0);
if (op_array && cfg) {
ZVAL_FALSE(&zv);
for (b = 0; b < cfg->blocks_count; b++) {
if (cfg->blocks[b].flags & (ZEND_BB_ENTRY|ZEND_BB_RECV_ENTRY)) {
addr = (uint64_t)(uintptr_t)op_array->opcodes[cfg->blocks[b].start].handler;
if (addr >= (uint64_t)(uintptr_t)start && addr < (uint64_t)(uintptr_t)end) {
zend_hash_index_add(&labels, addr, &zv);
}
}
}
}
#ifdef HAVE_CAPSTONE
ZVAL_TRUE(&zv);
# ifdef HAVE_CAPSTONE_ITER
cs_code = start;
cs_size = (uint8_t*)end - (uint8_t*)start;
cs_addr = (uint64_t)(uintptr_t)cs_code;
insn = cs_malloc(cs);
while (cs_disasm_iter(cs, &cs_code, &cs_size, &cs_addr, insn)) {
if ((addr = zend_jit_disasm_branch_target(cs, insn))) {
# else
count = cs_disasm(cs, start, (uint8_t*)end - (uint8_t*)start, (uintptr_t)start, 0, &insn);
for (i = 0; i < count; i++) {
if ((addr = zend_jit_disasm_branch_target(cs, &(insn[i])))) {
# endif
if (addr >= (uint64_t)(uintptr_t)start && addr < (uint64_t)(uintptr_t)end) {
zend_hash_index_add(&labels, addr, &zv);
}
}
}
#else
ZVAL_TRUE(&zv);
while (ud_disassemble(&ud)) {
op = ud_insn_opr(&ud, 0);
if (op && op->type == UD_OP_JIMM) {
addr = ud_syn_rel_target(&ud, (struct ud_operand*)op);
if (addr >= (uint64_t)(uintptr_t)start && addr < (uint64_t)(uintptr_t)end) {
zend_hash_index_add(&labels, addr, &zv);
}
}
}
#endif
zend_hash_sort(&labels, zend_jit_cmp_labels, 0);
/* label numbering */
n = 0; m = 0;
ZEND_HASH_MAP_FOREACH_VAL(&labels, z) {
if (Z_TYPE_P(z) == IS_FALSE) {
m--;
ZVAL_LONG(z, m);
} else {
n++;
ZVAL_LONG(z, n);
}
} ZEND_HASH_FOREACH_END();
#ifdef HAVE_CAPSTONE
# ifdef HAVE_CAPSTONE_ITER
cs_code = start;
cs_size = (uint8_t*)end - (uint8_t*)start;
cs_addr = (uint64_t)(uintptr_t)cs_code;
while (cs_disasm_iter(cs, &cs_code, &cs_size, &cs_addr, insn)) {
z = zend_hash_index_find(&labels, insn->address);
# else
for (i = 0; i < count; i++) {
z = zend_hash_index_find(&labels, insn[i].address);
# endif
if (z) {
if (Z_LVAL_P(z) < 0) {
fprintf(stderr, ".ENTRY" ZEND_LONG_FMT ":\n", -Z_LVAL_P(z));
} else {
fprintf(stderr, ".L" ZEND_LONG_FMT ":\n", Z_LVAL_P(z));
}
}
# ifdef HAVE_CAPSTONE_ITER
if (JIT_G(debug) & ZEND_JIT_DEBUG_ASM_ADDR) {
fprintf(stderr, " %" PRIx64 ":", insn->address);
}
fprintf(stderr, "\t%s ", insn->mnemonic);
p = insn->op_str;
# else
if (JIT_G(debug) & ZEND_JIT_DEBUG_ASM_ADDR) {
fprintf(stderr, " %" PRIx64 ":", insn[i].address);
}
fprintf(stderr, "\t%s ", insn[i].mnemonic);
p = insn[i].op_str;
# endif
/* Try to replace the target addresses with a symbols */
while ((q = strchr(p, 'x')) != NULL) {
if (p != q && *(q-1) == '0') {
r = q + 1;
addr = 0;
while (1) {
if (*r >= '0' && *r <= '9') {
addr = addr * 16 + (*r - '0');
} else if (*r >= 'A' && *r <= 'F') {
addr = addr * 16 + (*r - 'A' + 10);
} else if (*r >= 'a' && *r <= 'f') {
addr = addr * 16 + (*r - 'a' + 10);
} else {
break;
}
r++;
}
if (addr >= (uint64_t)(uintptr_t)start && addr < (uint64_t)(uintptr_t)end) {
if ((z = zend_hash_index_find(&labels, addr))) {
if (Z_LVAL_P(z) < 0) {
fwrite(p, 1, q - p - 1, stderr);
fprintf(stderr, ".ENTRY" ZEND_LONG_FMT, -Z_LVAL_P(z));
} else {
fwrite(p, 1, q - p - 1, stderr);
fprintf(stderr, ".L" ZEND_LONG_FMT, Z_LVAL_P(z));
}
} else {
fwrite(p, 1, r - p, stderr);
}
} else if ((sym = zend_jit_disasm_resolver(addr, &offset))) {
fwrite(p, 1, q - p - 1, stderr);
fputs(sym, stderr);
if (offset != 0) {
if (offset > 0) {
fprintf(stderr, "+%" PRIx64, offset);
} else {
fprintf(stderr, "-%" PRIx64, offset);
}
}
} else {
fwrite(p, 1, r - p, stderr);
}
p = r;
} else {
fwrite(p, 1, q - p + 1, stderr);
p = q + 1;
}
}
fprintf(stderr, "%s\n", p);
}
# ifdef HAVE_CAPSTONE_ITER
cs_free(insn, 1);
# else
cs_free(insn, count);
# endif
#else
ud_set_input_buffer(&ud, (uint8_t*)start, (uint8_t*)end - (uint8_t*)start);
ud_set_pc(&ud, (uint64_t)(uintptr_t)start);
while (ud_disassemble(&ud)) {
addr = ud_insn_off(&ud);
z = zend_hash_index_find(&labels, addr);
if (z) {
if (Z_LVAL_P(z) < 0) {
fprintf(stderr, ".ENTRY" ZEND_LONG_FMT ":\n", -Z_LVAL_P(z));
} else {
fprintf(stderr, ".L" ZEND_LONG_FMT ":\n", Z_LVAL_P(z));
}
}
op = ud_insn_opr(&ud, 0);
if (op && op->type == UD_OP_JIMM) {
addr = ud_syn_rel_target(&ud, (struct ud_operand*)op);
if (addr >= (uint64_t)(uintptr_t)start && addr < (uint64_t)(uintptr_t)end) {
z = zend_hash_index_find(&labels, addr);
if (z) {
const char *str = ud_insn_asm(&ud);
int len;
len = 0;
while (str[len] != 0 && str[len] != ' ' && str[len] != '\t') {
len++;
}
if (str[len] != 0) {
while (str[len] == ' ' || str[len] == '\t') {
len++;
}
if (Z_LVAL_P(z) < 0) {
fprintf(stderr, "\t%.*s.ENTRY" ZEND_LONG_FMT "\n", len, str, -Z_LVAL_P(z));
} else {
fprintf(stderr, "\t%.*s.L" ZEND_LONG_FMT "\n", len, str, Z_LVAL_P(z));
}
continue;
}
}
}
}
if (JIT_G(debug) & ZEND_JIT_DEBUG_ASM_ADDR) {
fprintf(stderr, " %" PRIx64 ":", ud_insn_off(&ud));
}
fprintf(stderr, "\t%s\n", ud_insn_asm(&ud));
}
#endif
fprintf(stderr, "\n");
zend_hash_destroy(&labels);
#ifdef HAVE_CAPSTONE
cs_close(&cs);
#endif
return 1;
}
static int zend_jit_disasm_init(void)
{
#ifndef ZTS
#define REGISTER_EG(n) \
zend_jit_disasm_add_symbol("EG("#n")", \
(uint64_t)(uintptr_t)&executor_globals.n, sizeof(executor_globals.n))
REGISTER_EG(uninitialized_zval);
REGISTER_EG(exception);
REGISTER_EG(vm_interrupt);
REGISTER_EG(exception_op);
REGISTER_EG(timed_out);
REGISTER_EG(current_execute_data);
REGISTER_EG(vm_stack_top);
REGISTER_EG(vm_stack_end);
REGISTER_EG(symbol_table);
REGISTER_EG(jit_trace_num);
#undef REGISTER_EG
#define REGISTER_CG(n) \
zend_jit_disasm_add_symbol("CG("#n")", \
(uint64_t)(uintptr_t)&compiler_globals.n, sizeof(compiler_globals.n))
REGISTER_CG(map_ptr_base);
#undef REGISTER_CG
#endif
/* Register JIT helper functions */
#define REGISTER_HELPER(n) \
zend_jit_disasm_add_symbol(#n, \
(uint64_t)(uintptr_t)n, sizeof(void*));
REGISTER_HELPER(memcmp);
REGISTER_HELPER(zend_jit_init_func_run_time_cache_helper);
REGISTER_HELPER(zend_jit_find_func_helper);
REGISTER_HELPER(zend_jit_find_ns_func_helper);
REGISTER_HELPER(zend_jit_find_method_helper);
REGISTER_HELPER(zend_jit_find_method_tmp_helper);
REGISTER_HELPER(zend_jit_push_static_metod_call_frame);
REGISTER_HELPER(zend_jit_push_static_metod_call_frame_tmp);
REGISTER_HELPER(zend_jit_invalid_method_call);
REGISTER_HELPER(zend_jit_invalid_method_call_tmp);
REGISTER_HELPER(zend_jit_unref_helper);
REGISTER_HELPER(zend_jit_extend_stack_helper);
REGISTER_HELPER(zend_jit_int_extend_stack_helper);
REGISTER_HELPER(zend_jit_leave_nested_func_helper);
REGISTER_HELPER(zend_jit_leave_top_func_helper);
REGISTER_HELPER(zend_jit_leave_func_helper);
REGISTER_HELPER(zend_jit_symtable_find);
REGISTER_HELPER(zend_jit_hash_index_lookup_rw_no_packed);
REGISTER_HELPER(zend_jit_hash_index_lookup_rw);
REGISTER_HELPER(zend_jit_hash_lookup_rw);
REGISTER_HELPER(zend_jit_symtable_lookup_rw);
REGISTER_HELPER(zend_jit_symtable_lookup_w);
REGISTER_HELPER(zend_jit_undefined_op_helper);
REGISTER_HELPER(zend_jit_fetch_dim_r_helper);
REGISTER_HELPER(zend_jit_fetch_dim_is_helper);
REGISTER_HELPER(zend_jit_fetch_dim_isset_helper);
REGISTER_HELPER(zend_jit_fetch_dim_str_offset_r_helper);
REGISTER_HELPER(zend_jit_fetch_dim_str_r_helper);
REGISTER_HELPER(zend_jit_fetch_dim_str_is_helper);
REGISTER_HELPER(zend_jit_fetch_dim_obj_r_helper);
REGISTER_HELPER(zend_jit_fetch_dim_obj_is_helper);
REGISTER_HELPER(zend_jit_fetch_dim_rw_helper);
REGISTER_HELPER(zend_jit_fetch_dim_w_helper);
REGISTER_HELPER(zend_jit_fetch_dim_obj_rw_helper);
REGISTER_HELPER(zend_jit_fetch_dim_obj_w_helper);
// REGISTER_HELPER(zend_jit_fetch_dim_obj_unset_helper);
REGISTER_HELPER(zend_jit_assign_dim_helper);
REGISTER_HELPER(zend_jit_assign_dim_op_helper);
REGISTER_HELPER(zend_jit_fast_assign_concat_helper);
REGISTER_HELPER(zend_jit_fast_concat_helper);
REGISTER_HELPER(zend_jit_fast_concat_tmp_helper);
REGISTER_HELPER(zend_jit_isset_dim_helper);
REGISTER_HELPER(zend_jit_free_call_frame);
REGISTER_HELPER(zend_jit_fetch_global_helper);
REGISTER_HELPER(zend_jit_verify_arg_slow);
REGISTER_HELPER(zend_jit_verify_return_slow);
REGISTER_HELPER(zend_jit_fetch_obj_r_slow);
REGISTER_HELPER(zend_jit_fetch_obj_r_dynamic);
REGISTER_HELPER(zend_jit_fetch_obj_is_slow);
REGISTER_HELPER(zend_jit_fetch_obj_is_dynamic);
REGISTER_HELPER(zend_jit_fetch_obj_w_slow);
REGISTER_HELPER(zend_jit_check_array_promotion);
REGISTER_HELPER(zend_jit_create_typed_ref);
REGISTER_HELPER(zend_jit_extract_helper);
REGISTER_HELPER(zend_jit_vm_stack_free_args_helper);
REGISTER_HELPER(zend_jit_copy_extra_args_helper);
REGISTER_HELPER(zend_jit_deprecated_helper);
REGISTER_HELPER(zend_jit_assign_const_to_typed_ref);
REGISTER_HELPER(zend_jit_assign_tmp_to_typed_ref);
REGISTER_HELPER(zend_jit_assign_var_to_typed_ref);
REGISTER_HELPER(zend_jit_assign_cv_to_typed_ref);
REGISTER_HELPER(zend_jit_assign_const_to_typed_ref2);
REGISTER_HELPER(zend_jit_assign_tmp_to_typed_ref2);
REGISTER_HELPER(zend_jit_assign_var_to_typed_ref2);
REGISTER_HELPER(zend_jit_assign_cv_to_typed_ref2);
REGISTER_HELPER(zend_jit_pre_inc_typed_ref);
REGISTER_HELPER(zend_jit_pre_dec_typed_ref);
REGISTER_HELPER(zend_jit_post_inc_typed_ref);
REGISTER_HELPER(zend_jit_post_dec_typed_ref);
REGISTER_HELPER(zend_jit_assign_op_to_typed_ref);
REGISTER_HELPER(zend_jit_assign_op_to_typed_ref_tmp);
REGISTER_HELPER(zend_jit_only_vars_by_reference);
REGISTER_HELPER(zend_jit_invalid_array_access);
REGISTER_HELPER(zend_jit_invalid_property_read);
REGISTER_HELPER(zend_jit_invalid_property_write);
REGISTER_HELPER(zend_jit_invalid_property_incdec);
REGISTER_HELPER(zend_jit_invalid_property_assign);
REGISTER_HELPER(zend_jit_invalid_property_assign_op);
REGISTER_HELPER(zend_jit_prepare_assign_dim_ref);
REGISTER_HELPER(zend_jit_pre_inc);
REGISTER_HELPER(zend_jit_pre_dec);
REGISTER_HELPER(zend_runtime_jit);
REGISTER_HELPER(zend_jit_hot_func);
REGISTER_HELPER(zend_jit_check_constant);
REGISTER_HELPER(zend_jit_get_constant);
REGISTER_HELPER(zend_jit_array_free);
REGISTER_HELPER(zend_jit_zval_array_dup);
REGISTER_HELPER(zend_jit_add_arrays_helper);
REGISTER_HELPER(zend_jit_assign_obj_helper);
REGISTER_HELPER(zend_jit_assign_obj_op_helper);
REGISTER_HELPER(zend_jit_assign_to_typed_prop);
REGISTER_HELPER(zend_jit_assign_op_to_typed_prop);
REGISTER_HELPER(zend_jit_inc_typed_prop);
REGISTER_HELPER(zend_jit_dec_typed_prop);
REGISTER_HELPER(zend_jit_pre_inc_typed_prop);
REGISTER_HELPER(zend_jit_pre_dec_typed_prop);
REGISTER_HELPER(zend_jit_post_inc_typed_prop);
REGISTER_HELPER(zend_jit_post_dec_typed_prop);
REGISTER_HELPER(zend_jit_pre_inc_obj_helper);
REGISTER_HELPER(zend_jit_pre_dec_obj_helper);
REGISTER_HELPER(zend_jit_post_inc_obj_helper);
REGISTER_HELPER(zend_jit_post_dec_obj_helper);
REGISTER_HELPER(zend_jit_rope_end);
REGISTER_HELPER(zend_jit_free_trampoline_helper);
REGISTER_HELPER(zend_jit_exception_in_interrupt_handler_helper);
#undef REGISTER_HELPER
#ifndef _WIN32
zend_elf_load_symbols();
#endif
if (zend_vm_kind() == ZEND_VM_KIND_HYBRID) {
zend_op opline;
memset(&opline, 0, sizeof(opline));
opline.opcode = ZEND_DO_UCALL;
opline.result_type = IS_UNUSED;
zend_vm_set_opcode_handler(&opline);
zend_jit_disasm_add_symbol("ZEND_DO_UCALL_SPEC_RETVAL_UNUSED_LABEL", (uint64_t)(uintptr_t)opline.handler, sizeof(void*));
opline.opcode = ZEND_DO_UCALL;
opline.result_type = IS_VAR;
zend_vm_set_opcode_handler(&opline);
zend_jit_disasm_add_symbol("ZEND_DO_UCALL_SPEC_RETVAL_USED_LABEL", (uint64_t)(uintptr_t)opline.handler, sizeof(void*));
opline.opcode = ZEND_DO_FCALL_BY_NAME;
opline.result_type = IS_UNUSED;
zend_vm_set_opcode_handler(&opline);
zend_jit_disasm_add_symbol("ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_UNUSED_LABEL", (uint64_t)(uintptr_t)opline.handler, sizeof(void*));
opline.opcode = ZEND_DO_FCALL_BY_NAME;
opline.result_type = IS_VAR;
zend_vm_set_opcode_handler(&opline);
zend_jit_disasm_add_symbol("ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_USED_LABEL", (uint64_t)(uintptr_t)opline.handler, sizeof(void*));
opline.opcode = ZEND_DO_FCALL;
opline.result_type = IS_UNUSED;
zend_vm_set_opcode_handler(&opline);
zend_jit_disasm_add_symbol("ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_LABEL", (uint64_t)(uintptr_t)opline.handler, sizeof(void*));
opline.opcode = ZEND_DO_FCALL;
opline.result_type = IS_VAR;
zend_vm_set_opcode_handler(&opline);
zend_jit_disasm_add_symbol("ZEND_DO_FCALL_SPEC_RETVAL_USED_LABEL", (uint64_t)(uintptr_t)opline.handler, sizeof(void*));
opline.opcode = ZEND_RETURN;
opline.op1_type = IS_CONST;
zend_vm_set_opcode_handler(&opline);
zend_jit_disasm_add_symbol("ZEND_RETURN_SPEC_CONST_LABEL", (uint64_t)(uintptr_t)opline.handler, sizeof(void*));
opline.opcode = ZEND_RETURN;
opline.op1_type = IS_TMP_VAR;
zend_vm_set_opcode_handler(&opline);
zend_jit_disasm_add_symbol("ZEND_RETURN_SPEC_TMP_LABEL", (uint64_t)(uintptr_t)opline.handler, sizeof(void*));
opline.opcode = ZEND_RETURN;
opline.op1_type = IS_VAR;
zend_vm_set_opcode_handler(&opline);
zend_jit_disasm_add_symbol("ZEND_RETURN_SPEC_VAR_LABEL", (uint64_t)(uintptr_t)opline.handler, sizeof(void*));
opline.opcode = ZEND_RETURN;
opline.op1_type = IS_CV;
zend_vm_set_opcode_handler(&opline);
zend_jit_disasm_add_symbol("ZEND_RETURN_SPEC_CV_LABEL", (uint64_t)(uintptr_t)opline.handler, sizeof(void*));
zend_jit_disasm_add_symbol("ZEND_HYBRID_HALT_LABEL", (uint64_t)(uintptr_t)zend_jit_halt_op->handler, sizeof(void*));
}
return 1;
}
static void zend_jit_disasm_shutdown(void)
{
if (JIT_G(symbols)) {
zend_jit_disasm_destroy_symbols(JIT_G(symbols));
JIT_G(symbols) = NULL;
}
}
#endif /* HAVE_DISASM */

View file

@ -1,522 +0,0 @@
/*
+----------------------------------------------------------------------+
| Zend JIT |
+----------------------------------------------------------------------+
| Copyright (c) The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| https://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: Dmitry Stogov <dmitry@php.net> |
| Xinchen Hui <laruence@php.net> |
+----------------------------------------------------------------------+
| Based on Mike Pall's implementation of GDB interface for LuaJIT. |
| LuaJIT -- a Just-In-Time Compiler for Lua. http://luajit.org/ |
+----------------------------------------------------------------------+
*/
#define HAVE_GDB
#include "zend_jit_gdb.h"
#include "zend_elf.h"
#include "zend_gdb.h"
/* DWARF definitions. */
#define DW_CIE_VERSION 1
/* CFA (Canonical frame address) */
enum {
DW_CFA_nop = 0x0,
DW_CFA_offset_extended = 0x5,
DW_CFA_def_cfa = 0xc,
DW_CFA_def_cfa_offset = 0xe,
DW_CFA_offset_extended_sf = 0x11,
DW_CFA_advance_loc = 0x40,
DW_CFA_offset = 0x80
};
enum {
DW_EH_PE_udata4 = 0x03,
DW_EH_PE_textrel = 0x20
};
enum {
DW_TAG_compile_unit = 0x11
};
enum {
DW_children_no = 0,
DW_children_yes = 1
};
enum {
DW_AT_name = 0x03,
DW_AT_stmt_list = 0x10,
DW_AT_low_pc = 0x11,
DW_AT_high_pc = 0x12
};
enum {
DW_FORM_addr = 0x01,
DW_FORM_data4 = 0x06,
DW_FORM_string = 0x08
};
enum {
DW_LNS_extended_op = 0,
DW_LNS_copy = 1,
DW_LNS_advance_pc = 2,
DW_LNS_advance_line = 3
};
enum {
DW_LNE_end_sequence = 1,
DW_LNE_set_address = 2
};
enum {
#if defined(__i386__)
DW_REG_AX, DW_REG_CX, DW_REG_DX, DW_REG_BX,
DW_REG_SP, DW_REG_BP, DW_REG_SI, DW_REG_DI,
DW_REG_RA,
#elif defined(__x86_64__)
/* Yes, the order is strange, but correct. */
DW_REG_AX, DW_REG_DX, DW_REG_CX, DW_REG_BX,
DW_REG_SI, DW_REG_DI, DW_REG_BP, DW_REG_SP,
DW_REG_8, DW_REG_9, DW_REG_10, DW_REG_11,
DW_REG_12, DW_REG_13, DW_REG_14, DW_REG_15,
DW_REG_RA,
#elif defined(__aarch64__)
DW_REG_SP = 31,
DW_REG_RA = 30,
DW_REG_X29 = 29,
#else
#error "Unsupported target architecture"
#endif
};
enum {
GDBJIT_SECT_NULL,
GDBJIT_SECT_text,
GDBJIT_SECT_eh_frame,
GDBJIT_SECT_shstrtab,
GDBJIT_SECT_strtab,
GDBJIT_SECT_symtab,
GDBJIT_SECT_debug_info,
GDBJIT_SECT_debug_abbrev,
GDBJIT_SECT_debug_line,
GDBJIT_SECT__MAX
};
enum {
GDBJIT_SYM_UNDEF,
GDBJIT_SYM_FILE,
GDBJIT_SYM_FUNC,
GDBJIT_SYM__MAX
};
typedef struct _zend_gdbjit_obj {
zend_elf_header hdr;
zend_elf_sectheader sect[GDBJIT_SECT__MAX];
zend_elf_symbol sym[GDBJIT_SYM__MAX];
uint8_t space[4096];
} zend_gdbjit_obj;
static const zend_elf_header zend_elfhdr_template = {
.emagic = { 0x7f, 'E', 'L', 'F' },
#ifdef ELF64
.eclass = 2,
#else
.eclass = 1,
#endif
#ifdef WORDS_BIGENDIAN
.eendian = 2,
#else
.eendian = 1,
#endif
.eversion = 1,
#if defined(Linux)
.eosabi = 0, /* Nope, it's not 3. ??? */
#elif defined(__FreeBSD__)
.eosabi = 9,
#elif defined(__OpenBSD__)
.eosabi = 12,
#elif defined(__NetBSD__)
.eosabi = 2,
#elif defined(__DragonFly__)
.eosabi = 0,
#elif (defined(__sun__) && defined(__svr4__))
.eosabi = 6,
#else
.eosabi = 0,
#endif
.eabiversion = 0,
.epad = { 0, 0, 0, 0, 0, 0, 0 },
.type = 1,
#if defined(__i386__)
.machine = 3,
#elif defined(__x86_64__)
.machine = 62,
#elif defined(__aarch64__)
.machine = 183,
#else
# error "Unsupported target architecture"
#endif
.version = 1,
.entry = 0,
.phofs = 0,
.shofs = offsetof(zend_gdbjit_obj, sect),
.flags = 0,
.ehsize = sizeof(zend_elf_header),
.phentsize = 0,
.phnum = 0,
.shentsize = sizeof(zend_elf_sectheader),
.shnum = GDBJIT_SECT__MAX,
.shstridx = GDBJIT_SECT_shstrtab
};
/* Context for generating the ELF object for the GDB JIT API. */
typedef struct _zend_gdbjit_ctx {
uint8_t *p; /* Pointer to next address in obj.space. */
uint8_t *startp; /* Pointer to start address in obj.space. */
uintptr_t mcaddr; /* Machine code address. */
uint32_t szmcode; /* Size of machine code. */
int32_t lineno; /* Starting line number. */
const char *name; /* JIT function name */
const char *filename; /* Starting file name. */
size_t objsize; /* Final size of ELF object. */
zend_gdbjit_obj obj; /* In-memory ELF object. */
} zend_gdbjit_ctx;
/* Add a zero-terminated string */
static uint32_t zend_gdbjit_strz(zend_gdbjit_ctx *ctx, const char *str)
{
uint8_t *p = ctx->p;
uint32_t ofs = (uint32_t)(p - ctx->startp);
do {
*p++ = (uint8_t)*str;
} while (*str++);
ctx->p = p;
return ofs;
}
/* Add a ULEB128 value */
static void zend_gdbjit_uleb128(zend_gdbjit_ctx *ctx, uint32_t v)
{
uint8_t *p = ctx->p;
for (; v >= 0x80; v >>= 7)
*p++ = (uint8_t)((v & 0x7f) | 0x80);
*p++ = (uint8_t)v;
ctx->p = p;
}
/* Add a SLEB128 value */
static void zend_gdbjit_sleb128(zend_gdbjit_ctx *ctx, int32_t v)
{
uint8_t *p = ctx->p;
for (; (uint32_t)(v+0x40) >= 0x80; v >>= 7)
*p++ = (uint8_t)((v & 0x7f) | 0x80);
*p++ = (uint8_t)(v & 0x7f);
ctx->p = p;
}
static void zend_gdbjit_secthdr(zend_gdbjit_ctx *ctx)
{
zend_elf_sectheader *sect;
*ctx->p++ = '\0';
#define SECTDEF(id, tp, al) \
sect = &ctx->obj.sect[GDBJIT_SECT_##id]; \
sect->name = zend_gdbjit_strz(ctx, "." #id); \
sect->type = ELFSECT_TYPE_##tp; \
sect->align = (al)
SECTDEF(text, NOBITS, 16);
sect->flags = ELFSECT_FLAGS_ALLOC|ELFSECT_FLAGS_EXEC;
sect->addr = ctx->mcaddr;
sect->ofs = 0;
sect->size = ctx->szmcode;
SECTDEF(eh_frame, PROGBITS, sizeof(uintptr_t));
sect->flags = ELFSECT_FLAGS_ALLOC;
SECTDEF(shstrtab, STRTAB, 1);
SECTDEF(strtab, STRTAB, 1);
SECTDEF(symtab, SYMTAB, sizeof(uintptr_t));
sect->ofs = offsetof(zend_gdbjit_obj, sym);
sect->size = sizeof(ctx->obj.sym);
sect->link = GDBJIT_SECT_strtab;
sect->entsize = sizeof(zend_elf_symbol);
sect->info = GDBJIT_SYM_FUNC;
SECTDEF(debug_info, PROGBITS, 1);
SECTDEF(debug_abbrev, PROGBITS, 1);
SECTDEF(debug_line, PROGBITS, 1);
#undef SECTDEF
}
static void zend_gdbjit_symtab(zend_gdbjit_ctx *ctx)
{
zend_elf_symbol *sym;
*ctx->p++ = '\0';
sym = &ctx->obj.sym[GDBJIT_SYM_FILE];
sym->name = zend_gdbjit_strz(ctx, "JIT code");
sym->sectidx = ELFSECT_IDX_ABS;
sym->info = ELFSYM_INFO(ELFSYM_BIND_LOCAL, ELFSYM_TYPE_FILE);
sym = &ctx->obj.sym[GDBJIT_SYM_FUNC];
sym->name = zend_gdbjit_strz(ctx, ctx->name);
sym->sectidx = GDBJIT_SECT_text;
sym->value = 0;
sym->size = ctx->szmcode;
sym->info = ELFSYM_INFO(ELFSYM_BIND_GLOBAL, ELFSYM_TYPE_FUNC);
}
typedef ZEND_SET_ALIGNED(1, uint16_t unaligned_uint16_t);
typedef ZEND_SET_ALIGNED(1, uint32_t unaligned_uint32_t);
typedef ZEND_SET_ALIGNED(1, uintptr_t unaligned_uintptr_t);
#define SECTALIGN(p, a) \
((p) = (uint8_t *)(((uintptr_t)(p) + ((a)-1)) & ~(uintptr_t)((a)-1)))
/* Shortcuts to generate DWARF structures. */
#define DB(x) (*p++ = (x))
#define DI8(x) (*(int8_t *)p = (x), p++)
#define DU16(x) (*(unaligned_uint16_t *)p = (x), p += 2)
#define DU32(x) (*(unaligned_uint32_t *)p = (x), p += 4)
#define DADDR(x) (*(unaligned_uintptr_t *)p = (x), p += sizeof(uintptr_t))
#define DUV(x) (ctx->p = p, zend_gdbjit_uleb128(ctx, (x)), p = ctx->p)
#define DSV(x) (ctx->p = p, zend_gdbjit_sleb128(ctx, (x)), p = ctx->p)
#define DSTR(str) (ctx->p = p, zend_gdbjit_strz(ctx, (str)), p = ctx->p)
#define DALIGNNOP(s) while ((uintptr_t)p & ((s)-1)) *p++ = DW_CFA_nop
#define DSECT(name, stmt) \
{ unaligned_uint32_t *szp_##name = (uint32_t *)p; p += 4; stmt \
*szp_##name = (uint32_t)((p-(uint8_t *)szp_##name)-4); }
static void zend_gdbjit_ehframe(zend_gdbjit_ctx *ctx, uint32_t sp_offset, uint32_t sp_adjustment)
{
uint8_t *p = ctx->p;
uint8_t *framep = p;
/* DWARF EH CIE (Common Information Entry) */
DSECT(CIE,
DU32(0); /* CIE ID. */
DB(DW_CIE_VERSION); /* Version */
DSTR("zR"); /* Augmentation String. */
DUV(1); /* Code alignment factor. */
DSV(-(int32_t)sizeof(uintptr_t)); /* Data alignment factor. */
DB(DW_REG_RA); /* Return address register. */
DB(1); DB(DW_EH_PE_textrel|DW_EH_PE_udata4); /* Augmentation data. */
#if defined(__x86_64__) || defined(i386)
DB(DW_CFA_def_cfa); DUV(DW_REG_SP); DUV(sizeof(uintptr_t));
DB(DW_CFA_offset|DW_REG_RA); DUV(1);
#elif defined(__aarch64__)
DB(DW_CFA_def_cfa); DUV(DW_REG_SP); DUV(0);
#endif
DALIGNNOP(sizeof(uintptr_t));
)
/* DWARF EH FDE (Frame Description Entry). */
DSECT(FDE,
DU32((uint32_t)(p-framep)); /* Offset to CIE Pointer. */
DU32(0); /* Machine code offset relative to .text. */
DU32(ctx->szmcode); /* Machine code length. */
DB(0); /* Augmentation data. */
DB(DW_CFA_def_cfa_offset); DUV(sp_offset);
#if defined(__aarch64__)
if (sp_offset) {
if (sp_adjustment && sp_adjustment < sp_offset) {
DB(DW_CFA_offset|DW_REG_X29); DUV(sp_adjustment / sizeof(uintptr_t));
DB(DW_CFA_offset|DW_REG_RA); DUV((sp_adjustment / sizeof(uintptr_t)) - 1);
} else {
DB(DW_CFA_offset|DW_REG_X29); DUV(sp_offset / sizeof(uintptr_t));
DB(DW_CFA_offset|DW_REG_RA); DUV((sp_offset / sizeof(uintptr_t)) - 1);
}
}
#endif
if (sp_adjustment && sp_adjustment > sp_offset) {
DB(DW_CFA_advance_loc|1); DB(DW_CFA_def_cfa_offset); DUV(sp_adjustment);
#if defined(__aarch64__)
if (!sp_offset) {
DB(DW_CFA_offset|DW_REG_X29); DUV(sp_adjustment / sizeof(uintptr_t));
DB(DW_CFA_offset|DW_REG_RA); DUV((sp_adjustment / sizeof(uintptr_t)) - 1);
}
#endif
}
DALIGNNOP(sizeof(uintptr_t));
)
ctx->p = p;
}
static void zend_gdbjit_debuginfo(zend_gdbjit_ctx *ctx)
{
uint8_t *p = ctx->p;
DSECT(info,
DU16(2); /* DWARF version. */
DU32(0); /* Abbrev offset. */
DB(sizeof(uintptr_t)); /* Pointer size. */
DUV(1); /* Abbrev #1: DW_TAG_compile_unit. */
DSTR(ctx->filename); /* DW_AT_name. */
DADDR(ctx->mcaddr); /* DW_AT_low_pc. */
DADDR(ctx->mcaddr + ctx->szmcode); /* DW_AT_high_pc. */
DU32(0); /* DW_AT_stmt_list. */
);
ctx->p = p;
}
static void zend_gdbjit_debugabbrev(zend_gdbjit_ctx *ctx)
{
uint8_t *p = ctx->p;
/* Abbrev #1: DW_TAG_compile_unit. */
DUV(1);
DUV(DW_TAG_compile_unit);
DB(DW_children_no);
DUV(DW_AT_name);
DUV(DW_FORM_string);
DUV(DW_AT_low_pc);
DUV(DW_FORM_addr);
DUV(DW_AT_high_pc);
DUV(DW_FORM_addr);
DUV(DW_AT_stmt_list);
DUV(DW_FORM_data4);
DB(0);
DB(0);
ctx->p = p;
}
#define DLNE(op, s) (DB(DW_LNS_extended_op), DUV(1+(s)), DB((op)))
static void zend_gdbjit_debugline(zend_gdbjit_ctx *ctx)
{
uint8_t *p = ctx->p;
DSECT(line,
DU16(2); /* DWARF version. */
DSECT(header,
DB(1); /* Minimum instruction length. */
DB(1); /* is_stmt. */
DI8(0); /* Line base for special opcodes. */
DB(2); /* Line range for special opcodes. */
DB(3+1); /* Opcode base at DW_LNS_advance_line+1. */
DB(0); DB(1); DB(1); /* Standard opcode lengths. */
/* Directory table. */
DB(0);
/* File name table. */
DSTR(ctx->filename); DUV(0); DUV(0); DUV(0);
DB(0);
);
DLNE(DW_LNE_set_address, sizeof(uintptr_t));
DADDR(ctx->mcaddr);
if (ctx->lineno) (DB(DW_LNS_advance_line), DSV(ctx->lineno-1));
DB(DW_LNS_copy);
DB(DW_LNS_advance_pc); DUV(ctx->szmcode);
DLNE(DW_LNE_end_sequence, 0);
);
ctx->p = p;
}
#undef DLNE
/* Undef shortcuts. */
#undef DB
#undef DI8
#undef DU16
#undef DU32
#undef DADDR
#undef DUV
#undef DSV
#undef DSTR
#undef DALIGNNOP
#undef DSECT
typedef void (*zend_gdbjit_initf) (zend_gdbjit_ctx *ctx);
static void zend_gdbjit_initsect(zend_gdbjit_ctx *ctx, int sect)
{
ctx->startp = ctx->p;
ctx->obj.sect[sect].ofs = (uintptr_t)((char *)ctx->p - (char *)&ctx->obj);
}
static void zend_gdbjit_initsect_done(zend_gdbjit_ctx *ctx, int sect)
{
ctx->obj.sect[sect].size = (uintptr_t)(ctx->p - ctx->startp);
}
static void zend_gdbjit_buildobj(zend_gdbjit_ctx *ctx, uint32_t sp_offset, uint32_t sp_adjustment)
{
zend_gdbjit_obj *obj = &ctx->obj;
/* Fill in ELF header and clear structures. */
memcpy(&obj->hdr, &zend_elfhdr_template, sizeof(zend_elf_header));
memset(&obj->sect, 0, sizeof(zend_elf_sectheader) * GDBJIT_SECT__MAX);
memset(&obj->sym, 0, sizeof(zend_elf_symbol) * GDBJIT_SYM__MAX);
/* Initialize sections. */
ctx->p = obj->space;
zend_gdbjit_initsect(ctx, GDBJIT_SECT_shstrtab); zend_gdbjit_secthdr(ctx); zend_gdbjit_initsect_done(ctx, GDBJIT_SECT_shstrtab);
zend_gdbjit_initsect(ctx, GDBJIT_SECT_strtab); zend_gdbjit_symtab(ctx); zend_gdbjit_initsect_done(ctx, GDBJIT_SECT_strtab);
zend_gdbjit_initsect(ctx, GDBJIT_SECT_debug_info); zend_gdbjit_debuginfo(ctx); zend_gdbjit_initsect_done(ctx, GDBJIT_SECT_debug_info);
zend_gdbjit_initsect(ctx, GDBJIT_SECT_debug_abbrev); zend_gdbjit_debugabbrev(ctx); zend_gdbjit_initsect_done(ctx, GDBJIT_SECT_debug_abbrev);
zend_gdbjit_initsect(ctx, GDBJIT_SECT_debug_line); zend_gdbjit_debugline(ctx); zend_gdbjit_initsect_done(ctx, GDBJIT_SECT_debug_line);
SECTALIGN(ctx->p, sizeof(uintptr_t));
zend_gdbjit_initsect(ctx, GDBJIT_SECT_eh_frame); zend_gdbjit_ehframe(ctx, sp_offset, sp_adjustment); zend_gdbjit_initsect_done(ctx, GDBJIT_SECT_eh_frame);
ctx->objsize = (size_t)((char *)ctx->p - (char *)obj);
ZEND_ASSERT(ctx->objsize < sizeof(zend_gdbjit_obj));
}
int zend_jit_gdb_register(const char *name,
const zend_op_array *op_array,
const void *start,
size_t size,
uint32_t sp_offset,
uint32_t sp_adjustment)
{
zend_gdbjit_ctx ctx;
ctx.mcaddr = (uintptr_t)start;
ctx.szmcode = (uint32_t)size;
ctx.name = name;
ctx.filename = op_array ? ZSTR_VAL(op_array->filename) : "unknown";
ctx.lineno = op_array ? op_array->line_start : 0;
zend_gdbjit_buildobj(&ctx, sp_offset, sp_adjustment);
return zend_gdb_register_code(&ctx.obj, ctx.objsize);
}
int zend_jit_gdb_unregister(void)
{
zend_gdb_unregister_all();
return 1;
}
void zend_jit_gdb_init(void)
{
#if 0
/* This might enable registration of all JIT-ed code, but unfortunately,
* in case of many functions, this takes enormous time. */
if (zend_gdb_present()) {
JIT_G(debug) |= ZEND_JIT_DEBUG_GDB;
}
#endif
}

View file

@ -1,37 +0,0 @@
/*
+----------------------------------------------------------------------+
| Zend JIT |
+----------------------------------------------------------------------+
| Copyright (c) The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| https://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: Dmitry Stogov <dmitry@php.net> |
| Xinchen Hui <laruence@php.net> |
+----------------------------------------------------------------------+
*/
#ifndef HAVE_ZEND_JIT_GDB_H
#define HAVE_ZEND_JIT_GDB_H
#include "zend_compile.h"
#define HAVE_GDB
int zend_jit_gdb_register(const char *name,
const zend_op_array *op_array,
const void *start,
size_t size,
uint32_t sp_offset,
uint32_t sp_adjustment);
int zend_jit_gdb_unregister(void);
void zend_jit_gdb_init(void);
#endif /* HAVE_ZEND_JIT_GDB_H */

View file

@ -21,97 +21,6 @@
#ifndef ZEND_JIT_INTERNAL_H #ifndef ZEND_JIT_INTERNAL_H
#define ZEND_JIT_INTERNAL_H #define ZEND_JIT_INTERNAL_H
#ifndef ZEND_JIT_IR
#include "zend_bitset.h"
/* Register Set */
#define ZEND_REGSET_EMPTY 0
#define ZEND_REGSET_IS_EMPTY(regset) \
(regset == ZEND_REGSET_EMPTY)
#define ZEND_REGSET_IS_SINGLETON(regset) \
(regset && !(regset & (regset - 1)))
#if (!ZEND_REGSET_64BIT)
#define ZEND_REGSET(reg) \
(1u << (reg))
#else
#define ZEND_REGSET(reg) \
(1ull << (reg))
#endif
#if (!ZEND_REGSET_64BIT)
#define ZEND_REGSET_INTERVAL(reg1, reg2) \
(((1u << ((reg2) - (reg1) + 1)) - 1) << (reg1))
#else
#define ZEND_REGSET_INTERVAL(reg1, reg2) \
(((1ull << ((reg2) - (reg1) + 1)) - 1) << (reg1))
#endif
#define ZEND_REGSET_IN(regset, reg) \
(((regset) & ZEND_REGSET(reg)) != 0)
#define ZEND_REGSET_INCL(regset, reg) \
(regset) |= ZEND_REGSET(reg)
#define ZEND_REGSET_EXCL(regset, reg) \
(regset) &= ~ZEND_REGSET(reg)
#define ZEND_REGSET_UNION(set1, set2) \
((set1) | (set2))
#define ZEND_REGSET_INTERSECTION(set1, set2) \
((set1) & (set2))
#define ZEND_REGSET_DIFFERENCE(set1, set2) \
((set1) & ~(set2))
#if !defined(_WIN32)
# if (!ZEND_REGSET_64BIT)
# define ZEND_REGSET_FIRST(set) ((zend_reg)__builtin_ctz(set))
# define ZEND_REGSET_LAST(set) ((zend_reg)(__builtin_clz(set)^31))
# else
# define ZEND_REGSET_FIRST(set) ((zend_reg)__builtin_ctzll(set))
# define ZEND_REGSET_LAST(set) ((zend_reg)(__builtin_clzll(set)^63))
# endif
#else
# include <intrin.h>
uint32_t __inline __zend_jit_ctz(uint32_t value) {
DWORD trailing_zero = 0;
if (_BitScanForward(&trailing_zero, value)) {
return trailing_zero;
}
return 32;
}
uint32_t __inline __zend_jit_clz(uint32_t value) {
DWORD leading_zero = 0;
if (_BitScanReverse(&leading_zero, value)) {
return 31 - leading_zero;
}
return 32;
}
# define ZEND_REGSET_FIRST(set) ((zend_reg)__zend_jit_ctz(set))
# define ZEND_REGSET_LAST(set) ((zend_reg)(__zend_jit_clz(set)^31))
#endif
#define ZEND_REGSET_FOREACH(set, reg) \
do { \
zend_regset _tmp = (set); \
while (!ZEND_REGSET_IS_EMPTY(_tmp)) { \
zend_reg _reg = ZEND_REGSET_FIRST(_tmp); \
ZEND_REGSET_EXCL(_tmp, _reg); \
reg = _reg; \
#define ZEND_REGSET_FOREACH_END() \
} \
} while (0)
/* Register Names */
extern const char *zend_reg_name[];
#endif /* ZEND_JIT_IR */
/* Address Encoding */ /* Address Encoding */
typedef uintptr_t zend_jit_addr; typedef uintptr_t zend_jit_addr;
@ -140,58 +49,6 @@ typedef uintptr_t zend_jit_addr;
#define Z_OFFSET(addr) ((uint32_t)((addr)>>_ZEND_ADDR_OFFSET_SHIFT)) #define Z_OFFSET(addr) ((uint32_t)((addr)>>_ZEND_ADDR_OFFSET_SHIFT))
#define Z_REG(addr) ((zend_reg)(((addr)>>_ZEND_ADDR_REG_SHIFT) & _ZEND_ADDR_REG_MASK)) #define Z_REG(addr) ((zend_reg)(((addr)>>_ZEND_ADDR_REG_SHIFT) & _ZEND_ADDR_REG_MASK))
#ifndef ZEND_JIT_IR
#define _ZEND_ADDR_REG_STORE_BIT 8
#define _ZEND_ADDR_REG_LOAD_BIT 9
#define _ZEND_ADDR_REG_LAST_USE_BIT 10
#define Z_STORE(addr) ((zend_reg)(((addr)>>_ZEND_ADDR_REG_STORE_BIT) & 1))
#define Z_LOAD(addr) ((zend_reg)(((addr)>>_ZEND_ADDR_REG_LOAD_BIT) & 1))
#define Z_LAST_USE(addr) ((zend_reg)(((addr)>>_ZEND_ADDR_REG_LAST_USE_BIT) & 1))
#define OP_REG_EX(reg, store, load, last_use) \
((reg) | \
((store) ? (1 << (_ZEND_ADDR_REG_STORE_BIT-_ZEND_ADDR_REG_SHIFT)) : 0) | \
((load) ? (1 << (_ZEND_ADDR_REG_LOAD_BIT-_ZEND_ADDR_REG_SHIFT)) : 0) | \
((last_use) ? (1 << (_ZEND_ADDR_REG_LAST_USE_BIT-_ZEND_ADDR_REG_SHIFT)) : 0) \
)
#define OP_REG(ssa_op, op) \
(ra && ssa_op->op >= 0 && ra[ssa_op->op] ? \
OP_REG_EX(ra[ssa_op->op]->reg, \
(ra[ssa_op->op]->flags & ZREG_STORE), \
(ra[ssa_op->op]->flags & ZREG_LOAD), \
zend_ival_is_last_use(ra[ssa_op->op], ssa_op - ssa->ops) \
) : ZREG_NONE)
static zend_always_inline zend_jit_addr _zend_jit_decode_op(uint8_t op_type, znode_op op, const zend_op *opline, zend_reg reg)
{
if (op_type == IS_CONST) {
#if ZEND_USE_ABS_CONST_ADDR
return ZEND_ADDR_CONST_ZVAL(op.zv);
#else
return ZEND_ADDR_CONST_ZVAL(RT_CONSTANT(opline, op));
#endif
} else {
ZEND_ASSERT(op_type & (IS_CV|IS_TMP_VAR|IS_VAR));
if (reg != ZREG_NONE) {
return ZEND_ADDR_REG(reg);
} else {
return ZEND_ADDR_MEM_ZVAL(ZREG_FP, op.var);
}
}
}
#define OP_ADDR(opline, type, op) \
_zend_jit_decode_op((opline)->type, (opline)->op, opline, ZREG_NONE)
#define OP_REG_ADDR(opline, type, _op, _ssa_op) \
_zend_jit_decode_op((opline)->type, (opline)->_op, opline, \
OP_REG(ssa_op, _ssa_op))
#else /* ZEND_JIT_IR */
#define ZEND_ADDR_REF_ZVAL(ref) \ #define ZEND_ADDR_REF_ZVAL(ref) \
((((zend_jit_addr)(uintptr_t)(ref)) << _ZEND_ADDR_REG_SHIFT) | \ ((((zend_jit_addr)(uintptr_t)(ref)) << _ZEND_ADDR_REG_SHIFT) | \
IS_REF_ZVAL) IS_REF_ZVAL)
@ -225,8 +82,6 @@ static zend_always_inline zend_jit_addr _zend_jit_decode_op(uint8_t op_type, zno
ZEND_ADDR_REG(ssa_op->_ssa_op) : \ ZEND_ADDR_REG(ssa_op->_ssa_op) : \
OP_ADDR(opline, type, op)) OP_ADDR(opline, type, op))
#endif /* ZEND_JIT_IR */
#define OP1_ADDR() \ #define OP1_ADDR() \
OP_ADDR(opline, op1_type, op1) OP_ADDR(opline, op1_type, op1)
#define OP2_ADDR() \ #define OP2_ADDR() \
@ -258,15 +113,10 @@ static zend_always_inline bool zend_jit_same_addr(zend_jit_addr addr1, zend_jit_
{ {
if (addr1 == addr2) { if (addr1 == addr2) {
return 1; return 1;
#ifndef ZEND_JIT_IR
} else if (Z_MODE(addr1) == IS_REG && Z_MODE(addr2) == IS_REG) {
return Z_REG(addr1) == Z_REG(addr2);
#else
} else if (Z_MODE(addr1) == IS_REG && Z_MODE(addr2) == IS_REG) { } else if (Z_MODE(addr1) == IS_REG && Z_MODE(addr2) == IS_REG) {
return Z_SSA_VAR(addr1) == Z_SSA_VAR(addr2); return Z_SSA_VAR(addr1) == Z_SSA_VAR(addr2);
} else if (Z_MODE(addr1) == IS_REF_ZVAL && Z_MODE(addr2) == IS_REF_ZVAL) { } else if (Z_MODE(addr1) == IS_REF_ZVAL && Z_MODE(addr2) == IS_REF_ZVAL) {
return Z_IR_REF(addr1) == Z_IR_REF(addr2); return Z_IR_REF(addr1) == Z_IR_REF(addr2);
#endif
} }
return 0; return 0;
} }
@ -569,36 +419,12 @@ typedef struct _zend_jit_trace_exit_info {
uint32_t flags; /* set of ZEND_JIT_EXIT_... */ uint32_t flags; /* set of ZEND_JIT_EXIT_... */
uint32_t stack_size; uint32_t stack_size;
uint32_t stack_offset; uint32_t stack_offset;
#ifdef ZEND_JIT_IR
int32_t poly_func_ref; int32_t poly_func_ref;
int32_t poly_this_ref; int32_t poly_this_ref;
int8_t poly_func_reg; int8_t poly_func_reg;
int8_t poly_this_reg; int8_t poly_this_reg;
#endif
} zend_jit_trace_exit_info; } zend_jit_trace_exit_info;
#ifndef ZEND_JIT_IR
typedef union _zend_jit_trace_stack {
int32_t ssa_var;
uint32_t info;
struct {
uint8_t type; /* variable type (for type inference) */
uint8_t mem_type; /* stack slot type (for eliminate dead type store) */
int8_t reg;
uint8_t flags;
};
} zend_jit_trace_stack;
#define STACK_VAR(_stack, _slot) \
(_stack)[_slot].ssa_var
#define SET_STACK_VAR(_stack, _slot, _ssa_var) do { \
(_stack)[_slot].ssa_var = _ssa_var; \
} while (0)
#define CLEAR_STACK_REF(_stack, _slot)
#else /* ZEND_JIT_IR */
typedef struct _zend_jit_trace_stack { typedef struct _zend_jit_trace_stack {
union { union {
uint32_t info; uint32_t info;
@ -633,8 +459,6 @@ typedef struct _zend_jit_trace_stack {
(_stack)[_slot].flags = _flags; \ (_stack)[_slot].flags = _flags; \
} while (0) } while (0)
#endif /* ZEND_JIT_IR */
#define STACK_INFO(_stack, _slot) \ #define STACK_INFO(_stack, _slot) \
(_stack)[_slot].info (_stack)[_slot].info
#define STACK_TYPE(_stack, _slot) \ #define STACK_TYPE(_stack, _slot) \
@ -675,12 +499,10 @@ typedef struct _zend_jit_trace_stack {
#define ZEND_JIT_TRACE_LOOP (1<<1) #define ZEND_JIT_TRACE_LOOP (1<<1)
#define ZEND_JIT_TRACE_USES_INITIAL_IP (1<<2) #define ZEND_JIT_TRACE_USES_INITIAL_IP (1<<2)
#ifdef ZEND_JIT_IR
typedef union _zend_jit_exit_const { typedef union _zend_jit_exit_const {
int64_t i; int64_t i;
double d; double d;
} zend_jit_exit_const; } zend_jit_exit_const;
#endif
typedef struct _zend_jit_trace_info { typedef struct _zend_jit_trace_info {
uint32_t id; /* trace id */ uint32_t id; /* trace id */
@ -701,10 +523,8 @@ typedef struct _zend_jit_trace_info {
zend_jit_trace_exit_info *exit_info; /* info about side exits */ zend_jit_trace_exit_info *exit_info; /* info about side exits */
zend_jit_trace_stack *stack_map; zend_jit_trace_stack *stack_map;
//uint32_t loop_offset; //uint32_t loop_offset;
#ifdef ZEND_JIT_IR
uint32_t consts_count; /* number of side exits */ uint32_t consts_count; /* number of side exits */
zend_jit_exit_const *constants; zend_jit_exit_const *constants;
#endif
} zend_jit_trace_info; } zend_jit_trace_info;
struct _zend_jit_trace_stack_frame { struct _zend_jit_trace_stack_frame {
@ -823,9 +643,6 @@ ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_ret_trace_helper(ZEND_OPCODE_HAND
ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_loop_trace_helper(ZEND_OPCODE_HANDLER_ARGS); ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_loop_trace_helper(ZEND_OPCODE_HANDLER_ARGS);
int ZEND_FASTCALL zend_jit_trace_hot_root(zend_execute_data *execute_data, const zend_op *opline); int ZEND_FASTCALL zend_jit_trace_hot_root(zend_execute_data *execute_data, const zend_op *opline);
#ifndef ZEND_JIT_IR
int ZEND_FASTCALL zend_jit_trace_exit(uint32_t exit_num, zend_jit_registers_buf *regs);
#endif
zend_jit_trace_stop ZEND_FASTCALL zend_jit_trace_execute(zend_execute_data *execute_data, const zend_op *opline, zend_jit_trace_rec *trace_buffer, uint8_t start, uint32_t is_megamorphc); zend_jit_trace_stop ZEND_FASTCALL zend_jit_trace_execute(zend_execute_data *execute_data, const zend_op *opline, zend_jit_trace_rec *trace_buffer, uint8_t start, uint32_t is_megamorphc);
static zend_always_inline const zend_op* zend_jit_trace_get_exit_opline(zend_jit_trace_rec *trace, const zend_op *opline, bool *exit_if_true) static zend_always_inline const zend_op* zend_jit_trace_get_exit_opline(zend_jit_trace_rec *trace, const zend_op *opline, bool *exit_if_true)
@ -910,14 +727,6 @@ static zend_always_inline bool zend_long_is_power_of_two(zend_long x)
return (x > 0) && !(x & (x - 1)); return (x > 0) && !(x & (x - 1));
} }
#ifndef ZEND_JIT_IR
static zend_always_inline uint32_t zend_long_floor_log2(zend_long x)
{
ZEND_ASSERT(zend_long_is_power_of_two(x));
return zend_ulong_ntz(x);
}
#endif
/* from http://aggregate.org/MAGIC/ */ /* from http://aggregate.org/MAGIC/ */
static zend_always_inline uint32_t ones32(uint32_t x) static zend_always_inline uint32_t ones32(uint32_t x)
{ {

View file

@ -1,327 +0,0 @@
/*
+----------------------------------------------------------------------+
| Zend JIT |
+----------------------------------------------------------------------+
| Copyright (c) The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| https://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: Dmitry Stogov <dmitry@php.net> |
+----------------------------------------------------------------------+
*/
#define HAVE_PERFTOOLS 1
#include <stdio.h>
#include <unistd.h>
#include <time.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#if !defined(HAVE_OS_SIGNPOST_H)
#if defined(__linux__)
#include <sys/syscall.h>
#elif defined(__darwin__)
# include <pthread.h>
#elif defined(__FreeBSD__)
# include <sys/thr.h>
# include <sys/sysctl.h>
#elif defined(__NetBSD__)
# include <lwp.h>
#elif defined(__DragonFly__)
# include <sys/lwp.h>
# include <sys/sysctl.h>
#elif defined(__sun)
// avoiding thread.h inclusion as it conflicts with vtunes types.
extern unsigned int thr_self(void);
#elif defined(__HAIKU__)
#include <FindDirectory.h>
#endif
#include "zend_elf.h"
#include "zend_mmap.h"
/*
* 1) Profile using perf-<pid>.map
*
* perf record php -d opcache.huge_code_pages=0 -d opcache.jit_debug=0x10 bench.php
* perf report
*
* 2) Profile using jit-<pid>.dump
*
* perf record -k 1 php -d opcache.huge_code_pages=0 -d opcache.jit_debug=0x20 bench.php
* perf inject -j -i perf.data -o perf.data.jitted
* perf report -i perf.data.jitted
*
*/
#define ZEND_PERF_JITDUMP_HEADER_MAGIC 0x4A695444
#define ZEND_PERF_JITDUMP_HEADER_VERSION 1
#define ZEND_PERF_JITDUMP_RECORD_LOAD 0
#define ZEND_PERF_JITDUMP_RECORD_MOVE 1
#define ZEND_PERF_JITDUMP_RECORD_DEBUG_INFO 2
#define ZEND_PERF_JITDUMP_RECORD_CLOSE 3
#define ZEND_PERF_JITDUMP_UNWINDING_UNFO 4
#define ALIGN8(size) (((size) + 7) & ~7)
#define PADDING8(size) (ALIGN8(size) - (size))
typedef struct zend_perf_jitdump_header {
uint32_t magic;
uint32_t version;
uint32_t size;
uint32_t elf_mach_target;
uint32_t reserved;
uint32_t process_id;
uint64_t time_stamp;
uint64_t flags;
} zend_perf_jitdump_header;
typedef struct _zend_perf_jitdump_record {
uint32_t event;
uint32_t size;
uint64_t time_stamp;
} zend_perf_jitdump_record;
typedef struct _zend_perf_jitdump_load_record {
zend_perf_jitdump_record hdr;
uint32_t process_id;
uint32_t thread_id;
uint64_t vma;
uint64_t code_address;
uint64_t code_size;
uint64_t code_id;
} zend_perf_jitdump_load_record;
static int jitdump_fd = -1;
static void *jitdump_mem = MAP_FAILED;
static uint64_t zend_perf_timestamp(void)
{
struct timespec ts;
if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) {
return 0;
}
return ((uint64_t)ts.tv_sec * 1000000000) + ts.tv_nsec;
}
static void zend_jit_perf_jitdump_open(void)
{
char filename[64];
int fd, ret;
zend_elf_header elf_hdr;
zend_perf_jitdump_header jit_hdr;
sprintf(filename, "/tmp/jit-%d.dump", getpid());
if (!zend_perf_timestamp()) {
return;
}
#if defined(__linux__)
fd = open("/proc/self/exe", O_RDONLY);
#elif defined(__NetBSD__)
fd = open("/proc/curproc/exe", O_RDONLY);
#elif defined(__FreeBSD__) || defined(__DragonFly__)
char path[PATH_MAX];
size_t pathlen = sizeof(path);
int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
if (sysctl(mib, 4, path, &pathlen, NULL, 0) == -1) {
return;
}
fd = open(path, O_RDONLY);
#elif defined(__sun)
fd = open("/proc/self/path/a.out", O_RDONLY);
#elif defined(__HAIKU__)
char path[PATH_MAX];
if (find_path(B_APP_IMAGE_SYMBOL, B_FIND_PATH_IMAGE_PATH,
NULL, path, sizeof(path)) != B_OK) {
return;
}
fd = open(path, O_RDONLY);
#else
fd = -1;
#endif
if (fd < 0) {
return;
}
ret = read(fd, &elf_hdr, sizeof(elf_hdr));
close(fd);
if (ret != sizeof(elf_hdr) ||
elf_hdr.emagic[0] != 0x7f ||
elf_hdr.emagic[1] != 'E' ||
elf_hdr.emagic[2] != 'L' ||
elf_hdr.emagic[3] != 'F') {
return;
}
jitdump_fd = open(filename, O_CREAT | O_TRUNC | O_RDWR, 0666);
if (jitdump_fd < 0) {
return;
}
const size_t page_size = sysconf(_SC_PAGESIZE);
jitdump_mem = mmap(NULL,
page_size,
PROT_READ|PROT_EXEC,
MAP_PRIVATE, jitdump_fd, 0);
if (jitdump_mem == MAP_FAILED) {
close(jitdump_fd);
jitdump_fd = -1;
return;
}
zend_mmap_set_name(jitdump_mem, page_size, "zend_jitdump");
memset(&jit_hdr, 0, sizeof(jit_hdr));
jit_hdr.magic = ZEND_PERF_JITDUMP_HEADER_MAGIC;
jit_hdr.version = ZEND_PERF_JITDUMP_HEADER_VERSION;
jit_hdr.size = sizeof(jit_hdr);
jit_hdr.elf_mach_target = elf_hdr.machine;
jit_hdr.process_id = getpid();
jit_hdr.time_stamp = zend_perf_timestamp();
jit_hdr.flags = 0;
zend_quiet_write(jitdump_fd, &jit_hdr, sizeof(jit_hdr));
}
static void zend_jit_perf_jitdump_close(void)
{
if (jitdump_fd >= 0) {
zend_perf_jitdump_record rec;
rec.event = ZEND_PERF_JITDUMP_RECORD_CLOSE;
rec.size = sizeof(rec);
rec.time_stamp = zend_perf_timestamp();
zend_quiet_write(jitdump_fd, &rec, sizeof(rec));
close(jitdump_fd);
if (jitdump_mem != MAP_FAILED) {
munmap(jitdump_mem, sysconf(_SC_PAGESIZE));
}
}
}
static void zend_jit_perf_jitdump_register(const char *name, void *start, size_t size)
{
if (jitdump_fd >= 0) {
static uint64_t id = 1;
zend_perf_jitdump_load_record rec;
size_t len = strlen(name);
uint32_t thread_id = 0;
#if defined(__linux__)
thread_id = syscall(SYS_gettid);
#elif defined(__darwin__)
uint64_t thread_id_u64;
pthread_threadid_np(NULL, &thread_id_u64);
thread_id = (uint32_t) thread_id_u64;
#elif defined(__FreeBSD__)
long tid;
thr_self(&tid);
thread_id = (uint32_t)tid;
#elif defined(__OpenBSD__)
thread_id = getthrid();
#elif defined(__NetBSD__)
thread_id = _lwp_self();
#elif defined(__DragonFly__)
thread_id = lwp_gettid();
#elif defined(__sun)
thread_id = thr_self();
#endif
memset(&rec, 0, sizeof(rec));
rec.hdr.event = ZEND_PERF_JITDUMP_RECORD_LOAD;
rec.hdr.size = sizeof(rec) + len + 1 + size;
rec.hdr.time_stamp = zend_perf_timestamp();
rec.process_id = getpid();
rec.thread_id = thread_id;
rec.vma = (uint64_t)(uintptr_t)start;
rec.code_address = (uint64_t)(uintptr_t)start;
rec.code_size = (uint64_t)size;
rec.code_id = id++;
zend_quiet_write(jitdump_fd, &rec, sizeof(rec));
zend_quiet_write(jitdump_fd, name, len + 1);
zend_quiet_write(jitdump_fd, start, size);
}
}
static void zend_jit_perf_map_register(const char *name, void *start, size_t size)
{
static FILE *fp = NULL;
if (!fp) {
char filename[64];
sprintf(filename, "/tmp/perf-%d.map", getpid());
fp = fopen(filename, "w");
if (!fp) {
return;
}
setlinebuf(fp);
}
fprintf(fp, "%zx %zx %s\n", (size_t)(uintptr_t)start, size, name);
}
#else
#include <os/log.h>
#include <os/signpost.h>
/*
* 1) To generate an Instrument tracing data:
* xcrun xctrace record --template <Template name> --launch -- php
* xcrun xctrace record --template Logging --launch -- php -dopcache.jit=1255 -dopcache.jit_debug=32 bench.php
* 2) An instrument trace folder is created:
* e.g. open Launch_php_2022-07-03_15.41.05_5F96D825.trace
*/
static os_log_t jitdump_fd;
static os_signpost_id_t jitdump_sp = OS_SIGNPOST_ID_NULL;
static void zend_jit_perf_jitdump_open(void)
{
/**
* The `os_log_t` list per namespace is maintained by the os
* and are not deallocated by (and not deallocatable)
* but are reusable.
*/
jitdump_fd = os_log_create("net.php.opcache.jit", OS_LOG_CATEGORY_POINTS_OF_INTEREST);
jitdump_sp = os_signpost_id_generate(jitdump_fd);
if (jitdump_sp != OS_SIGNPOST_ID_NULL && jitdump_sp != OS_SIGNPOST_ID_INVALID) {
os_signpost_interval_begin(jitdump_fd, jitdump_sp, "zend_jitdump");
}
}
static void zend_jit_perf_jitdump_close(void)
{
if (jitdump_sp != OS_SIGNPOST_ID_NULL && jitdump_sp != OS_SIGNPOST_ID_INVALID) {
os_signpost_interval_end(jitdump_fd, jitdump_sp, "zend_jitdump");
}
}
static void zend_jit_perf_jitdump_register(const char *name, void *start, size_t size)
{
}
static void zend_jit_perf_map_register(const char *name, void *start, size_t size)
{
os_signpost_id_t map = os_signpost_id_make_with_pointer(jitdump_fd, start);
if (map != OS_SIGNPOST_ID_NULL && map != OS_SIGNPOST_ID_INVALID) {
os_signpost_event_emit(jitdump_fd, map, "zend_jitdump_name", "%s", name);
os_signpost_event_emit(jitdump_fd, map, "zend_jitdump_size", "%lu", size);
}
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -28,13 +28,6 @@
#include "Optimizer/zend_func_info.h" #include "Optimizer/zend_func_info.h"
#include "Optimizer/zend_call_graph.h" #include "Optimizer/zend_call_graph.h"
#include "zend_jit.h" #include "zend_jit.h"
#ifndef ZEND_JIT_IR
#if ZEND_JIT_TARGET_X86
# include "zend_jit_x86.h"
#elif ZEND_JIT_TARGET_ARM64
# include "zend_jit_arm64.h"
#endif
#endif /* ZEND_JIT_IR */
#include "zend_jit_internal.h" #include "zend_jit_internal.h"

View file

@ -1,46 +0,0 @@
/*
+----------------------------------------------------------------------+
| Zend JIT |
+----------------------------------------------------------------------+
| Copyright (c) The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| https://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: Dmitry Stogov <dmitry@php.net> |
+----------------------------------------------------------------------+
*/
#if defined(__x86_64__) || defined(i386)
#define HAVE_VTUNE 1
#include "jit/vtune/jitprofiling.h"
#include "jit/vtune/jitprofiling.c"
static void zend_jit_vtune_register(const char *name,
const void *start,
size_t size)
{
iJIT_Method_Load jmethod = {0};
if (iJIT_IsProfilingActive() != iJIT_SAMPLING_ON) {
return;
}
jmethod.method_id = iJIT_GetNewMethodID();
jmethod.method_name = (char*)name;
jmethod.class_file_name = NULL;
jmethod.source_file_name = NULL;
jmethod.method_load_address = (void*)start;
jmethod.method_size = size;
iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, (void*)&jmethod);
}
#endif /* defined(__x86_64__) || defined(i386) */

File diff suppressed because it is too large Load diff

View file

@ -1,157 +0,0 @@
/*
+----------------------------------------------------------------------+
| Zend JIT |
+----------------------------------------------------------------------+
| Copyright (c) The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| https://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: Dmitry Stogov <dmitry@php.net> |
+----------------------------------------------------------------------+
*/
#ifndef HAVE_JIT_X86_H
#define HAVE_JIT_X86_H
typedef enum _zend_reg {
ZREG_NONE = -1,
ZREG_R0,
ZREG_R1,
ZREG_R2,
ZREG_R3,
ZREG_R4,
ZREG_R5,
ZREG_R6,
ZREG_R7,
#if defined(__x86_64__) || defined(_WIN64)
ZREG_R8,
ZREG_R9,
ZREG_R10,
ZREG_R11,
ZREG_R12,
ZREG_R13,
ZREG_R14,
ZREG_R15,
#endif
ZREG_XMM0,
ZREG_XMM1,
ZREG_XMM2,
ZREG_XMM3,
ZREG_XMM4,
ZREG_XMM5,
ZREG_XMM6,
ZREG_XMM7,
#if defined(__x86_64__) || defined(_WIN64)
ZREG_XMM8,
ZREG_XMM9,
ZREG_XMM10,
ZREG_XMM11,
ZREG_XMM12,
ZREG_XMM13,
ZREG_XMM14,
ZREG_XMM15,
#endif
ZREG_NUM,
ZREG_THIS, /* used for delayed FETCH_THIS deoptimization */
/* pseudo constants used by deoptimizer */
ZREG_LONG_MIN_MINUS_1,
ZREG_LONG_MIN,
ZREG_LONG_MAX,
ZREG_LONG_MAX_PLUS_1,
ZREG_NULL,
ZREG_ZVAL_TRY_ADDREF,
ZREG_ZVAL_COPY_GPR0,
} zend_reg;
typedef struct _zend_jit_registers_buf {
#if defined(__x86_64__) || defined(_WIN64)
uint64_t gpr[16]; /* general purpose integer register */
double fpr[16]; /* floating point registers */
#else
uint32_t gpr[8]; /* general purpose integer register */
double fpr[8]; /* floating point registers */
#endif
} zend_jit_registers_buf;
#define ZREG_FIRST_FPR ZREG_XMM0
#define ZREG_COPY ZREG_R0
#define ZREG_RAX ZREG_R0
#define ZREG_RCX ZREG_R1
#define ZREG_RDX ZREG_R2
#define ZREG_RBX ZREG_R3
#define ZREG_RSP ZREG_R4
#define ZREG_RBP ZREG_R5
#define ZREG_RSI ZREG_R6
#define ZREG_RDI ZREG_R7
#ifdef _WIN64
# define ZREG_FP ZREG_R14
# define ZREG_IP ZREG_R15
#elif defined(__x86_64__)
# define ZREG_FP ZREG_R14
# define ZREG_IP ZREG_R15
#else
# define ZREG_FP ZREG_RSI
# define ZREG_IP ZREG_RDI
#endif
#define ZREG_RX ZREG_IP
typedef uint32_t zend_regset;
#define ZEND_REGSET_64BIT 0
#ifdef _WIN64
# define ZEND_REGSET_FIXED \
(ZEND_REGSET(ZREG_RSP) | ZEND_REGSET(ZREG_R14) | ZEND_REGSET(ZREG_R15))
# define ZEND_REGSET_GP \
ZEND_REGSET_DIFFERENCE(ZEND_REGSET_INTERVAL(ZREG_R0, ZREG_R15), ZEND_REGSET_FIXED)
# define ZEND_REGSET_FP \
ZEND_REGSET_DIFFERENCE(ZEND_REGSET_INTERVAL(ZREG_XMM0, ZREG_XMM15), ZEND_REGSET_FIXED)
# define ZEND_REGSET_SCRATCH \
(ZEND_REGSET(ZREG_RAX) | ZEND_REGSET(ZREG_RDX) | ZEND_REGSET(ZREG_RCX) | ZEND_REGSET_INTERVAL(ZREG_R8, ZREG_R11) | ZEND_REGSET_FP)
# define ZEND_REGSET_PRESERVED \
(ZEND_REGSET(ZREG_RBX) | ZEND_REGSET(ZREG_RBP) | ZEND_REGSET(ZREG_R12) | ZEND_REGSET(ZREG_R13) | ZEND_REGSET(ZREG_RDI) | ZEND_REGSET(ZREG_RSI))
#elif defined(__x86_64__)
# define ZEND_REGSET_FIXED \
(ZEND_REGSET(ZREG_RSP) | ZEND_REGSET(ZREG_R14) | ZEND_REGSET(ZREG_R15))
# define ZEND_REGSET_GP \
ZEND_REGSET_DIFFERENCE(ZEND_REGSET_INTERVAL(ZREG_R0, ZREG_R15), ZEND_REGSET_FIXED)
# define ZEND_REGSET_FP \
ZEND_REGSET_DIFFERENCE(ZEND_REGSET_INTERVAL(ZREG_XMM0, ZREG_XMM15), ZEND_REGSET_FIXED)
# define ZEND_REGSET_SCRATCH \
(ZEND_REGSET(ZREG_RAX) | ZEND_REGSET(ZREG_RDI) | ZEND_REGSET(ZREG_RSI) | ZEND_REGSET(ZREG_RDX) | ZEND_REGSET(ZREG_RCX) | ZEND_REGSET_INTERVAL(ZREG_R8, ZREG_R11) | ZEND_REGSET_FP)
# define ZEND_REGSET_PRESERVED \
(ZEND_REGSET(ZREG_RBX) | ZEND_REGSET(ZREG_RBP) | ZEND_REGSET(ZREG_R12) | ZEND_REGSET(ZREG_R13))
#else
# define ZEND_REGSET_FIXED \
(ZEND_REGSET(ZREG_RSP) | ZEND_REGSET(ZREG_RSI) | ZEND_REGSET(ZREG_RDI))
# define ZEND_REGSET_GP \
ZEND_REGSET_DIFFERENCE(ZEND_REGSET_INTERVAL(ZREG_R0, ZREG_R7), ZEND_REGSET_FIXED)
# define ZEND_REGSET_FP \
ZEND_REGSET_DIFFERENCE(ZEND_REGSET_INTERVAL(ZREG_XMM0, ZREG_XMM7), ZEND_REGSET_FIXED)
# define ZEND_REGSET_SCRATCH \
(ZEND_REGSET(ZREG_RAX) | ZEND_REGSET(ZREG_RCX) | ZEND_REGSET(ZREG_RDX) | ZEND_REGSET_FP)
# define ZEND_REGSET_PRESERVED \
(ZEND_REGSET(ZREG_RBX) | ZEND_REGSET(ZREG_RBP))
#endif
#define ZEND_REGSET_LOW_PRIORITY \
(ZEND_REGSET(ZREG_R0) | ZEND_REGSET(ZREG_R1) | ZEND_REGSET(ZREG_XMM0) | ZEND_REGSET(ZREG_XMM1))
#endif /* ZEND_JIT_X86_H */