From: Jovi Zhangwei <jovi.zhangwei@gmail.com>
To: Ingo Molnar <mingo@redhat.com>, Steven Rostedt <rostedt@goodmis.org>
Cc: linux-kernel@vger.kernel.org,
Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Frederic Weisbecker <fweisbec@gmail.com>,
Andi Kleen <andi@firstfloor.org>,
Jovi Zhangwei <jovi.zhangwei@gmail.com>
Subject: [PATCH v2 24/29] ktap: add bytecode writer(tools/ktap/kp_bcwrite.c)
Date: Fri, 28 Mar 2014 10:45:19 -0400 [thread overview]
Message-ID: <1396017924-7754-25-git-send-email-jovi.zhangwei@gmail.com> (raw)
In-Reply-To: <1396017924-7754-1-git-send-email-jovi.zhangwei@gmail.com>
Bytecode writer and listing.
[root@localhost ktap]# ./ktap -b -e 'var s = {} s["key"] = 1'
-- BYTECODE -- (command line):0-1
0001 TNEW 0 0
0002 KSHORT 1 1
0003 TSETS 1 0 0 ; "key"
0004 RET0 0 1
Signed-off-by: Jovi Zhangwei <jovi.zhangwei@gmail.com>
---
tools/ktap/kp_bcwrite.c | 375 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 375 insertions(+)
create mode 100644 tools/ktap/kp_bcwrite.c
diff --git a/tools/ktap/kp_bcwrite.c b/tools/ktap/kp_bcwrite.c
new file mode 100644
index 0000000..ae5f948
--- /dev/null
+++ b/tools/ktap/kp_bcwrite.c
@@ -0,0 +1,375 @@
+/*
+ * Bytecode writer
+ *
+ * This file is part of ktap by Jovi Zhangwei.
+ *
+ * Copyright (C) 2012-2014 Jovi Zhangwei <jovi.zhangwei@gmail.com>.
+ *
+ * Copyright (C) 1994-2013 Lua.org, PUC-Rio.
+ * - The part of code in this file is copied from lua initially.
+ * - lua's MIT license is compatible with GPL.
+ *
+ * ktap is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * ktap is distributed in the hope 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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../../include/uapi/ktap/ktap_types.h"
+#include "kp_util.h"
+
+/* Context for bytecode writer. */
+typedef struct BCWriteCtx {
+ SBuf sb; /* Output buffer. */
+ ktap_proto_t *pt; /* Root prototype. */
+ ktap_writer wfunc; /* Writer callback. */
+ void *wdata; /* Writer callback data. */
+ int strip; /* Strip debug info. */
+ int status; /* Status from writer callback. */
+} BCWriteCtx;
+
+
+static char *bcwrite_uint32(char *p, uint32_t v)
+{
+ memcpy(p, &v, sizeof(uint32_t));
+ p += sizeof(uint32_t);
+ return p;
+}
+
+/* -- Bytecode writer ----------------------------------------------------- */
+
+/* Write a single constant key/value of a template table. */
+static void bcwrite_ktabk(BCWriteCtx *ctx, const ktap_val_t *o, int narrow)
+{
+ char *p = kp_buf_more(&ctx->sb, 1+10);
+ if (is_string(o)) {
+ const ktap_str_t *str = rawtsvalue(o);
+ int len = str->len;
+ p = kp_buf_more(&ctx->sb, 5+len);
+ p = bcwrite_uint32(p, BCDUMP_KTAB_STR+len);
+ p = kp_buf_wmem(p, getstr(str), len);
+ } else if (is_number(o)) {
+ p = bcwrite_uint32(p, BCDUMP_KTAB_NUM);
+ p = kp_buf_wmem(p, &nvalue(o), sizeof(ktap_number));
+ } else {
+ kp_assert(tvispri(o));
+ p = bcwrite_uint32(p, BCDUMP_KTAB_NIL+~itype(o));
+ }
+ setsbufP(&ctx->sb, p);
+}
+
+/* Write a template table. */
+static void bcwrite_ktab(BCWriteCtx *ctx, char *p, const ktap_tab_t *t)
+{
+ int narray = 0, nhash = 0;
+ if (t->asize > 0) { /* Determine max. length of array part. */
+ ptrdiff_t i;
+ ktap_val_t *array = t->array;
+ for (i = (ptrdiff_t)t->asize-1; i >= 0; i--)
+ if (!is_nil(&array[i]))
+ break;
+ narray = (int)(i+1);
+ }
+ if (t->hmask > 0) { /* Count number of used hash slots. */
+ int i, hmask = t->hmask;
+ ktap_node_t *node = t->node;
+ for (i = 0; i <= hmask; i++)
+ nhash += !is_nil(&node[i].val);
+ }
+ /* Write number of array slots and hash slots. */
+ p = bcwrite_uint32(p, narray);
+ p = bcwrite_uint32(p, nhash);
+ setsbufP(&ctx->sb, p);
+ if (narray) { /* Write array entries (may contain nil). */
+ int i;
+ ktap_val_t *o = t->array;
+ for (i = 0; i < narray; i++, o++)
+ bcwrite_ktabk(ctx, o, 1);
+ }
+ if (nhash) { /* Write hash entries. */
+ int i = nhash;
+ ktap_node_t *node = t->node + t->hmask;
+ for (;; node--)
+ if (!is_nil(&node->val)) {
+ bcwrite_ktabk(ctx, &node->key, 0);
+ bcwrite_ktabk(ctx, &node->val, 1);
+ if (--i == 0)
+ break;
+ }
+ }
+}
+
+/* Write GC constants of a prototype. */
+static void bcwrite_kgc(BCWriteCtx *ctx, ktap_proto_t *pt)
+{
+ int i, sizekgc = pt->sizekgc;
+ ktap_obj_t **kr = (ktap_obj_t **)pt->k - (ptrdiff_t)sizekgc;
+
+ for (i = 0; i < sizekgc; i++, kr++) {
+ ktap_obj_t *o = *kr;
+ int tp, need = 1;
+ char *p;
+
+ /* Determine constant type and needed size. */
+ if (o->gch.gct == ~KTAP_TSTR) {
+ tp = BCDUMP_KGC_STR + ((ktap_str_t *)o)->len;
+ need = 5 + ((ktap_str_t *)o)->len;
+ } else if (o->gch.gct == ~KTAP_TPROTO) {
+ kp_assert((pt->flags & PROTO_CHILD));
+ tp = BCDUMP_KGC_CHILD;
+ } else {
+ kp_assert(o->gch.gct == ~KTAP_TTAB);
+ tp = BCDUMP_KGC_TAB;
+ need = 1+2*5;
+ }
+
+ /* Write constant type. */
+ p = kp_buf_more(&ctx->sb, need);
+ p = bcwrite_uint32(p, tp);
+ /* Write constant data (if any). */
+ if (tp >= BCDUMP_KGC_STR) {
+ p = kp_buf_wmem(p, getstr((ktap_str_t *)o),
+ ((ktap_str_t *)o)->len);
+ } else if (tp == BCDUMP_KGC_TAB) {
+ bcwrite_ktab(ctx, p, (ktap_tab_t *)o);
+ continue;
+ }
+ setsbufP(&ctx->sb, p);
+ }
+}
+
+/* Write number constants of a prototype. */
+static void bcwrite_knum(BCWriteCtx *ctx, ktap_proto_t *pt)
+{
+ int i, sizekn = pt->sizekn;
+ const ktap_val_t *o = (ktap_val_t *)pt->k;
+ char *p = kp_buf_more(&ctx->sb, 10*sizekn);
+
+ for (i = 0; i < sizekn; i++, o++) {
+ if (is_number(o))
+ p = kp_buf_wmem(p, &nvalue(o), sizeof(ktap_number));
+ }
+ setsbufP(&ctx->sb, p);
+}
+
+/* Write bytecode instructions. */
+static char *bcwrite_bytecode(BCWriteCtx *ctx, char *p, ktap_proto_t *pt)
+{
+ int nbc = pt->sizebc-1; /* Omit the [JI]FUNC* header. */
+
+ p = kp_buf_wmem(p, proto_bc(pt)+1, nbc*(int)sizeof(BCIns));
+ return p;
+}
+
+/* Write prototype. */
+static void bcwrite_proto(BCWriteCtx *ctx, ktap_proto_t *pt)
+{
+ int sizedbg = 0;
+ char *p;
+
+ /* Recursively write children of prototype. */
+ if (pt->flags & PROTO_CHILD) {
+ ptrdiff_t i, n = pt->sizekgc;
+ ktap_obj_t **kr = (ktap_obj_t **)pt->k - 1;
+ for (i = 0; i < n; i++, kr--) {
+ ktap_obj_t *o = *kr;
+ if (o->gch.gct == ~KTAP_TPROTO)
+ bcwrite_proto(ctx, (ktap_proto_t *)o);
+ }
+ }
+
+ /* Start writing the prototype info to a buffer. */
+ p = kp_buf_need(&ctx->sb,
+ 5+4+6*5+(pt->sizebc-1)*(int)sizeof(BCIns)+pt->sizeuv*2);
+ p += 4; /* Leave room for final size. */
+
+ /* Write prototype header. */
+ *p++ = (pt->flags & (PROTO_CHILD|PROTO_VARARG|PROTO_FFI));
+ *p++ = pt->numparams;
+ *p++ = pt->framesize;
+ *p++ = pt->sizeuv;
+ p = bcwrite_uint32(p, pt->sizekgc);
+ p = bcwrite_uint32(p, pt->sizekn);
+ p = bcwrite_uint32(p, pt->sizebc-1);
+ if (!ctx->strip) {
+ if (proto_lineinfo(pt))
+ sizedbg = pt->sizept -
+ (int)((char *)proto_lineinfo(pt) - (char *)pt);
+ p = bcwrite_uint32(p, sizedbg);
+ if (sizedbg) {
+ p = bcwrite_uint32(p, pt->firstline);
+ p = bcwrite_uint32(p, pt->numline);
+ }
+ }
+
+ /* Write bytecode instructions and upvalue refs. */
+ p = bcwrite_bytecode(ctx, p, pt);
+ p = kp_buf_wmem(p, proto_uv(pt), pt->sizeuv*2);
+ setsbufP(&ctx->sb, p);
+
+ /* Write constants. */
+ bcwrite_kgc(ctx, pt);
+ bcwrite_knum(ctx, pt);
+
+ /* Write debug info, if not stripped. */
+ if (sizedbg) {
+ p = kp_buf_more(&ctx->sb, sizedbg);
+ p = kp_buf_wmem(p, proto_lineinfo(pt), sizedbg);
+ setsbufP(&ctx->sb, p);
+ }
+
+ /* Pass buffer to writer function. */
+ if (ctx->status == 0) {
+ int n = sbuflen(&ctx->sb) - 4;
+ char *q = sbufB(&ctx->sb);
+ p = bcwrite_uint32(q, n); /* Fill in final size. */
+ kp_assert(p == sbufB(&ctx->sb) + 4);
+ ctx->status = ctx->wfunc(q, n + 4, ctx->wdata);
+ }
+}
+
+/* Write header of bytecode dump. */
+static void bcwrite_header(BCWriteCtx *ctx)
+{
+ ktap_str_t *chunkname = proto_chunkname(ctx->pt);
+ const char *name = getstr(chunkname);
+ int len = chunkname->len;
+ char *p = kp_buf_need(&ctx->sb, 5+5+len);
+ *p++ = BCDUMP_HEAD1;
+ *p++ = BCDUMP_HEAD2;
+ *p++ = BCDUMP_HEAD3;
+ *p++ = BCDUMP_VERSION;
+ *p++ = (ctx->strip ? BCDUMP_F_STRIP : 0) + (KP_BE ? BCDUMP_F_BE : 0);
+
+ if (!ctx->strip) {
+ p = bcwrite_uint32(p, len);
+ p = kp_buf_wmem(p, name, len);
+ }
+ ctx->status = ctx->wfunc(sbufB(&ctx->sb),
+ (int)(p - sbufB(&ctx->sb)), ctx->wdata);
+}
+
+/* Write footer of bytecode dump. */
+static void bcwrite_footer(BCWriteCtx *ctx)
+{
+ if (ctx->status == 0) {
+ uint8_t zero = 0;
+ ctx->status = ctx->wfunc(&zero, 1, ctx->wdata);
+ }
+}
+
+/* Write bytecode for a prototype. */
+int kp_bcwrite(ktap_proto_t *pt, ktap_writer writer, void *data, int strip)
+{
+ BCWriteCtx ctx;
+
+ ctx.pt = pt;
+ ctx.wfunc = writer;
+ ctx.wdata = data;
+ ctx.strip = strip;
+ ctx.status = 0;
+
+ kp_buf_init(&ctx.sb);
+ kp_buf_need(&ctx.sb, 1024); /* Avoids resize for most prototypes. */
+ bcwrite_header(&ctx);
+ bcwrite_proto(&ctx, ctx.pt);
+ bcwrite_footer(&ctx);
+
+ kp_buf_free(&ctx.sb);
+ return ctx.status;
+}
+
+/* -- Bytecode dump ----------------------------------------------------- */
+
+static const char * const bc_names[] = {
+#define BCNAME(name, ma, mb, mc, mt) #name,
+ BCDEF(BCNAME)
+#undef BCNAME
+ NULL
+};
+
+static const uint16_t bc_mode[] = {
+ BCDEF(BCMODE)
+};
+
+static void dump_bytecode(ktap_proto_t *pt)
+{
+ int nbc = pt->sizebc - 1; /* Omit the FUNC* header. */
+ BCIns *ins = proto_bc(pt) + 1;
+ ktap_obj_t **kbase = pt->k;
+ int i;
+
+ printf("-- BYTECODE -- %s:%d-%d\n", getstr(pt->chunkname),
+ pt->firstline, pt->firstline + pt->numline);
+
+ for (i = 0; i < nbc; i++, ins++) {
+ int op = bc_op(*ins);
+
+ printf("%04d\t%s", i + 1, bc_names[op]);
+
+ printf("\t%d", bc_a(*ins));
+ if (bcmode_b(op) != BCMnone)
+ printf("\t%d", bc_b(*ins));
+
+ if (bcmode_hasd(op))
+ printf("\t%d", bc_d(*ins));
+ else
+ printf("\t%d", bc_c(*ins));
+
+ if (bcmode_b(op) == BCMstr || bcmode_c(op) == BCMstr) {
+ printf("\t ; ");
+ if (bcmode_d(op) == BCMstr) {
+ int idx = ~bc_d(*ins);
+ printf("\"%s\"", getstr((ktap_str_t *)kbase[idx]));
+ }
+ }
+ printf("\n");
+ }
+}
+
+static int function_nr = 0;
+
+void kp_dump_proto(ktap_proto_t *pt)
+{
+ printf("\n----------------------------------------------------\n");
+ printf("function proto %d:\n", function_nr++);
+ printf("numparams: %d\n", pt->numparams);
+ printf("framesize: %d\n", pt->framesize);
+ printf("sizebc: %d\n", pt->sizebc);
+ printf("sizekgc: %d\n", pt->sizekgc);
+ printf("sizekn: %d\n", pt->sizekn);
+ printf("sizept: %d\n", pt->sizept);
+ printf("sizeuv: %d\n", pt->sizeuv);
+ printf("firstline: %d\n", pt->firstline);
+ printf("numline: %d\n", pt->numline);
+
+ printf("has child proto: %d\n", pt->flags & PROTO_CHILD);
+ printf("has vararg: %d\n", pt->flags & PROTO_VARARG);
+ printf("has ILOOP: %d\n", pt->flags & PROTO_ILOOP);
+
+ dump_bytecode(pt);
+
+ /* Recursively dump children of prototype. */
+ if (pt->flags & PROTO_CHILD) {
+ ptrdiff_t i, n = pt->sizekgc;
+ ktap_obj_t **kr = (ktap_obj_t **)pt->k - 1;
+ for (i = 0; i < n; i++, kr--) {
+ ktap_obj_t *o = *kr;
+ if (o->gch.gct == ~KTAP_TPROTO)
+ kp_dump_proto((ktap_proto_t *)o);
+ }
+ }
+}
+
--
1.8.1.4
next prev parent reply other threads:[~2014-03-29 15:27 UTC|newest]
Thread overview: 46+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-03-28 14:44 [RFC PATCH v2 00/29] ktap: A lightweight dynamic tracing tool for Linux Jovi Zhangwei
2014-03-28 14:44 ` [PATCH v2 01/29] ktap: add tools/ktap/README.md file Jovi Zhangwei
2014-03-28 14:44 ` [PATCH v2 02/29] ktap: add ktap tutorial(tools/ktap/doc/tutorial.md) Jovi Zhangwei
2014-03-28 14:44 ` [PATCH v2 03/29] ktap: add sample scripts(tools/ktap/samples/*) Jovi Zhangwei
2014-03-28 14:44 ` [PATCH v2 04/29] ktap: add basic ktap types definition(include/uapi/ktap/ktap_types.h) Jovi Zhangwei
2014-03-28 14:45 ` [PATCH v2 05/29] ktap: add bytecode definition(include/uapi/ktap/ktap_bc.h) Jovi Zhangwei
2014-03-28 14:45 ` [PATCH v2 06/29] ktap: add ktap_arch.h and error header file(include/uapi/ktap/) Jovi Zhangwei
2014-03-28 14:45 ` [PATCH v2 07/29] ktap: add kernel module main entry(kernel/trace/ktap/ktap.[c|h]) Jovi Zhangwei
2014-03-28 14:45 ` [PATCH v2 08/29] ktap: add bytecode reader(kernel/trace/ktap/kp_bcread.[c|h]) Jovi Zhangwei
2014-03-30 2:47 ` Andi Kleen
2014-03-30 8:02 ` Jovi Zhangwei
2014-03-30 17:17 ` Andi Kleen
2014-03-31 2:05 ` Jovi Zhangwei
2014-03-28 14:45 ` [PATCH v2 09/29] ktap: add bytecode execution engine(kernel/trace/ktap/kp_vm.[c|h]) Jovi Zhangwei
2014-03-28 14:45 ` [PATCH v2 10/29] ktap: add string handling code(kernel/trace/ktap/kp_[str|mempool].[c|h]) Jovi Zhangwei
2014-03-30 3:50 ` Andi Kleen
2014-03-30 9:12 ` Jovi Zhangwei
2014-03-30 17:19 ` Andi Kleen
2014-03-31 2:35 ` Jovi Zhangwei
2014-03-28 14:45 ` [PATCH v2 11/29] ktap: add table handling code(kernel/trace/ktap/kp_tab.[c|h]) Jovi Zhangwei
2014-03-28 14:45 ` [PATCH v2 12/29] ktap: add generic object handling code(kernel/trace/ktap/kp_obj.[c|h]) Jovi Zhangwei
2014-03-30 3:56 ` Andi Kleen
2014-03-30 8:14 ` Jovi Zhangwei
2014-03-28 14:45 ` [PATCH v2 13/29] ktap: add ring buffer handling code(kernel/trace/ktap/kp_transport.[c|h]) Jovi Zhangwei
2014-03-30 3:58 ` Andi Kleen
2014-03-30 7:40 ` Jovi Zhangwei
2014-03-28 14:45 ` [PATCH v2 14/29] ktap: add events management(kernel/trace/ktap/kp_events.[c|h]) Jovi Zhangwei
2014-03-28 14:45 ` [PATCH v2 15/29] ktap: add built-in functions and library(kernel/trace/ktap/lib_*.c) Jovi Zhangwei
2014-03-28 14:45 ` [PATCH v2 16/29] ktap: add amalgamation build(kernel/trace/ktap/amalg.c) Jovi Zhangwei
2014-03-31 2:17 ` Li Zefan
2014-03-31 3:22 ` Jovi Zhangwei
2014-03-28 14:45 ` [PATCH v2 17/29] ktap: add Makefile for kernel module(kernel/trace/ktap/Makefile) Jovi Zhangwei
2014-03-28 14:45 ` [PATCH v2 18/29] ktap: add Kconfig(kernel/trace/ktap/Kconfig) Jovi Zhangwei
2014-03-28 14:45 ` [PATCH v2 19/29] ktap: add main file for ktap binary(tools/ktap/kp_main.c) Jovi Zhangwei
2014-03-28 14:45 ` [PATCH v2 20/29] ktap: add compiler(tools/ktap/kp_[lex|parse].[c|h]) Jovi Zhangwei
2014-03-28 14:45 ` [PATCH v2 21/29] ktap: add symbol handling code(tools/ktap/symbol.[c|h]) Jovi Zhangwei
2014-03-28 14:45 ` [PATCH v2 22/29] ktap: add events parse code(tools/ktap/kp_parse_events.c) Jovi Zhangwei
2014-03-28 14:45 ` [PATCH v2 23/29] ktap: add ring buffer reader(tools/ktap/kp_reader.c) Jovi Zhangwei
2014-03-28 14:45 ` Jovi Zhangwei [this message]
2014-03-28 14:45 ` [PATCH v2 25/29] ktap: add userspace util(tools/ktap/kp_util.c) Jovi Zhangwei
2014-03-28 14:45 ` [PATCH v2 26/29] ktap: add userspace binary Makefile(tools/ktap/Makefile) Jovi Zhangwei
2014-03-28 14:45 ` [PATCH v2 27/29] ktap: add testsuite and benchmark(tools/ktap/test/*) Jovi Zhangwei
2014-03-28 14:45 ` [PATCH v2 28/29] ktap: add vim syntax file(tools/ktap/vim/*) Jovi Zhangwei
2014-03-28 14:45 ` [PATCH v2 29/29] ktap: add COPYRIGHT file(tools/ktap/COPYRIGHT) Jovi Zhangwei
2014-03-30 1:00 ` [RFC PATCH v2 00/29] ktap: A lightweight dynamic tracing tool for Linux Andi Kleen
2014-03-30 9:18 ` Jovi Zhangwei
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1396017924-7754-25-git-send-email-jovi.zhangwei@gmail.com \
--to=jovi.zhangwei@gmail.com \
--cc=andi@firstfloor.org \
--cc=fweisbec@gmail.com \
--cc=gregkh@linuxfoundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=masami.hiramatsu.pt@hitachi.com \
--cc=mingo@redhat.com \
--cc=rostedt@goodmis.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®