view release on metacpan or search on metacpan
libjit/include/Makefile.am
libjit/include/jit/Makefile.am
libjit/include/jit/jit-apply.h
libjit/include/jit/jit-arch-arm.h
libjit/include/jit/jit-arch-generic.h
libjit/include/jit/jit-arch-x86-64.h
libjit/include/jit/jit-arch-x86.h
libjit/include/jit/jit-block.h
libjit/include/jit/jit-common.h
libjit/include/jit/jit-context.h
libjit/include/jit/jit-debugger.h
libjit/include/jit/jit-defs.h.in
libjit/include/jit/jit-dump.h
libjit/include/jit/jit-dynamic.h
libjit/include/jit/jit-elf.h
libjit/include/jit/jit-except.h
libjit/include/jit/jit-function.h
libjit/include/jit/jit-init.h
libjit/include/jit/jit-insn.h
libjit/include/jit/jit-intrinsic.h
libjit/include/jit/jit-memory.h
libjit/jit/jit-bitset.c
libjit/jit/jit-bitset.h
libjit/jit/jit-block.c
libjit/jit/jit-cfg.c
libjit/jit/jit-cfg.h
libjit/jit/jit-compile.c
libjit/jit/jit-config.h
libjit/jit/jit-context.c
libjit/jit/jit-cpuid-x86.c
libjit/jit/jit-cpuid-x86.h
libjit/jit/jit-debugger.c
libjit/jit/jit-dump.c
libjit/jit/jit-elf-defs.h
libjit/jit/jit-elf-read.c
libjit/jit/jit-elf-write.c
libjit/jit/jit-except.c
libjit/jit/jit-function.c
libjit/jit/jit-gen-arm.c
libjit/jit/jit-gen-arm.h
libjit/jit/jit-gen-x86-64.h
libjit/jit/jit-gen-x86.h
libjit/COPYING.LESSER view on Meta::CPAN
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
libjit/ChangeLog view on Meta::CPAN
* jit/jit-reg-alloc.c (choose_output_register, _jit_regs_assign):
fix handling of explicitely assigned registers.
* jit/jit-rules-x86.c (shift_reg): remove function.
* jit/jit-rules-x86.ins (JIT_OP_ISHL, JIT_OP_ISHR, JIT_OP_ISHR_UN):
rewrite rules with explicit assignment to "ecx" register, don't use
shift_reg() function.
2011-07-02 Aleksey Demakov <ademakov@gmail.com>
* jit/jit-compile.c (compile_block): amend debug info
2010-11-28 Klaus Treichel <ktreichel@web.de>
* config/jit-opcodes.ops: Set the destination value type for the
address_of_label opcode.
* jit/jit-dump.c (jit_dump_insn): Print the destination value for
the address_of_label opcode.
2010-11-07 Klaus Treichel <ktreichel@web.de>
libjit/ChangeLog view on Meta::CPAN
* include/jit/jit-walk.h (jit_get_current_frame):
* jit/jit-walk.c (jit_get_starting_frame):
* tools/gen-apply.c (find_return_offset, detect_frame_offsets): use
_JIT_ARCH_GET_CURRENT_FRAME macro if available. This resolves the
problem with gcc 4.1.* where __builtin_frame_address() function is
broken (thanks Klaus for identifing the problem).
2006-09-15 Radek Polak <psonek2@seznam.cz>
* include/jit/jit-insn.h, jit/jit-insn.c, jit/jit-debugger.c: new
instruction jit_insn_mark_breakpoint_variable.
2006-09-14 Aleksey Demakov <ademakov@gmail.com>
* jit/jit-reg-alloc.h, jit/jit-reg-alloc.c: remove "old" register
allocation code.
* configure.in: remove --enable-new-reg-alloc option.
* jit/jit-rules-x86.ins: simplify JIT_OP_RETURN_LONG rule, lift code
libjit/ChangeLog view on Meta::CPAN
destination pointers in "store_relative" instructions, because
otherwise the register allocator gets confused.
2004-10-29 Peter Lund <firefly@diku.dk>
* doc/libjit.3: fix manpage formatting issues. (patch attached
to bug #10779, Gopal).
2004-10-28 Rhys Weatherley <rweather@southern-storm.com.au>
* configure.in, jit/jit-debugger.c, jit/jit-thread.c,
jit/jit-thread.h: implement some of the locking code
for the debugging API.
2004-10-12 Evin Robertson <evin@users.sourceforge.net>
* jit/jit-rules-x86.c (output_branch): correct the offset
when outputting a long-form backward branch.
* tests/Makefile.am, tests/loop.pas: test case for the
long-form backward branch bug.
2004-10-06 Rhys Weatherley <rweather@southern-storm.com.au>
* doc/Makefile.am, doc/libjit.texi, include/jit/Makefile.am,
include/jit/jit-common.h, include/jit/jit-context.h,
include/jit/jit-debugger.h, include/jit/jit-except.h,
include/jit/jit-function.h, include/jit/jit.h, jit/Makefile.am,
jit/jit-context.c, jit/jit-debug.c, jit/jit-debugger.c,
jit/jit-insn.c, jit/jit-internal.h, jit/jit-interp.c:
redesign the debugger API so that it contains functions
like "add breakpoint", "run", "step", etc that more closely resemble
what a front end debugger will want to have, shifting the
implementation burden off the front end.
2004-10-04 Rhys Weatherley <rweather@southern-storm.com.au>
* include/jit/jit-function.h, include/jit/jit-insn.h,
include/jit/jit-opcode.h, include/jit/jit-plus.h, jit/jit-function.c,
jit/jit-insn.c, jit/jit-internal.h, jit/jit-interp.c,
jit/jit-opcode.c, jit/jit-rules-interp.c, jit/jit-rules-arm.sel,
jit/jit-rules-x86.sel, jitplus/jit-plus-function.cpp:
add instructions and function API's for supporting debug line
numbers and breakpoints.
* doc/Makefile.am, doc/libjit.texi, include/jit/jit-context.h,
include/jit/jit-insn.h, include/jit/jit-opcode.h,
include/jit/jit-plus.h, jit/Makefile.am, jit/jit-context.c,
jit/jit-debug.c, jit/jit-function.c, jit/jit-insn.c,
jit/jit-internal.h, jit/jit-interp.c, jit/jit-opcode.c,
jit/jit-rules-arm.sel, jit/jit-rules-interp.c, jit/jit-rules-x86.sel,
jitplus/jit-plus-function.cpp: clean up the breakpoint API and
implement debug hooks for the interpreter.
* jit/jit-insn.c, jit/jit-rules-arm.sel, jit/jit-rules-x86.sel:
use a common helper function for performing debug hook tests on
native platforms, to avoid the need to implement breakpoint testing
individually in every native back end.
2004-09-10 Rhys Weatherley <rweather@southern-storm.com.au>
* jit/jit-rules-x86.sel: pointer-relative loads and stores
for structures in the x86 back end.
2004-09-09 Rhys Weatherley <rweather@southern-storm.com.au>
libjit/ChangeLog view on Meta::CPAN
* jit/jit-apply-arm.c, jit/jit-gen-arm.c, jit/jit-gen-arm.h,
jit/jit-rules-arm.c, jit/jit-rules-arm.h, jit/jit-rules-arm.sel,
tools/gen-sel-parser.y: redesign the ARM code generation macros
so that they have stronger protection against buffer overruns.
* jit/jit-rules-arm.sel: flush the constant pool after unconditional
branches, to try to minimize the probability that the pool will
be flushed in the middle of a loop body.
* jit/jit-dump.c: dump the hex address of external functions,
to aid with debugging native disassembly dumps.
* include/jit/jit-insn.h, include/jit/jit-opcode.h,
include/jit/jit-plus.h, jit/jit-insn.c, jit/jit-internal.h,
jit/jit-interp.c, jit/jit-opcode.c, jit/jit-rules-arm.c,
jit/jit-rules-arm.sel, jitplus/jit-plus-function.cpp:
add support for outgoing parameter areas, which should reduce
the overhead of function calls that involve stacked arguments
on non-x86 platforms; use parameter areas in the ARM back end.
* include/jit/jit-plus.h, include/jit/jit-value.h, jit/jit-insn.c,
libjit/ChangeLog view on Meta::CPAN
jit/jit-rules-arm.c, jit/jit-rules-interp.c, jit/jit-rules-x86.c,
jit/jit-rules.h, jitplus/jit-plus-function.cpp: put some
infrastructure in place to support "try"-related instructions.
* dpas/dpas-parser.y, dpas/dpas-scope.h, dpas/dpas-semantics.h:
introduce effective address based l-values into dpas.
2004-04-27 Rhys Weatherley <rweather@southern-storm.com.au>
* jit/jit-dump.c, jit/jit-reg-alloc.c: fix a register stack bug
in "_jit_regs_set_value"; add some more debug code.
* include/jit/jit-opcode.h, jit/jit-insn.c, jit/jit-internal.h,
jit/jit-interp.cpp, jit/jit-opcode.c: wrap function calls
with code to set up and remove exception frame information.
* jit/jit-function.c, jit/jit-insn.c, jit/jit-internal.h:
intuit "nothrow" and "noreturn" flags for compiled functions.
* include/jit/jit-insn.h, include/jit/jit-plus.h, jit/jit-insn.c,
jitplus/jit-plus-function.cpp: add "jit_insn_throw",
libjit/NEWS view on Meta::CPAN
* Throw builtin exceptions (Aleksey Demakov).
* Implement array expressions (Avinash Atreya).
Other:
* Sample VM for demonstrating libjit (Norbert Bellow).
* Debug interface for line numbers and breakpoints (Rhys Weatherley).
* Man page formatting issues (Peter Lund).
* Wrong return value in jit_function_apply_vararg (Evin Robertson).
* Make debug dumping work with cygwin (Aleksey Demakov).
* Option to force use on long double on Win32 (Aleksey Demakov).
0.0.4 (8 August 2004)
* Pluggable object models.
* Problems with "gen-apply" on Win32 systems.
* Optimize "if true goto" into "goto".
* Peephole optimization on branches.
* Adjust ARM codegen macros to support branch elimination instructions.
* Redesign exception handling to use "setjmp" everywhere.
libjit/TODO view on Meta::CPAN
Target release: 0.1.4
=====================
* CFG-based liveness analysis and dead code elimination
* global copy and constant propagation
* jitruby (in case copyright issues are resolved)
* sync jitplus with jit (jump tables, compile driver, debug)
* fix catch/throw within finally
* get rid of manual rules
* add direct conversion opcodes to/from float32 and float64
* add rounding towards zero
* try to be smarter with %rax for variadic functions on x86-64
Target Release: 0.2.0
=====================
* linear scan register allocation
libjit/doc/Makefile.am view on Meta::CPAN
man_MANS = libjit.3
EXTRA_SCRIPTS = extract-docs.sh mkhtml.sh mkpdf.sh
EXTRA_DIST = $(man_MANS) $(EXTRA_SCRIPTS)
info_TEXINFOS = libjit.texi
libjit_TEXINFOS = \
$(srcdir)/libjitext-apply.texi \
$(srcdir)/libjitext-block.texi \
$(srcdir)/libjitext-context.texi \
$(srcdir)/libjitext-debugger.texi \
$(srcdir)/libjitext-dump.texi \
$(srcdir)/libjitext-dynlib.texi \
$(srcdir)/libjitext-elf-read.texi \
$(srcdir)/libjitext-except.texi \
$(srcdir)/libjitext-function.texi \
$(srcdir)/libjitext-init.texi \
$(srcdir)/libjitext-insn.texi \
$(srcdir)/libjitext-intrinsic.texi \
$(srcdir)/libjitext-cpp-mangle.texi \
$(srcdir)/libjitext-util.texi \
libjit/doc/Makefile.am view on Meta::CPAN
$(srcdir)/libjitext-apply.texi: $(top_srcdir)/jit/jit-apply.c
$(SHELL) $(srcdir)/extract-docs.sh $< >$@
$(srcdir)/libjitext-block.texi: $(top_srcdir)/jit/jit-block.c
$(SHELL) $(srcdir)/extract-docs.sh $< >$@
$(srcdir)/libjitext-context.texi: $(top_srcdir)/jit/jit-context.c
$(SHELL) $(srcdir)/extract-docs.sh $< >$@
$(srcdir)/libjitext-debugger.texi: $(top_srcdir)/jit/jit-debugger.c
$(SHELL) $(srcdir)/extract-docs.sh $< >$@
$(srcdir)/libjitext-dump.texi: $(top_srcdir)/jit/jit-dump.c
$(SHELL) $(srcdir)/extract-docs.sh $< >$@
$(srcdir)/libjitext-dynlib.texi: $(top_srcdir)/jitdynamic/jit-dynlib.c
$(SHELL) $(srcdir)/extract-docs.sh $< >$@
$(srcdir)/libjitext-elf-read.texi: $(top_srcdir)/jit/jit-elf-read.c
$(SHELL) $(srcdir)/extract-docs.sh $< >$@
libjit/doc/libjit.texi view on Meta::CPAN
* Features:: Features of libjit
* Tutorials:: Tutorials in using libjit
* Initialization:: Initializing the JIT
* Functions:: Building and compiling functions with the JIT
* Types:: Manipulating system types
* Values:: Working with temporary values in the JIT
* Instructions:: Working with instructions in the JIT
* Basic Blocks:: Working with basic blocks in the JIT
* Intrinsics:: Intrinsic functions available to libjit users
* Exceptions:: Handling exceptions
* Breakpoint Debugging:: Hooking a breakpoint debugger into libjit
* ELF Binaries:: Manipulating ELF binaries
* Utility Routines:: Miscellaneous utility routines
* Diagnostic Routines:: Diagnostic routines
* C++ Interface:: Using libjit from C++
* Porting:: Porting libjit to new architectures
* Index:: Index of concepts and facilities
@end menu
@c -----------------------------------------------------------------------
libjit/doc/libjit.texi view on Meta::CPAN
jit_value_t temp3;
...
temp_args[0] = x;
temp_args[1] = jit_insn_sub(function, y, x);
temp3 = jit_insn_call
(function, "gcd", function, 0, temp_args, 2, 0);
jit_insn_return(function, temp3);
@end example
The string @code{"gcd"} in the second argument is for diagnostic purposes
only. It can be helpful when debugging, but the @code{libjit} library
otherwise makes no use of it. You can set it to NULL if you wish.
In general, @code{libjit} does not maintain mappings from names to
@code{jit_function_t} objects. It is assumed that the front end will
take care of that, using whatever naming scheme is appropriate to
its needs.
@noindent
The final part of the @code{gcd} function is similar to the previous one:
libjit/doc/libjit.texi view on Meta::CPAN
@node Exceptions, Breakpoint Debugging, Intrinsics, Top
@chapter Handling exceptions
@cindex Handling exceptions
@include libjitext-except.texi
@c -----------------------------------------------------------------------
@node Breakpoint Debugging, ELF Binaries, Exceptions, Top
@chapter Hooking a breakpoint debugger into libjit
@cindex Breakpoint debugging
@include libjitext-debugger.texi
@c -----------------------------------------------------------------------
@node ELF Binaries, Utility Routines, Breakpoint Debugging, Top
@chapter Manipulating ELF binaries
@cindex ELF binaries
@include libjitext-elf-read.texi
@c -----------------------------------------------------------------------
libjit/include/jit/Makefile.am view on Meta::CPAN
BUILT_SOURCES = jit-arch.h jit-opcode.h
libjitincludedir = $(includedir)/jit
dist_libjitinclude_HEADERS = \
jit.h \
jit-apply.h \
jit-block.h \
jit-common.h \
jit-context.h \
jit-debugger.h \
jit-defs.h \
jit-dump.h \
jit-dynamic.h \
jit-elf.h \
jit-except.h \
jit-function.h \
jit-init.h \
jit-insn.h \
jit-intrinsic.h \
jit-memory.h \
libjit/include/jit/jit-debugger.h view on Meta::CPAN
/*
* jit-debugger.h - Helper routines for single-step debugging of programs.
*
* Copyright (C) 2004 Southern Storm Software, Pty Ltd.
*
* The libjit library is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation, either version 2.1 of
* the License, or (at your option) any later version.
*
* The libjit library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
libjit/include/jit/jit-debugger.h view on Meta::CPAN
#ifndef _JIT_DEBUGGER_H
#define _JIT_DEBUGGER_H
#include <jit/jit-common.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct jit_debugger *jit_debugger_t;
typedef jit_nint jit_debugger_thread_id_t;
typedef jit_nint jit_debugger_breakpoint_id_t;
typedef struct jit_debugger_event
{
int type;
jit_debugger_thread_id_t thread;
jit_function_t function;
jit_nint data1;
jit_nint data2;
jit_debugger_breakpoint_id_t id;
jit_stack_trace_t trace;
} jit_debugger_event_t;
#define JIT_DEBUGGER_TYPE_QUIT 0
#define JIT_DEBUGGER_TYPE_HARD_BREAKPOINT 1
#define JIT_DEBUGGER_TYPE_SOFT_BREAKPOINT 2
#define JIT_DEBUGGER_TYPE_USER_BREAKPOINT 3
#define JIT_DEBUGGER_TYPE_ATTACH_THREAD 4
#define JIT_DEBUGGER_TYPE_DETACH_THREAD 5
typedef struct jit_debugger_breakpoint_info
{
int flags;
jit_debugger_thread_id_t thread;
jit_function_t function;
jit_nint data1;
jit_nint data2;
} *jit_debugger_breakpoint_info_t;
#define JIT_DEBUGGER_FLAG_THREAD (1 << 0)
#define JIT_DEBUGGER_FLAG_FUNCTION (1 << 1)
#define JIT_DEBUGGER_FLAG_DATA1 (1 << 2)
#define JIT_DEBUGGER_FLAG_DATA2 (1 << 3)
#define JIT_DEBUGGER_DATA1_FIRST 10000
#define JIT_DEBUGGER_DATA1_LINE 10000
#define JIT_DEBUGGER_DATA1_ENTER 10001
#define JIT_DEBUGGER_DATA1_LEAVE 10002
#define JIT_DEBUGGER_DATA1_THROW 10003
typedef void (*jit_debugger_hook_func)
(jit_function_t func, jit_nint data1, jit_nint data2);
int jit_debugging_possible(void) JIT_NOTHROW;
jit_debugger_t jit_debugger_create(jit_context_t context) JIT_NOTHROW;
void jit_debugger_destroy(jit_debugger_t dbg) JIT_NOTHROW;
jit_context_t jit_debugger_get_context(jit_debugger_t dbg) JIT_NOTHROW;
jit_debugger_t jit_debugger_from_context(jit_context_t context) JIT_NOTHROW;
jit_debugger_thread_id_t jit_debugger_get_self(jit_debugger_t dbg) JIT_NOTHROW;
jit_debugger_thread_id_t jit_debugger_get_thread
(jit_debugger_t dbg, const void *native_thread) JIT_NOTHROW;
int jit_debugger_get_native_thread
(jit_debugger_t dbg, jit_debugger_thread_id_t thread,
void *native_thread) JIT_NOTHROW;
void jit_debugger_set_breakable
(jit_debugger_t dbg, const void *native_thread, int flag) JIT_NOTHROW;
void jit_debugger_attach_self
(jit_debugger_t dbg, int stop_immediately) JIT_NOTHROW;
void jit_debugger_detach_self(jit_debugger_t dbg) JIT_NOTHROW;
int jit_debugger_wait_event
(jit_debugger_t dbg, jit_debugger_event_t *event,
jit_int timeout) JIT_NOTHROW;
jit_debugger_breakpoint_id_t jit_debugger_add_breakpoint
(jit_debugger_t dbg, jit_debugger_breakpoint_info_t info) JIT_NOTHROW;
void jit_debugger_remove_breakpoint
(jit_debugger_t dbg, jit_debugger_breakpoint_id_t id) JIT_NOTHROW;
void jit_debugger_remove_all_breakpoints(jit_debugger_t dbg) JIT_NOTHROW;
int jit_debugger_is_alive
(jit_debugger_t dbg, jit_debugger_thread_id_t thread) JIT_NOTHROW;
int jit_debugger_is_running
(jit_debugger_t dbg, jit_debugger_thread_id_t thread) JIT_NOTHROW;
void jit_debugger_run
(jit_debugger_t dbg, jit_debugger_thread_id_t thread) JIT_NOTHROW;
void jit_debugger_step
(jit_debugger_t dbg, jit_debugger_thread_id_t thread) JIT_NOTHROW;
void jit_debugger_next
(jit_debugger_t dbg, jit_debugger_thread_id_t thread) JIT_NOTHROW;
void jit_debugger_finish
(jit_debugger_t dbg, jit_debugger_thread_id_t thread) JIT_NOTHROW;
void jit_debugger_break(jit_debugger_t dbg) JIT_NOTHROW;
void jit_debugger_quit(jit_debugger_t dbg) JIT_NOTHROW;
jit_debugger_hook_func jit_debugger_set_hook
(jit_context_t context, jit_debugger_hook_func hook);
#ifdef __cplusplus
};
#endif
#endif /* _JIT_DEBUGGER_H */
libjit/include/jit/jit-dump.h view on Meta::CPAN
/*
* jit-dump.h - Functions for dumping JIT structures, for debugging.
*
* Copyright (C) 2004 Southern Storm Software, Pty Ltd.
*
* The libjit library is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation, either version 2.1 of
* the License, or (at your option) any later version.
*
* The libjit library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
libjit/include/jit/jit-dynamic.h view on Meta::CPAN
/*
* Dynamic library routines.
*/
typedef void *jit_dynlib_handle_t;
jit_dynlib_handle_t jit_dynlib_open(const char *name) JIT_NOTHROW;
void jit_dynlib_close(jit_dynlib_handle_t handle) JIT_NOTHROW;
void *jit_dynlib_get_symbol
(jit_dynlib_handle_t handle, const char *symbol) JIT_NOTHROW;
const char *jit_dynlib_get_suffix(void) JIT_NOTHROW;
void jit_dynlib_set_debug(int flag) JIT_NOTHROW;
/*
* C++ name mangling definitions.
*/
#define JIT_MANGLE_PUBLIC 0x0001
#define JIT_MANGLE_PROTECTED 0x0002
#define JIT_MANGLE_PRIVATE 0x0003
#define JIT_MANGLE_STATIC 0x0008
#define JIT_MANGLE_VIRTUAL 0x0010
#define JIT_MANGLE_CONST 0x0020
libjit/include/jit/jit-elf.h view on Meta::CPAN
/*
* Opaque types that represent a loaded ELF binary in read or write mode.
*/
typedef struct jit_readelf *jit_readelf_t;
typedef struct jit_writeelf *jit_writeelf_t;
/*
* Flags for "jit_readelf_open".
*/
#define JIT_READELF_FLAG_FORCE (1 << 0) /* Force file to load */
#define JIT_READELF_FLAG_DEBUG (1 << 1) /* Print debugging information */
/*
* Result codes from "jit_readelf_open".
*/
#define JIT_READELF_OK 0 /* File was opened successfully */
#define JIT_READELF_CANNOT_OPEN 1 /* Could not open the file */
#define JIT_READELF_NOT_ELF 2 /* Not an ELF-format binary */
#define JIT_READELF_WRONG_ARCH 3 /* Wrong architecture for local system */
#define JIT_READELF_BAD_FORMAT 4 /* ELF file, but badly formatted */
#define JIT_READELF_MEMORY 5 /* Insufficient memory to load the file */
libjit/include/jit/jit.h view on Meta::CPAN
#ifdef __cplusplus
extern "C" {
#endif
#include <jit/jit-defs.h>
#include <jit/jit-common.h>
#include <jit/jit-context.h>
#include <jit/jit-apply.h>
#include <jit/jit-block.h>
#include <jit/jit-debugger.h>
#include <jit/jit-elf.h>
#include <jit/jit-except.h>
#include <jit/jit-function.h>
#include <jit/jit-init.h>
#include <jit/jit-insn.h>
#include <jit/jit-intrinsic.h>
#include <jit/jit-meta.h>
#include <jit/jit-objmodel.h>
#include <jit/jit-opcode.h>
#include <jit/jit-type.h>
libjit/jit/Makefile.am view on Meta::CPAN
jit-apply-x86-64.h \
jit-apply-x86-64.c \
jit-bitset.h \
jit-bitset.c \
jit-block.c \
jit-compile.c \
jit-config.h \
jit-context.c \
jit-cpuid-x86.h \
jit-cpuid-x86.c \
jit-debugger.c \
jit-dump.c \
jit-elf-defs.h \
jit-elf-read.c \
jit-elf-write.c \
jit-except.c \
jit-function.c \
jit-gen-arm.h \
jit-gen-arm.c \
jit-gen-x86.h \
jit-gen-x86-64.h \
libjit/jit/jit-compile.c view on Meta::CPAN
* Optimize a function by analyzing and transforming its intermediate
* representation. If the function was already compiled or optimized,
* then do nothing.
*
* Returns @code{JIT_RESUlT_OK} on success, otherwise it might return
* @code{JIT_RESULT_OUT_OF_MEMORY}, @code{JIT_RESULT_COMPILE_ERROR} or
* possibly some other more specific @code{JIT_RESULT_} code.
*
* Normally this function should not be used because @code{jit_compile}
* performs all the optimization anyway. However it might be useful for
* debugging to verify the effect of the @code{libjit} code optimization.
* This might be done, for instance, by calling @code{jit_dump_function}
* before and after @code{jit_optimize}.
* @end deftypefun
@*/
int
jit_optimize(jit_function_t func)
{
jit_jmp_buf jbuf;
jit_exception_func handler;
libjit/jit/jit-compile.c view on Meta::CPAN
jit_exception_builtin(JIT_RESULT_OUT_OF_MEMORY);
}
}
#ifndef JIT_BACKEND_INTERP
/* On success perform a CPU cache flush, to make the code executable */
_jit_flush_exec(state->gen.code_start,
state->gen.code_end - state->gen.code_start);
#endif
/* Terminate the debug information and flush it */
if(!_jit_varint_encode_end(&state->gen.offset_encoder))
{
jit_exception_builtin(JIT_RESULT_OUT_OF_MEMORY);
}
state->func->bytecode_offset = _jit_varint_get_data(&state->gen.offset_encoder);
}
}
/*
* Give back the allocated space in case of failure to generate the code.
libjit/jit/jit-context.c view on Meta::CPAN
* @item JIT_OPTION_PRE_COMPILE
* A numeric option that indicates that this context is being used
* for pre-compilation if it is set to a non-zero value. Code within
* pre-compiled contexts cannot be executed directly. Instead, they
* can be written out to disk in ELF format to be reloaded at
* some future time.
*
* @vindex JIT_OPTION_DONT_FOLD
* @item JIT_OPTION_DONT_FOLD
* A numeric option that disables constant folding when it is set to a
* non-zero value. This is useful for debugging, as it forces @code{libjit} to
* always execute constant expressions at run time, instead of at compile time.
*
* @vindex JIT_OPTION_POSITION_INDEPENDENT
* @item JIT_OPTION_POSITION_INDEPENDENT
* A numeric option that forces generation of position-independent code (PIC)
* if it is set to a non-zero value. This may be mainly useful for pre-compiled
* contexts.
* @end table
*
* Metadata type values of 10000 or greater are reserved for internal use.
libjit/jit/jit-debugger.c view on Meta::CPAN
/*
* jit-debugger.c - Helper routines for single-step debugging of programs.
*
* Copyright (C) 2004 Southern Storm Software, Pty Ltd.
*
* This file is part of the libjit library.
*
* The libjit library is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation, either version 2.1 of
* the License, or (at your option) any later version.
*
libjit/jit/jit-debugger.c view on Meta::CPAN
*
* You should have received a copy of the GNU Lesser General Public
* License along with the libjit library. If not, see
* <http://www.gnu.org/licenses/>.
*/
#include "jit-internal.h"
/*@
@cindex jit-debugger.h
The @code{libjit} library provides support routines for breakpoint-based
single-step debugging. It isn't a full debugger, but provides the
infrastructure necessary to support one.
The front end virtual machine is responsible for inserting "potential
breakpoints" into the code when functions are built and compiled. This
is performed using @code{jit_insn_mark_breakpoint}:
@deftypefun int jit_insn_mark_breakpoint (jit_function_t @var{func}, jit_nint @var{data1}, jit_nint @var{data2})
Mark the current position in @var{func} as corresponding to a breakpoint
location. When a break occurs, the debugging routines are passed
@var{func}, @var{data1}, and @var{data2} as arguments. By convention,
@var{data1} is the type of breakpoint (source line, function entry,
function exit, etc).
@end deftypefun
There are two ways for a front end to receive notification about breakpoints.
The bulk of this chapter describes the @code{jit_debugger_t} interface,
which handles most of the ugly details. In addition, a low-level "debug hook
mechanism" is provided for front ends that wish more control over the
process. The debug hook mechanism is described below, under the
@code{jit_debugger_set_hook} function.
This debugger implementation requires a threading system to work
successfully. At least two threads are required, in addition to those of
the program being debugged:
@enumerate
@item
Event thread which calls @code{jit_debugger_wait_event} to receive
notifications of breakpoints and other interesting events.
@item
User interface thread which calls functions like @code{jit_debugger_run},
@code{jit_debugger_step}, etc, to control the debug process.
@end enumerate
These two threads should be set to "unbreakable" with a call to
@code{jit_debugger_set_breakable}. This prevents them from accidentally
stopping at a breakpoint, which would cause a system deadlock.
Other housekeeping threads, such as a finalization thread, should
also be set to "unbreakable" for the same reason.
@noindent
Events have the following members:
@table @code
@item type
The type of event (see the next table for details).
libjit/jit/jit-debugger.c view on Meta::CPAN
@itemx data2
The data values at the breakpoint. These values are inserted into
the function's code with @code{jit_insn_mark_breakpoint}.
@item id
The identifier for the breakpoint.
@item trace
The stack trace corresponding to the location where the breakpoint
occurred. This value is automatically freed upon the next call
to @code{jit_debugger_wait_event}. If you wish to preserve the
value, then you must call @code{jit_stack_trace_copy}.
@end table
@noindent
The following event types are currently supported:
@table @code
@item JIT_DEBUGGER_TYPE_QUIT
A thread called @code{jit_debugger_quit}, indicating that it wanted the
event thread to terminate.
@item JIT_DEBUGGER_TYPE_HARD_BREAKPOINT
A thread stopped at a hard breakpoint. That is, a breakpoint defined
by a call to @code{jit_debugger_add_breakpoint}.
@item JIT_DEBUGGER_TYPE_SOFT_BREAKPOINT
A thread stopped at a breakpoint that wasn't explicitly defined by
a call to @code{jit_debugger_add_breakpoint}. This typicaly results
from a call to a "step" function like @code{jit_debugger_step}, where
execution stopped at the next line but there isn't an explicit breakpoint
on that line.
@item JIT_DEBUGGER_TYPE_USER_BREAKPOINT
A thread stopped because of a call to @code{jit_debugger_break}.
@item JIT_DEBUGGER_TYPE_ATTACH_THREAD
A thread called @code{jit_debugger_attach_self}. The @code{data1} field
of the event is set to the value of @code{stop_immediately} for the call.
@item JIT_DEBUGGER_TYPE_DETACH_THREAD
A thread called @code{jit_debugger_detach_self}.
@end table
@deftypefun int jit_insn_mark_breakpoint_variable (jit_function_t @var{func}, jit_value_t @var{data1}, jit_value_t @var{data2})
This function is similar to @code{jit_insn_mark_breakpoint} except that values
in @var{data1} and @var{data2} can be computed at runtime. You can use this
function for example to get address of local variable.
@end deftypefun
@*/
/*
* Linked event, for the debugger event queue.
*/
typedef struct jit_debugger_linked_event
{
jit_debugger_event_t event;
struct jit_debugger_linked_event *next;
} jit_debugger_linked_event_t;
/*
* Run types.
*/
#define JIT_RUN_TYPE_STOPPED 0
#define JIT_RUN_TYPE_CONTINUE 1
#define JIT_RUN_TYPE_STEP 2
#define JIT_RUN_TYPE_NEXT 3
#define JIT_RUN_TYPE_FINISH 4
#define JIT_RUN_TYPE_DETACHED 5
/*
* Information about a thread that is under the control of the debugger.
*/
typedef struct jit_debugger_thread
{
struct jit_debugger_thread *next;
jit_debugger_thread_id_t id;
jit_thread_id_t native_id;
int volatile run_type;
jit_function_t find_func;
jit_nint last_data1;
jit_nint last_func_data1;
int breakable;
} *jit_debugger_thread_t;
/*
* Structure of a debugger instance.
*/
struct jit_debugger
{
jit_monitor_t queue_lock;
jit_monitor_t run_lock;
jit_context_t context;
jit_debugger_linked_event_t * volatile events;
jit_debugger_linked_event_t * volatile last_event;
};
/*
* Lock the debugger object.
*/
#define lock_debugger(dbg) jit_monitor_lock(&((dbg)->run_lock))
/*
* Unlock the debugger object.
*/
#define unlock_debugger(dbg) jit_monitor_unlock(&((dbg)->run_lock))
/*
* Suspend the current thread until it is marked as running again.
* It is assumed that the debugger's monitor lock has been acquired.
*/
static void suspend_thread(jit_debugger_t dbg, jit_debugger_thread_t thread)
{
while(thread->run_type == JIT_RUN_TYPE_STOPPED)
{
jit_monitor_wait(&(dbg->run_lock), -1);
}
}
/*
* Wake all threads that are waiting on the debugger's monitor.
*/
#define wakeup_all(dbg) jit_monitor_signal_all(&((dbg)->run_lock))
/*
* Get the information block for the current thread.
*/
static jit_debugger_thread_t get_current_thread(jit_debugger_t dbg)
{
/* TODO */
return 0;
}
/*
* Get the information block for a specific thread.
*/
static jit_debugger_thread_t get_specific_thread
(jit_debugger_t dbg, jit_debugger_thread_id_t thread)
{
/* TODO */
return 0;
}
/*
* Allocate space for a new event on the event queue.
*/
#define alloc_event() \
((jit_debugger_event_t *)jit_cnew(jit_debugger_linked_event_t))
/*
* Add an event that was previously allocated with "alloc_event"
* to a debugger's event queue.
*/
static void add_event(jit_debugger_t dbg, jit_debugger_event_t *_event)
{
jit_debugger_linked_event_t *event = (jit_debugger_linked_event_t *)_event;
event->next = 0;
jit_monitor_lock(&(dbg->queue_lock));
if(dbg->last_event)
{
dbg->last_event->next = event;
}
else
{
dbg->events = event;
}
dbg->last_event = event;
jit_monitor_signal(&(dbg->queue_lock));
jit_monitor_unlock(&(dbg->queue_lock));
}
/*@
* @deftypefun int jit_debugging_possible (void)
* Determine if debugging is possible. i.e. that threading is available
* and compatible with the debugger's requirements.
* @end deftypefun
@*/
int jit_debugging_possible(void)
{
return JIT_THREADS_SUPPORTED;
}
/*@
* @deftypefun jit_debugger_t jit_debugger_create (jit_context_t @var{context})
* Create a new debugger instance and attach it to a JIT @var{context}.
* If the context already has a debugger associated with it, then this
* function will return the previous debugger.
* @end deftypefun
@*/
jit_debugger_t jit_debugger_create(jit_context_t context)
{
jit_debugger_t dbg;
if(context)
{
if(context->debugger)
{
return context->debugger;
}
dbg = jit_cnew(struct jit_debugger);
if(!dbg)
{
return 0;
}
dbg->context = context;
context->debugger = dbg;
jit_monitor_create(&(dbg->queue_lock));
jit_monitor_create(&(dbg->run_lock));
return dbg;
}
else
{
return 0;
}
}
/*@
* @deftypefun void jit_debugger_destroy (jit_debugger_t @var{dbg})
* Destroy a debugger instance.
* @end deftypefun
@*/
void jit_debugger_destroy(jit_debugger_t dbg)
{
/* TODO */
}
/*@
* @deftypefun jit_context_t jit_debugger_get_context (jit_debugger_t @var{dbg})
* Get the JIT context that is associated with a debugger instance.
* @end deftypefun
@*/
jit_context_t jit_debugger_get_context(jit_debugger_t dbg)
{
if(dbg)
{
return dbg->context;
}
else
{
return 0;
}
}
/*@
* @deftypefun jit_debugger_t jit_debugger_from_context (jit_context_t @var{context})
* Get the debugger that is currently associated with a JIT @var{context},
* or NULL if there is no debugger associated with the context.
* @end deftypefun
@*/
jit_debugger_t jit_debugger_from_context(jit_context_t context)
{
if(context)
{
return context->debugger;
}
else
{
return 0;
}
}
/*@
* @deftypefun jit_debugger_thread_id_t jit_debugger_get_self (jit_debugger_t @var{dbg})
* Get the thread identifier associated with the current thread.
* The return values are normally values like 1, 2, 3, etc, allowing
* the user interface to report messages like "thread 3 has stopped
* at a breakpoint".
* @end deftypefun
@*/
jit_debugger_thread_id_t jit_debugger_get_self(jit_debugger_t dbg)
{
jit_thread_id_t id = jit_thread_self();
jit_debugger_thread_id_t thread;
thread = jit_debugger_get_thread(dbg, &id);
jit_thread_release_self(id);
return thread;
}
/*@
* @deftypefun jit_debugger_thread_id_t jit_debugger_get_thread (jit_debugger_t @var{dbg}, const void *@var{native_thread})
* Get the thread identifier for a specific native thread. The
* @var{native_thread} pointer is assumed to point at a block
* of memory containing a native thread handle. This would be a
* @code{pthread_t} on Pthreads platforms or a @code{HANDLE}
* on Win32 platforms. If the native thread has not been seen
* previously, then a new thread identifier is allocated.
* @end deftypefun
@*/
jit_debugger_thread_id_t jit_debugger_get_thread
(jit_debugger_t dbg, const void *native_thread)
{
/* TODO */
return 0;
}
/*@
* @deftypefun int jit_debugger_get_native_thread (jit_debugger_t @var{dbg}, jit_debugger_thread_id_t @var{thread}, void *@var{native_thread})
* Get the native thread handle associated with a debugger thread identifier.
* Returns non-zero if OK, or zero if the debugger thread identifier is not
* yet associated with a native thread handle.
* @end deftypefun
@*/
int jit_debugger_get_native_thread
(jit_debugger_t dbg, jit_debugger_thread_id_t thread,
void *native_thread)
{
jit_debugger_thread_t th;
lock_debugger(dbg);
th = get_specific_thread(dbg, thread);
if(th)
{
jit_memcpy(native_thread, &(th->native_id), sizeof(th->native_id));
unlock_debugger(dbg);
return 1;
}
else
{
unlock_debugger(dbg);
return 0;
}
}
/*@
* @deftypefun void jit_debugger_set_breakable (jit_debugger_t @var{dbg}, const void *@var{native_thread}, int @var{flag})
* Set a flag that indicates if a native thread can stop at breakpoints.
* If set to 1 (the default), breakpoints will be active on the thread.
* If set to 0, breakpoints will be ignored on the thread. Typically
* this is used to mark threads associated with the debugger's user
* interface, or the virtual machine's finalization thread, so that they
* aren't accidentally suspended by the debugger (which might cause a
* deadlock).
* @end deftypefun
@*/
void jit_debugger_set_breakable
(jit_debugger_t dbg, const void *native_thread, int flag)
{
jit_debugger_thread_t th;
jit_debugger_thread_id_t id;
id = jit_debugger_get_thread(dbg, native_thread);
lock_debugger(dbg);
th = get_specific_thread(dbg, id);
if(th)
{
th->breakable = flag;
}
unlock_debugger(dbg);
}
/*@
* @deftypefun void jit_debugger_attach_self (jit_debugger_t @var{dbg}, int @var{stop_immediately})
* Attach the current thread to a debugger. If @var{stop_immediately}
* is non-zero, then the current thread immediately suspends, waiting for
* the user to start it with @code{jit_debugger_run}. This function is
* typically called in a thread's startup code just before any "real work"
* is performed.
* @end deftypefun
@*/
void jit_debugger_attach_self(jit_debugger_t dbg, int stop_immediately)
{
jit_debugger_event_t *event;
jit_debugger_thread_t th;
lock_debugger(dbg);
th = get_current_thread(dbg);
if(th)
{
event = alloc_event();
if(event)
{
event->type = JIT_DEBUGGER_TYPE_ATTACH_THREAD;
event->thread = th->id;
event->data1 = (jit_nint)stop_immediately;
add_event(dbg, event);
libjit/jit/jit-debugger.c view on Meta::CPAN
{
th->run_type = JIT_RUN_TYPE_STOPPED;
suspend_thread(dbg, th);
}
else
{
th->run_type = JIT_RUN_TYPE_CONTINUE;
}
}
}
unlock_debugger(dbg);
}
/*@
* @deftypefun void jit_debugger_detach_self (jit_debugger_t @var{dbg})
* Detach the current thread from the debugger. This is typically
* called just before the thread exits.
* @end deftypefun
@*/
void jit_debugger_detach_self(jit_debugger_t dbg)
{
jit_debugger_event_t *event;
jit_debugger_thread_t th;
lock_debugger(dbg);
th = get_current_thread(dbg);
if(th)
{
event = alloc_event();
if(event)
{
event->type = JIT_DEBUGGER_TYPE_DETACH_THREAD;
event->thread = th->id;
add_event(dbg, event);
th->run_type = JIT_RUN_TYPE_DETACHED;
}
}
unlock_debugger(dbg);
}
/*@
* @deftypefun int jit_debugger_wait_event (jit_debugger_t @var{dbg}, jit_debugger_event_t *@var{event}, jit_nint @var{timeout})
* Wait for the next debugger event to arrive. Debugger events typically
* indicate breakpoints that have occurred. The @var{timeout} is in
* milliseconds, or -1 for an infinite timeout period. Returns non-zero
* if an event has arrived, or zero on timeout.
* @end deftypefun
@*/
int jit_debugger_wait_event
(jit_debugger_t dbg, jit_debugger_event_t *event, jit_int timeout)
{
jit_debugger_linked_event_t *levent;
jit_monitor_lock(&(dbg->queue_lock));
if((levent = dbg->events) == 0)
{
if(!jit_monitor_wait(&(dbg->queue_lock), timeout))
{
jit_monitor_unlock(&(dbg->queue_lock));
return 0;
}
levent = dbg->events;
}
libjit/jit/jit-debugger.c view on Meta::CPAN
if(!(levent->next))
{
dbg->last_event = 0;
}
jit_free(levent);
jit_monitor_unlock(&(dbg->queue_lock));
return 1;
}
/*@
* @deftypefun jit_debugger_breakpoint_id_t jit_debugger_add_breakpoint (jit_debugger_t @var{dbg}, jit_debugger_breakpoint_info_t @var{info})
* Add a hard breakpoint to a debugger instance. The @var{info} structure
* defines the conditions under which the breakpoint should fire.
* The fields of @var{info} are as follows:
*
* @table @code
* @item flags
* Flags that indicate which of the following fields should be matched.
* If a flag is not present, then all possible values of the field will match.
* Valid flags are @code{JIT_DEBUGGER_FLAG_THREAD},
* @code{JIT_DEBUGGER_FLAG_FUNCTION}, @code{JIT_DEBUGGER_FLAG_DATA1},
* and @code{JIT_DEBUGGER_FLAG_DATA2}.
libjit/jit/jit-debugger.c view on Meta::CPAN
* @item JIT_DEBUGGER_DATA1_LEAVE
* Breakpoint location that corresponds to the end of a function, just
* prior to a @code{return} statement. This is used to determine where
* to continue to upon a "finish".
*
* @item JIT_DEBUGGER_DATA1_THROW
* Breakpoint location that corresponds to an exception throw.
* @end table
* @end deftypefun
@*/
jit_debugger_breakpoint_id_t jit_debugger_add_breakpoint
(jit_debugger_t dbg, jit_debugger_breakpoint_info_t info)
{
/* TODO */
return 0;
}
/*@
* @deftypefun void jit_debugger_remove_breakpoint (jit_debugger_t @var{dbg}, jit_debugger_breakpoint_id_t @var{id})
* Remove a previously defined breakpoint from a debugger instance.
* @end deftypefun
@*/
void jit_debugger_remove_breakpoint
(jit_debugger_t dbg, jit_debugger_breakpoint_id_t id)
{
/* TODO */
}
/*@
* @deftypefun void jit_debugger_remove_all_breakpoints (jit_debugger_t @var{dbg})
* Remove all breakpoints from a debugger instance.
* @end deftypefun
@*/
void jit_debugger_remove_all_breakpoints(jit_debugger_t dbg)
{
/* TODO */
}
/*@
* @deftypefun int jit_debugger_is_alive (jit_debugger_t @var{dbg}, jit_debugger_thread_id_t @var{thread})
* Determine if a particular thread is still alive.
* @end deftypefun
@*/
int jit_debugger_is_alive(jit_debugger_t dbg, jit_debugger_thread_id_t thread)
{
/* TODO */
return 1;
}
/*@
* @deftypefun int jit_debugger_is_running (jit_debugger_t @var{dbg}, jit_debugger_thread_id_t @var{thread})
* Determine if a particular thread is currently running (non-zero) or
* stopped (zero).
* @end deftypefun
@*/
int jit_debugger_is_running(jit_debugger_t dbg, jit_debugger_thread_id_t thread)
{
jit_debugger_thread_t th;
int flag = 0;
lock_debugger(dbg);
th = get_specific_thread(dbg, thread);
if(th)
{
flag = (th->run_type != JIT_RUN_TYPE_STOPPED);
}
unlock_debugger(dbg);
return flag;
}
/*@
* @deftypefun void jit_debugger_run (jit_debugger_t @var{dbg}, jit_debugger_thread_id_t @var{thread})
* Start the specified thread running, or continue from the last breakpoint.
*
* This function, and the others that follow, sends a request to the specified
* thread and then returns to the caller immediately.
* @end deftypefun
@*/
void jit_debugger_run(jit_debugger_t dbg, jit_debugger_thread_id_t thread)
{
jit_debugger_thread_t th;
lock_debugger(dbg);
th = get_specific_thread(dbg, thread);
if(th && th->run_type == JIT_RUN_TYPE_STOPPED)
{
th->run_type = JIT_RUN_TYPE_CONTINUE;
wakeup_all(dbg);
}
unlock_debugger(dbg);
}
/*@
* @deftypefun void jit_debugger_step (jit_debugger_t @var{dbg}, jit_debugger_thread_id_t @var{thread})
* Step over a single line of code. If the line performs a method call,
* then this will step into the call. The request will be ignored if
* the thread is currently running.
* @end deftypefun
@*/
void jit_debugger_step(jit_debugger_t dbg, jit_debugger_thread_id_t thread)
{
jit_debugger_thread_t th;
lock_debugger(dbg);
th = get_specific_thread(dbg, thread);
if(th && th->run_type == JIT_RUN_TYPE_STOPPED)
{
th->run_type = JIT_RUN_TYPE_STEP;
wakeup_all(dbg);
}
unlock_debugger(dbg);
}
/*@
* @deftypefun void jit_debugger_next (jit_debugger_t @var{dbg}, jit_debugger_thread_id_t @var{thread})
* Step over a single line of code but do not step into method calls.
* The request will be ignored if the thread is currently running.
* @end deftypefun
@*/
void jit_debugger_next(jit_debugger_t dbg, jit_debugger_thread_id_t thread)
{
jit_debugger_thread_t th;
lock_debugger(dbg);
th = get_specific_thread(dbg, thread);
if(th && th->run_type == JIT_RUN_TYPE_STOPPED)
{
th->run_type = JIT_RUN_TYPE_NEXT;
wakeup_all(dbg);
}
unlock_debugger(dbg);
}
/*@
* @deftypefun void jit_debugger_finish (jit_debugger_t @var{dbg}, jit_debugger_thread_id_t @var{thread})
* Keep running until the end of the current function. The request will
* be ignored if the thread is currently running.
* @end deftypefun
@*/
void jit_debugger_finish(jit_debugger_t dbg, jit_debugger_thread_id_t thread)
{
jit_debugger_thread_t th;
lock_debugger(dbg);
th = get_specific_thread(dbg, thread);
if(th && th->run_type == JIT_RUN_TYPE_STOPPED)
{
th->run_type = JIT_RUN_TYPE_FINISH;
wakeup_all(dbg);
}
unlock_debugger(dbg);
}
/*@
* @deftypefun void jit_debugger_break (jit_debugger_t @var{dbg})
* Force an explicit user breakpoint at the current location within the
* current thread. Control returns to the caller when the debugger
* calls one of the above "run" or "step" functions in another thread.
* @end deftypefun
@*/
void jit_debugger_break(jit_debugger_t dbg)
{
jit_debugger_event_t *event;
jit_debugger_thread_t th;
lock_debugger(dbg);
th = get_current_thread(dbg);
if(th && th->breakable)
{
event = alloc_event();
if(event)
{
th->run_type = JIT_RUN_TYPE_STOPPED;
th->find_func = 0;
th->last_data1 = 0;
th->last_func_data1 = 0;
event->type = JIT_DEBUGGER_TYPE_USER_BREAKPOINT;
event->thread = th->id;
event->trace = jit_exception_get_stack_trace();
add_event(dbg, event);
suspend_thread(dbg, th);
}
}
unlock_debugger(dbg);
}
/*@
* @deftypefun void jit_debugger_quit (jit_debugger_t @var{dbg})
* Sends a request to the thread that called @code{jit_debugger_wait_event}
* indicating that the debugger should quit.
* @end deftypefun
@*/
void jit_debugger_quit(jit_debugger_t dbg)
{
jit_debugger_event_t *event;
lock_debugger(dbg);
event = alloc_event();
if(event)
{
event->type = JIT_DEBUGGER_TYPE_QUIT;
add_event(dbg, event);
}
unlock_debugger(dbg);
}
/*@
* @deftypefun jit_debugger_hook_func jit_debugger_set_hook (jit_context_t @var{context}, jit_debugger_hook_func @var{hook})
* Set a debugger hook on a JIT context. Returns the previous hook.
*
* Debug hooks are a very low-level breakpoint mechanism. Upon reaching each
* breakpoint in a function, a user-supplied hook function is called.
* It is up to the hook function to decide whether to stop execution
* or to ignore the breakpoint. The hook function has the following
* prototype:
*
* @example
* void hook(jit_function_t func, jit_nint data1, jit_nint data2);
* @end example
*
* The @code{func} argument indicates the function that the breakpoint
* occurred within. The @code{data1} and @code{data2} arguments are
* those supplied to @code{jit_insn_mark_breakpoint}. The debugger can use
* these values to indicate information about the breakpoint's type
* and location.
*
* Hook functions can be used for other purposes besides breakpoint
* debugging. For example, a program could be instrumented with hooks
* that tally up the number of times that each function is called,
* or which profile the amount of time spent in each function.
*
* By convention, @code{data1} values less than 10000 are intended for
* use by user-defined hook functions. Values of 10000 and greater are
* reserved for the full-blown debugger system described earlier.
* @end deftypefun
@*/
jit_debugger_hook_func jit_debugger_set_hook
(jit_context_t context, jit_debugger_hook_func hook)
{
jit_debugger_hook_func prev;
if(context)
{
prev = context->debug_hook;
context->debug_hook = hook;
return prev;
}
else
{
return 0;
}
}
void _jit_debugger_hook(jit_function_t func, jit_nint data1, jit_nint data2)
{
jit_context_t context;
jit_debugger_t dbg;
jit_debugger_thread_t th;
jit_debugger_event_t *event;
int stop;
/* Find the context and look for a user-supplied debug hook */
context = func->context;
if(context->debug_hook)
{
(*(context->debug_hook))(func, data1, data2);
}
/* Ignore breakpoints with data1 values less than 10000. These are
presumed to be handled by a user-supplied debug hook instead */
if(data1 < JIT_DEBUGGER_DATA1_FIRST)
{
return;
}
/* Determine if there is a debugger attached to the context */
dbg = context->debugger;
if(!dbg)
{
return;
}
/* Lock down the debugger while we do this */
lock_debugger(dbg);
/* Get the current thread's information block */
th = get_current_thread(dbg);
if(!th || !(th->breakable))
{
unlock_debugger(dbg);
return;
}
/* Determine if there is a hard breakpoint at this location */
/* TODO */
/* Determine if we are looking for a soft breakpoint */
stop = 0;
switch(th->run_type)
{
libjit/jit/jit-debugger.c view on Meta::CPAN
event->function = func;
event->data1 = data1;
event->data2 = data2;
event->trace = jit_exception_get_stack_trace();
add_event(dbg, event);
suspend_thread(dbg, th);
}
}
/* Unlock and exit */
unlock_debugger(dbg);
}
libjit/jit/jit-dump.c view on Meta::CPAN
/*
* jit-dump.c - Functions for dumping JIT structures, for debugging.
*
* Copyright (C) 2004 Southern Storm Software, Pty Ltd.
*
* This file is part of the libjit library.
*
* The libjit library is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation, either version 2.1 of
* the License, or (at your option) any later version.
*
libjit/jit/jit-elf-defs.h view on Meta::CPAN
#define DT_SYMENT 11 /* Size of one symbol table entry */
#define DT_INIT 12 /* Address of init function */
#define DT_FINI 13 /* Address of termination function */
#define DT_SONAME 14 /* Name of shared object */
#define DT_RPATH 15 /* Library search path (deprecated) */
#define DT_SYMBOLIC 16 /* Start symbol search here */
#define DT_REL 17 /* Address of Rel relocs */
#define DT_RELSZ 18 /* Total size of Rel relocs */
#define DT_RELENT 19 /* Size of one Rel reloc */
#define DT_PLTREL 20 /* Type of reloc in PLT */
#define DT_DEBUG 21 /* For debugging; unspecified */
#define DT_TEXTREL 22 /* Reloc might modify .text */
#define DT_JMPREL 23 /* Address of PLT relocs */
#define DT_BIND_NOW 24 /* Process relocations of object */
#define DT_INIT_ARRAY 25 /* Array with addresses of init fct */
#define DT_FINI_ARRAY 26 /* Array with addresses of fini fct */
#define DT_INIT_ARRAYSZ 27 /* Size in bytes of DT_INIT_ARRAY */
#define DT_FINI_ARRAYSZ 28 /* Size in bytes of DT_FINI_ARRAY */
#define DT_RUNPATH 29 /* Library search path */
#define DT_FLAGS 30 /* Flags for the object being loaded */
#define DT_ENCODING 32 /* Start of encoded range */
libjit/jit/jit-elf-defs.h view on Meta::CPAN
#define SHN_MIPS_SCOMMON 0xff03 /* Small common symbols */
#define SHN_MIPS_SUNDEFINED 0xff04 /* Small undefined symbols */
/* Legal values for sh_type field of Elf32_Shdr. */
#define SHT_MIPS_LIBLIST 0x70000000 /* Shared objects used in link */
#define SHT_MIPS_MSYM 0x70000001
#define SHT_MIPS_CONFLICT 0x70000002 /* Conflicting symbols */
#define SHT_MIPS_GPTAB 0x70000003 /* Global data area sizes */
#define SHT_MIPS_UCODE 0x70000004 /* Reserved for SGI/MIPS compilers */
#define SHT_MIPS_DEBUG 0x70000005 /* MIPS ECOFF debugging information*/
#define SHT_MIPS_REGINFO 0x70000006 /* Register usage information */
#define SHT_MIPS_PACKAGE 0x70000007
#define SHT_MIPS_PACKSYM 0x70000008
#define SHT_MIPS_RELD 0x70000009
#define SHT_MIPS_IFACE 0x7000000b
#define SHT_MIPS_CONTENT 0x7000000c
#define SHT_MIPS_OPTIONS 0x7000000d /* Miscellaneous options. */
#define SHT_MIPS_SHDR 0x70000010
#define SHT_MIPS_FDESC 0x70000011
#define SHT_MIPS_EXTSYM 0x70000012
libjit/jit/jit-elf-defs.h view on Meta::CPAN
#define SHT_MIPS_PDESC 0x70000014
#define SHT_MIPS_LOCSYM 0x70000015
#define SHT_MIPS_AUXSYM 0x70000016
#define SHT_MIPS_OPTSYM 0x70000017
#define SHT_MIPS_LOCSTR 0x70000018
#define SHT_MIPS_LINE 0x70000019
#define SHT_MIPS_RFDESC 0x7000001a
#define SHT_MIPS_DELTASYM 0x7000001b
#define SHT_MIPS_DELTAINST 0x7000001c
#define SHT_MIPS_DELTACLASS 0x7000001d
#define SHT_MIPS_DWARF 0x7000001e /* DWARF debugging information. */
#define SHT_MIPS_DELTADECL 0x7000001f
#define SHT_MIPS_SYMBOL_LIB 0x70000020
#define SHT_MIPS_EVENTS 0x70000021 /* Event section. */
#define SHT_MIPS_TRANSLATE 0x70000022
#define SHT_MIPS_PIXIE 0x70000023
#define SHT_MIPS_XLATE 0x70000024
#define SHT_MIPS_XLATE_DEBUG 0x70000025
#define SHT_MIPS_WHIRL 0x70000026
#define SHT_MIPS_EH_REGION 0x70000027
#define SHT_MIPS_XLATE_OLD 0x70000028
libjit/jit/jit-elf-defs.h view on Meta::CPAN
#define ODK_TAGS 6 /* reserve space for desktop tools to write. */
#define ODK_HWAND 7 /* HW workarounds. 'AND' bits when merging. */
#define ODK_HWOR 8 /* HW workarounds. 'OR' bits when merging. */
/* Values for `info' in Elf_Options for ODK_EXCEPTIONS entries. */
#define OEX_FPU_MIN 0x1f /* FPE's which MUST be enabled. */
#define OEX_FPU_MAX 0x1f00 /* FPE's which MAY be enabled. */
#define OEX_PAGE0 0x10000 /* page zero must be mapped. */
#define OEX_SMM 0x20000 /* Force sequential memory mode? */
#define OEX_FPDBUG 0x40000 /* Force floating point debug mode? */
#define OEX_PRECISEFP OEX_FPDBUG
#define OEX_DISMISS 0x80000 /* Dismiss invalid address faults? */
#define OEX_FPU_INVAL 0x10
#define OEX_FPU_DIV0 0x08
#define OEX_FPU_OFLO 0x04
#define OEX_FPU_UFLO 0x02
#define OEX_FPU_INEX 0x01
/* Masks for `info' in Elf_Options for an ODK_HWPATCH entry. */
libjit/jit/jit-elf-defs.h view on Meta::CPAN
/* Alpha specific definitions. */
/* Legal values for e_flags field of Elf64_Ehdr. */
#define EF_ALPHA_32BIT 1 /* All addresses must be < 2GB. */
#define EF_ALPHA_CANRELAX 2 /* Relocations for relaxing exist. */
/* Legal values for sh_type field of Elf64_Shdr. */
/* These two are primerily concerned with ECOFF debugging info. */
#define SHT_ALPHA_DEBUG 0x70000001
#define SHT_ALPHA_REGINFO 0x70000002
/* Legal values for sh_flags field of Elf64_Shdr. */
#define SHF_ALPHA_GPREL 0x10000000
/* Legal values for st_other field of Elf64_Sym. */
#define STO_ALPHA_NOPV 0x80 /* No PV required. */
#define STO_ALPHA_STD_GPLOAD 0x88 /* PV only used for initial ldgp. */
libjit/jit/jit-elf-read.c view on Meta::CPAN
readelf->symbol_hash_buckets = readelf->symbol_hash[0];
}
}
}
else
{
readelf->symbol_table = 0;
}
}
/* Bail out if we don't need to print debugging information */
if((flags & JIT_READELF_FLAG_DEBUG) == 0)
{
return;
}
/* Iterate through the ".dynamic" section, dumping all that we find */
dynamic_iter_init(&iter, readelf);
while(dynamic_iter_next(&iter, &type, &value))
{
switch(type)
libjit/jit/jit-elf-read.c view on Meta::CPAN
* There is insufficient memory to open the ELF binary.
* @end table
*
* The following flags may be supplied to alter the manner in which
* the ELF binary is loaded:
*
* @table @code
* @vindex JIT_READELF_FLAG_FORCE
* @item JIT_READELF_FLAG_FORCE
* Force @code{jit_readelf_open} to open the ELF binary, even if
* the architecture does not match this machine. Useful for debugging.
*
* @vindex JIT_READELF_FLAG_DEBUG
* @item JIT_READELF_FLAG_DEBUG
* Print additional debug information to stdout.
* @end table
* @end deftypefun
@*/
int jit_readelf_open(jit_readelf_t *_readelf, const char *filename, int flags)
{
int fd;
Elf_Ehdr ehdr;
Elf_Phdr *phdr;
Elf_Shdr *shdr;
jit_elf_info_t elf_info;
libjit/jit/jit-elf-read.c view on Meta::CPAN
{
readelf->regular_strings =
(char *)jit_readelf_map_vaddr(readelf, shdr->sh_addr);
}
if(readelf->regular_strings)
{
readelf->regular_strings_size = (jit_nuint)(shdr->sh_size);
}
}
/* Dump debug information about the program segments and sections */
if((flags & JIT_READELF_FLAG_DEBUG) != 0)
{
printf("header: machine=%d, abi=%d, abi_version=%d\n",
(int)(ehdr.e_machine), (int)(ehdr.e_ident[EI_OSABI]),
(int)(ehdr.e_ident[EI_ABIVERSION]));
for(index = 0; index < ehdr.e_phnum; ++index)
{
phdr = get_phdr(readelf, index);
if(phdr)
{
libjit/jit/jit-elf-read.c view on Meta::CPAN
}
}
return 0;
}
/*@
* @deftypefun {void *} jit_readelf_get_section_by_type (jit_readelf_t @var{readelf}, jit_int @var{type}, jit_nuint *@var{size})
* Get a particular section using its raw ELF section type (i.e. one of
* the @code{SHT_*} constants in @code{jit-elf-defs.h}). This is mostly
* for internal use, but some virtual machines may find it useful for
* debugging purposes.
* @end deftypefun
@*/
void *jit_readelf_get_section_by_type
(jit_readelf_t readelf, jit_int type, jit_nuint *size)
{
unsigned int index;
Elf_Shdr *shdr;
if(!readelf)
{
return 0;
libjit/jit/jit-insn.c view on Meta::CPAN
last = _jit_block_get_last(block);
if (last && last->opcode == JIT_OP_MARK_OFFSET)
{
last->value1 = value;
return 1;
}
return create_unary_note(func, JIT_OP_MARK_OFFSET, value);
}
/* Documentation is in jit-debugger.c */
int jit_insn_mark_breakpoint_variable
(jit_function_t func, jit_value_t data1, jit_value_t data2)
{
#if defined(JIT_BACKEND_INTERP)
/* Use the "mark_breakpoint" instruction for the interpreter */
if(!jit_insn_new_block(func))
{
return 0;
}
return create_note(func, JIT_OP_MARK_BREAKPOINT, data1, data2);
#else
/* Insert a call to "_jit_debugger_hook" on native platforms */
jit_type_t params[3];
jit_type_t signature;
jit_value_t values[3];
params[0] = jit_type_void_ptr;
params[1] = jit_type_nint;
params[2] = jit_type_nint;
signature = jit_type_create_signature
(jit_abi_cdecl, jit_type_void, params, 3, 0);
if(!signature)
{
return 0;
}
if((values[0] = jit_value_create_nint_constant
(func, jit_type_void_ptr, (jit_nint)func)) == 0)
{
jit_type_free(signature);
return 0;
}
values[1] = data1;
values[2] = data2;
jit_insn_call_native(func, "_jit_debugger_hook", (void *)_jit_debugger_hook,
signature, values, 3, JIT_CALL_NOTHROW);
jit_type_free(signature);
return 1;
#endif
}
/* Documentation is in jit-debugger.c */
int jit_insn_mark_breakpoint
(jit_function_t func, jit_nint data1, jit_nint data2)
{
jit_value_t value1;
jit_value_t value2;
value1 = jit_value_create_nint_constant(func, jit_type_nint, data1);
value2 = jit_value_create_nint_constant(func, jit_type_nint, data2);
if(value1 && value2)
libjit/jit/jit-internal.h view on Meta::CPAN
jit_meta_t meta;
/* ELF binaries that have been loaded into this context */
jit_readelf_t elf_binaries;
/* Table of symbols that have been registered with this context */
jit_regsym_t *registered_symbols;
int num_registered_symbols;
/* Debugger support */
jit_debugger_hook_func debug_hook;
jit_debugger_t debugger;
/* On-demand compilation driver */
jit_on_demand_driver_func on_demand_driver;
};
void *_jit_malloc_exec(unsigned int size);
void _jit_free_exec(void *ptr, unsigned int size);
void _jit_flush_exec(void *ptr, unsigned int size);
void _jit_memory_lock(jit_context_t context);
libjit/jit/jit-internal.h view on Meta::CPAN
* Get the correct opcode to use for a "store" instruction.
* We assume that the instructions are laid out as "byte",
* "short", "int", "long", "float32", "float64", "nfloat",
* and "struct".
*/
int _jit_store_opcode(int base_opcode, int small_base, jit_type_t type);
/*
* Function that is called upon each breakpoint location.
*/
void _jit_debugger_hook(jit_function_t func, jit_nint data1, jit_nint data2);
/*
* Internal structure of a type descriptor.
*/
struct jit_component
{
jit_type_t type;
jit_nuint offset;
char *name;
};
libjit/jit/jit-interp.c view on Meta::CPAN
* Debugging support.
******************************************************************/
VMCASE(JIT_OP_MARK_BREAKPOINT):
{
/* Process a marked breakpoint within the current function */
tempptr = (void *)VM_NINT_ARG;
tempptr2 = (void *)VM_NINT_ARG2;
VM_MODIFY_PC(3);
_jit_backtrace_push(&call_trace, pc);
_jit_debugger_hook
(func->func, (jit_nint)tempptr, (jit_nint)tempptr2);
_jit_backtrace_pop();
}
VMBREAK;
/******************************************************************
* Opcodes that aren't used by the interpreter. These are replaced
* by more specific instructions during function compilation.
******************************************************************/
libjit/jit/jit-memory-cache.c view on Meta::CPAN
method. Normally these regions correspond to exception "try" blocks, or
regular code between "try" blocks.
The jit_cache_method blocks are organised into a red-black tree, which
is used to perform fast lookups by address (_jit_cache_get_method). These
lookups are used when walking the stack during exceptions or security
processing.
Each method can also have offset information associated with it, to map
between native code addresses and offsets within the original bytecode.
This is typically used to support debugging. Offset information is stored
as auxiliary data, attached to the jit_cache_method block.
Threading issues
----------------
Writing a method to the cache, querying a method by address, or querying
offset information for a method, are not thread-safe. The caller should
arrange for a cache lock to be acquired prior to performing these
operations.
libjit/jit/jit-reg-alloc.c view on Meta::CPAN
/*@
The @code{libjit} library provides a number of functions for
performing register allocation within basic blocks so that you
mostly don't have to worry about it:
@*/
/*
* Dump debug information about the register allocation state.
*/
#undef JIT_REG_DEBUG
/*
* Minimum number of times a candidate must be used before it
* is considered worthy of putting in a global register.
*/
#define JIT_MIN_USED 3
/*
libjit/jit/jit-reg-class.h view on Meta::CPAN
#ifdef __cplusplus
extern "C" {
#endif
/*
* Information about a register class.
*/
typedef struct
{
const char *name; /* Name of the register class, for debugging */
int flags; /* Register flags */
int num_regs; /* The number of registers in the class */
int regs[1]; /* JIT_REG_INFO index for each register */
} _jit_regclass_t;
/* Create a register class. */
_jit_regclass_t *_jit_regclass_create(const char *name, int flags, int num_regs, ...);
/* Combine two register classes into another one. */
libjit/jit/jit-rules-interp.c view on Meta::CPAN
Every rule header file needs to define the macro @code{JIT_REG_INFO} to
an array of values that represents the properties of the CPU's
registers. The @code{_jit_reg_info} array is populated with
these values. @code{JIT_NUM_REGS} defines the number of
elements in the array. Each element in the array has the
following members:
@table @code
@item name
The name of the register. This is used for debugging purposes.
@item cpu_reg
The raw CPU register number. Registers in @code{libjit} are
referred to by their pseudo register numbers, corresponding to
their index within @code{JIT_REG_INFO}. However, these pseudo
register numbers may not necessarily correspond to the register
numbers used by the actual CPU. This field provides a mapping.
@item other_reg
The second pseudo register in a 64-bit register pair, or -1 if
libjit/jit/jit-rules-x86-64.c view on Meta::CPAN
* Setup or teardown the x86 code output process.
*/
#define jit_cache_setup_output(needed) \
unsigned char *inst = gen->ptr; \
_jit_gen_check_space(gen, (needed))
#define jit_cache_end_output() \
gen->ptr = inst
/*
* Set this to 1 for debugging fixups
*/
#define DEBUG_FIXUPS 0
/*
* The maximum block size copied inline
*/
#define _JIT_MAX_MEMCPY_INLINE 0x40
/*
* va_list type as specified in x86_64 sysv abi version 0.99
libjit/jit/jit-rules.h view on Meta::CPAN
#ifdef __cplusplus
extern "C" {
#endif
/*
* Information about a register.
*/
typedef struct
{
const char *name; /* Name of the register, for debugging */
short cpu_reg; /* CPU register number */
short other_reg; /* Other register for a "long" pair, or -1 */
int flags; /* Flags that define the register type */
} jit_reginfo_t;
/*
* Register information flags.
*/
#define JIT_REG_WORD (1 << 0) /* Can be used for word values */
libjit/jit/jit-varint.c view on Meta::CPAN
{
jit_varint_data_t data;
/* Allocate a new jit_varint_data structure to hold the data */
data = jit_malloc(sizeof(struct jit_varint_data) + encoder->len);
if(!data)
{
return 0;
}
/* Copy the temporary debug data into the new structure */
jit_memcpy(data->data, encoder->buf, encoder->len);
/* Link the structure into the debug list */
data->next = 0;
if(encoder->last)
{
encoder->last->next = data;
}
else
{
encoder->data = data;
}
encoder->last = data;
/* Reset the temporary debug buffer */
encoder->len = 0;
return 1;
}
void
_jit_varint_init_encoder(jit_varint_encoder_t *encoder)
{
encoder->len = 0;
encoder->data = 0;
encoder->last = 0;
libjit/jit/jit-varint.c view on Meta::CPAN
/* Mark the end of the data */
encoder->buf[encoder->len++] = 0xFF;
/* Flush the data that we have collected so far */
return flush_encoder(encoder);
}
/*
* Compress a "long" value so that it takes up less bytes.
* This is used to store offsets within functions and
* debug line numbers, which are usually small integers.
*/
int
_jit_varint_encode_uint(jit_varint_encoder_t *encoder, jit_uint value)
{
if(encoder->len + 6 > sizeof(encoder->buf))
{
/* Overflow occurred: end current buffer */
if(!_jit_varint_encode_end(encoder))
{
return 0;