jcov_crt.c
来自「This is a resource based on j2me embedde」· C语言 代码 · 共 615 行 · 第 1/2 页
C
615 行
/* * @(#)jcov_crt.c 1.8 06/10/10 * * Copyright 1990-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, 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 version 2 for more details (a copy is * included at /legal/license.txt). * * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions. * */#include "jcov.h"#include "jcov_util.h"#include "jcov_types.h"#include "jcov_error.h"#include "jcov_crt.h"#include "jcov_jvm.h"#define ASSRT(cond, n, ctx) if (!(cond)) { \ if ((ctx).hooked_class != NULL && ((ctx).hooked_class)->name != NULL) \ sprintf(info, "assertion failure #%d in class: %s", n, ((ctx).hooked_class)->name); \ else \ sprintf(info, "assertion failure #%d (class unknown)", n); \ jcov_error(info); \ exit(1); \ }#define READ_AND_CHECK(dest, bytes_total, ctx) \ dest = read##bytes_total##bytes(&((ctx).class_data), &((ctx).class_len), &err_code); \ if (err_code) { \ if ((ctx).hooked_class != NULL && ((ctx).hooked_class)->name != NULL) \ sprintf(info, "bad class format : %s", ((ctx).hooked_class)->name); \ else \ sprintf(info, "bad class format"); \ jcov_error(info); \ exit(1); \ }cov_item_t *cov_item_new(UINT16 pc, UINT8 type, UINT8 instr_type, INT32 line, INT32 pos) { cov_item_t *cov_item = (cov_item_t*)jcov_calloc(sizeof(cov_item_t)); cov_item->pc = pc; cov_item->type = type; cov_item->instr_type = instr_type; cov_item->where_line = line; cov_item->where_pos = pos; cov_item->count = 0; return cov_item;}static crt_entry_t *crt_entry_new(UINT16 pc_start, UINT16 pc_end, INT32 rng_start, INT32 rng_end, UINT16 flags) { crt_entry_t *crt_entry = (crt_entry_t*)jcov_calloc(sizeof(crt_entry_t)); crt_entry->pc_start = pc_start; crt_entry->pc_end = pc_end; crt_entry->rng_start = rng_start; crt_entry->rng_end = rng_end; crt_entry->flags = flags; return crt_entry;}/* Note: CRT_ANY is used to represent the logical OR'ed value of all possible CRT flags to be passed to the flags argument in get_crt_entry() below. */#define CRT_ANY ((UINT16)-1)static crt_entry_t *get_crt_entry(INT32 pc, jcov_list_t *map[], UINT16 flags) { jcov_list_t *l = map[pc]; for (; l != NULL; l = l->next) { crt_entry_t *e = (crt_entry_t*)l->elem; if (e->flags & flags) return e; } return NULL;}static cov_item_t *get_cov_item(INT32 pc, jcov_list_t *map[], UINT8 type) { jcov_list_t *l = map[pc]; for (; l != NULL; l = l->next) { cov_item_t *ci = (cov_item_t*)l->elem; if (ci->type == type) return ci; } return NULL;}static void gen_cov_for_if(UINT16 pc, crt_entry_t *ce, jcov_list_t *cov_map[], jcov_list_t *crt_map[], bin_class_context_t *context) { cov_item_t *cov_item; UINT8 opc; UINT16 targ_pc; UINT8 *code = context->code; UINT8 type = ce->flags & CRT_BRANCH_TRUE ? CT_BRANCH_FALSE : CT_BRANCH_TRUE; UINT8 itype; Bool is_if; opc = code[pc] & 0xFF; is_if = !(opc < opc_ifeq || (opc > opc_if_acmpne && opc < opc_ifnull) || opc > opc_ifnonnull); itype = is_if ? INSTR_IF : INSTR_ANY; cov_item = cov_item_new(pc, type, itype, ce->rng_start, ce->rng_end); add_to_list(&(cov_map[pc]), cov_item); type = type == CT_BRANCH_TRUE ? CT_BRANCH_FALSE : CT_BRANCH_TRUE; cov_item = cov_item_new(pc, type, itype, ce->rng_start, ce->rng_end); add_to_list(&(cov_map[pc]), cov_item); if (!is_if) return; targ_pc = pc + INT16_AT(code, pc + 1); if (get_cov_item(targ_pc, cov_map, CT_BLOCK) == NULL) { ce = get_crt_entry(targ_pc, crt_map, CRT_STATEMENT); if (ce != NULL) { cov_item = cov_item_new(targ_pc, CT_BLOCK, INSTR_ANY, ce->rng_start, ce->rng_end); add_to_list(&(cov_map[targ_pc]), cov_item); } } targ_pc = pc + get_instr_size(pc, code); if (get_cov_item(targ_pc, cov_map, CT_BLOCK) == NULL) { ce = get_crt_entry(targ_pc, crt_map, CRT_STATEMENT); if (ce != NULL) { cov_item = cov_item_new(targ_pc, CT_BLOCK, INSTR_ANY, ce->rng_start, ce->rng_end); add_to_list(&(cov_map[targ_pc]), cov_item); } }}static void gen_cov_for_switch(UINT8 *code, crt_entry_t *crt_entry, jcov_list_t *cov_list[], jcov_list_t *map[], bin_class_context_t *context) { INT32 n, off, def_off; UINT8 type; UINT16 cur_pc, i; char info[MAX_PATH_LEN]; crt_entry_t *ce = NULL; cov_item_t *def_item; UINT16 pc = crt_entry->pc_start; /* get remembered pc */ if (cov_list[pc] != NULL) { char *class = (context->hooked_class == NULL || context->hooked_class->name == NULL) ? "UNKNOWN" : context->hooked_class->name; sprintf(info, "invalid crt at switch instruction pc. Class: %s", class); jcov_error(info); } switch (code[pc]) { case opc_lookupswitch: cur_pc = (pc + 4) & (~3); off = INT32_AT(code, cur_pc) + pc; def_off = off; ce = get_crt_entry(off, map, CRT_FLOW_TARGET); if (ce == NULL) ce = get_crt_entry(off, map, CRT_ANY); if (ce == NULL) ce = crt_entry; ASSRT(ce != NULL, 20, *context); type = (ce->flags & CRT_FLOW_TARGET) ? CT_CASE : CT_SWITCH_WO_DEF; def_item = cov_item_new(pc, type, INSTR_LOOKUPSW, ce->rng_start, ce->rng_end); if (type == CT_SWITCH_WO_DEF && get_cov_item(off, cov_list, CT_BLOCK) == NULL) { /* workaround a compiler bug */ cov_item_t *ci = cov_item_new((UINT16)off, CT_BLOCK, INSTR_ANY, ce->rng_start, ce->rng_end); add_to_list(&(cov_list[off]), ci); } cur_pc += 4; n = INT32_AT(code, cur_pc); cur_pc += 4; for (i = 0; i < n; i++) { cur_pc += 4; off = INT32_AT(code, cur_pc) + pc; ce = get_crt_entry(off, map, CRT_FLOW_TARGET); if (ce == NULL) ce = get_crt_entry(off, map, CRT_ANY); ASSRT(ce != NULL || off == def_off, 21, *context); if (off != def_off) { cov_item_t *ci = cov_item_new(pc, CT_CASE, INSTR_ANY, ce->rng_start, ce->rng_end); add_to_list_end(&(cov_list[pc]), ci); } cur_pc += 4; } add_to_list_end(&(cov_list[pc]), def_item); break; case opc_tableswitch: cur_pc = (pc + 4) & (~3); off = INT32_AT(code, cur_pc) + pc; def_off = off; ce = get_crt_entry(off, map, CRT_FLOW_TARGET); if (ce == NULL) ce = get_crt_entry(off, map, CRT_ANY); if (ce == NULL) ce = crt_entry; ASSRT(ce != NULL, 22, *context); type = (ce->flags & CRT_FLOW_TARGET) ? CT_CASE : CT_SWITCH_WO_DEF; def_item = cov_item_new(pc, type, INSTR_TABLESW, ce->rng_start, ce->rng_end); if (type == CT_SWITCH_WO_DEF && get_cov_item(off, cov_list, CT_BLOCK) == NULL) { /* workaround a compiler bug */ cov_item_t *ci = cov_item_new((UINT16)off, CT_BLOCK, INSTR_ANY, ce->rng_start, ce->rng_end); add_to_list(&(cov_list[off]), ci); } cur_pc += 4; n = INT32_AT(code, cur_pc + 4) - INT32_AT(code, cur_pc) + 1; cur_pc += 8; for (i = 0; i < n; i++) { cov_item_t *ci; off = INT32_AT(code, cur_pc) + pc; ce = get_crt_entry(off, map, CRT_FLOW_TARGET); if (ce == NULL) ce = get_crt_entry(off, map, CRT_ANY); ASSRT(ce != NULL || off == def_off, 23, *context); type = (off != def_off); ci = cov_item_new(pc, CT_CASE, INSTR_ANY, type ? ce->rng_start : 0, type ? ce->rng_end : 0); add_to_list_end(&(cov_list[pc]), ci); cur_pc += 4; } add_to_list_end(&(cov_list[pc]), def_item); break; default: ASSRT(0, 24, *context); }}static void gen_cov_table(jcov_list_t **cov_list, jcov_method_t *meth) { SSIZE_T n = 0; SSIZE_T code_len = meth->pc_cache_size; int i; for (i = 0; i < code_len; n += list_size(cov_list[i]), i++); meth->covtable_size = n; if (n == 0) return; meth->pc_cache = (int*)jcov_calloc(code_len * sizeof(int)); meth->covtable = (cov_item_t*)jcov_calloc(n * sizeof(cov_item_t)); for (i = 0, n = 0; i < code_len; i++) { jcov_list_t *l = cov_list[i]; for (; l != NULL; l = l->next, n++) { cov_item_t *ci = (cov_item_t*)l->elem; meth->covtable[n] = *ci; if (l->next == NULL) meth->pc_cache[i] = n + 1; } }}static void gen_cov_for_catch(UINT16 catch_pc, jcov_list_t **cov_map, jcov_list_t **crt_map, UINT8 *code, SSIZE_T code_len) { crt_entry_t *res = NULL; int catch_instr_len = 0; Bool work_around = 0; cov_item_t *cov_item; if (catch_pc >= code_len) return; /* konst: error? */ res = get_crt_entry(catch_pc, crt_map, CRT_STATEMENT); if (res == NULL) res = get_crt_entry(catch_pc, crt_map, CRT_BLOCK); if (res == NULL) { /* konst: currently, CRT entry's start PC for a catch handler is 1 instruction greater */ /* than actual catch handler's offset in bytecode - a compiler bug */ catch_instr_len = opc_lengths[code[catch_pc] & 0xFF]; if (catch_instr_len <= 0 || catch_instr_len > 5) return; /* konst: error? */ catch_pc += catch_instr_len; if (catch_pc >= code_len) return; /* konst: error? */ res = get_crt_entry(catch_pc, crt_map, CRT_STATEMENT); if (res == NULL) res = get_crt_entry(catch_pc, crt_map, CRT_BLOCK); if (res == NULL) return; /* konst: error? */ work_around = 1; } cov_item = get_cov_item(catch_pc, cov_map, CT_BLOCK); if (cov_item != NULL && work_around) { cov_item->pc = catch_pc - catch_instr_len; return; } if (cov_item == NULL) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?