blob: 8db5a72f86cebbcc71bd2cf187f47682ce36d6f3 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007-2020 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
* You may elect to redistribute this code under either of these licenses.
*
* Contributors:
* Wind River Systems - initial API and implementation
*******************************************************************************/
/*
* This module contains definitions of target CPU registers and stack frames.
*/
#include <tcf/config.h>
#if ENABLE_DebugContext
#include <stddef.h>
#include <stdio.h>
#include <assert.h>
#include <tcf/framework/cpudefs.h>
#include <tcf/framework/errors.h>
#include <tcf/framework/context.h>
#include <tcf/framework/myalloc.h>
#include <tcf/framework/exceptions.h>
#include <tcf/services/symbols.h>
#include <tcf/framework/cpudefs-ext.h>
void create_reg_children_refs(RegisterDefinition * defs) {
#if ENABLE_RegisterChildrenRefs
RegisterDefinition * r = NULL;
RegisterDefinition ** p = NULL;
RegisterDefinition * c = NULL;
unsigned size = 0;
assert(defs->parent == NULL);
assert(defs->children == NULL);
for (r = defs; r->name != NULL; r++) size++;
p = (RegisterDefinition **)tmp_alloc_zero(sizeof(RegisterDefinition *) * size);
for (r = defs; r->name != NULL; r++) {
assert(r->sibling == NULL);
if (r->parent == NULL) {
if (c != NULL) c->sibling = r;
c = r;
}
else {
RegisterDefinition ** y = p + (r->parent - defs);
if (*y == NULL) r->parent->children = r;
else (*y)->sibling = r;
*y = r;
}
}
#endif
}
int read_reg_value(StackFrame * frame, RegisterDefinition * reg_def, uint64_t * value) {
uint8_t buf[8];
if (reg_def == NULL) {
set_errno(ERR_INV_CONTEXT, "Invalid register");
return -1;
}
if (frame == NULL) {
set_errno(ERR_INV_CONTEXT, "Invalid stack frame");
return -1;
}
if (reg_def->size > sizeof(buf)) {
errno = ERR_INV_DATA_SIZE;
return -1;
}
if (read_reg_bytes(frame, reg_def, 0, reg_def->size, buf) < 0) return -1;
if (value != NULL) {
size_t i;
uint64_t n = 0;
for (i = 0; i < reg_def->size; i++) {
n = n << 8;
n |= buf[reg_def->big_endian ? i : reg_def->size - i - 1];
}
*value = n;
}
return 0;
}
int write_reg_value(StackFrame * frame, RegisterDefinition * reg_def, uint64_t value) {
size_t i;
uint8_t buf[8];
if (reg_def == NULL) {
set_errno(ERR_INV_CONTEXT, "Invalid register");
return -1;
}
if (frame == NULL) {
set_errno(ERR_INV_CONTEXT, "Invalid stack frame");
return -1;
}
if (reg_def->size > sizeof(buf)) {
errno = ERR_INV_DATA_SIZE;
return -1;
}
for (i = 0; i < reg_def->size; i++) {
buf[reg_def->big_endian ? reg_def->size - i - 1 : i] = (uint8_t)value;
value = value >> 8;
}
if (write_reg_bytes(frame, reg_def, 0, reg_def->size, buf) < 0) return -1;
if (!frame->is_top_frame) frame->has_reg_data = 1;
return 0;
}
ContextAddress get_regs_PC(Context * ctx) {
ContextAddress pc = 0;
if (get_PC(ctx, &pc) < 0) return 0;
return pc;
}
void set_regs_PC(Context * ctx, ContextAddress pc) {
set_PC(ctx, pc);
}
int get_PC(Context * ctx, ContextAddress * p) {
size_t i;
uint8_t buf[8];
ContextAddress pc = 0;
RegisterDefinition * def = get_PC_definition(ctx);
if (def == NULL) {
set_errno(ERR_OTHER, "Cannot read PC: no such register");
return -1;
}
if (def->size > sizeof(buf)) {
set_errno(ERR_OTHER, "Cannot read PC: register is too large");
return -1;
}
if (context_read_reg(ctx, def, 0, def->size, buf) < 0) return -1;
for (i = 0; i < def->size; i++) {
pc = pc << 8;
pc |= buf[def->big_endian ? i : def->size - i - 1];
}
*p = pc;
return 0;
}
int set_PC(Context * ctx, ContextAddress pc) {
size_t i;
uint8_t buf[8];
RegisterDefinition * def = get_PC_definition(ctx);
if (def == NULL) {
set_errno(ERR_OTHER, "Cannot write PC: no such register");
return -1;
}
if (def->size > sizeof(buf)) {
set_errno(ERR_OTHER, "Cannot write PC: register is too large");
return -1;
}
for (i = 0; i < def->size; i++) {
buf[def->big_endian ? def->size - i - 1 : i] = (uint8_t)pc;
pc = pc >> 8;
}
return context_write_reg(ctx, def, 0, def->size, buf);
}
int id2frame(const char * id, Context ** ctx, int * frame) {
int f = 0;
Context * c = NULL;
if (*id++ != 'F') {
errno = ERR_INV_CONTEXT;
return -1;
}
if (*id++ != 'P') {
errno = ERR_INV_CONTEXT;
return -1;
}
while (*id != '.') {
if (*id < '0' || *id > '9') {
errno = ERR_INV_CONTEXT;
return -1;
}
f = f * 10 + (*id++ - '0');
}
id++;
c = id2ctx(id);
if (c == NULL || !context_has_state(c)) {
errno = ERR_INV_CONTEXT;
return -1;
}
*ctx = c;
*frame = f;
return 0;
}
const char * frame2id(Context * ctx, int frame) {
assert(frame >= 0);
return tmp_printf("FP%d.%s", frame, ctx->id);
}
const char * register2id(Context * ctx, int frame, RegisterDefinition * reg) {
RegisterDefinition * defs = get_reg_definitions(ctx);
assert(defs != NULL);
assert(reg >= defs);
if (frame < 0) return tmp_printf("R%d.%s", (int)(reg - defs), ctx->id);
return tmp_printf("R%d@%d.%s", (int)(reg - defs), frame, ctx->id);
}
int id2reg_num(const char * id, const char ** ctx_id, int * frame, unsigned * reg_num) {
*ctx_id = NULL;
*frame = STACK_TOP_FRAME;
*reg_num = 0;
if (*id++ != 'R') {
errno = ERR_INV_CONTEXT;
return -1;
}
while (*id != '.' && *id != '@') {
if (*id >= '0' && *id <= '9') {
*reg_num = *reg_num * 10 + (*id++ - '0');
}
else {
errno = ERR_INV_CONTEXT;
return -1;
}
}
if (*id == '@') {
int n = 0;
id++;
while (*id != '.') {
if (*id >= '0' && *id <= '9') {
n = n * 10 + (*id++ - '0');
}
else {
errno = ERR_INV_CONTEXT;
return -1;
}
}
*frame = n;
}
id++;
*ctx_id = id;
return 0;
}
int id2register(const char * id, Context ** ctx, int * frame, RegisterDefinition ** reg_def) {
const char * ctx_id = NULL;
RegisterDefinition * defs = NULL;
unsigned reg_num = 0;
*ctx = NULL;
*reg_def = NULL;
if (id2reg_num(id, &ctx_id, frame, &reg_num) < 0) return -1;
*ctx = id2ctx(ctx_id);
if (*ctx == NULL) {
errno = ERR_INV_CONTEXT;
return -1;
}
if ((*ctx)->exited) {
errno = ERR_ALREADY_EXITED;
return -1;
}
defs = get_reg_definitions(*ctx);
if (defs == NULL) {
set_errno(ERR_OTHER, "Context has no registers");
return -1;
}
*reg_def = defs + reg_num;
return 0;
}
static void location_expression_error(void) {
str_exception(ERR_OTHER, "Invalid location expression");
}
LocationExpressionState * evaluate_location_expression(Context * ctx, StackFrame * frame,
LocationExpressionCommand * cmds, unsigned cmd_cnt,
uint64_t * args, unsigned args_cnt) {
unsigned i;
unsigned stk_pos = 0;
unsigned stk_max = 0;
uint64_t * stk = NULL;
LocationExpressionState * state = (LocationExpressionState *)tmp_alloc_zero(sizeof(LocationExpressionState));
state->ctx = ctx;
state->stack_frame = frame;
state->args = args;
state->args_cnt = args_cnt;
for (i = 0; i < cmd_cnt && state->sft_cmd == NULL; i++) {
LocationExpressionCommand * cmd = cmds + i;
if (stk_pos >= stk_max) {
stk_max += 4;
stk = (uint64_t *)tmp_realloc(stk, sizeof(uint64_t) * stk_max);
}
switch (cmd->cmd) {
case SFT_CMD_NUMBER:
stk[stk_pos++] = cmd->args.num;
break;
case SFT_CMD_RD_REG:
if (read_reg_value(frame, cmd->args.reg, stk + stk_pos) < 0) exception(errno);
stk_pos++;
break;
case SFT_CMD_RD_REG_PCXI_TRICORE:
{
uint64_t offset;
uint64_t segment;
uint64_t pcxi;
if (read_reg_value(frame, cmd->args.reg, &pcxi) < 0) exception(errno);
/* PCXI is used as CFA and needs to be decyphered into order to point
* to the CSA (area of memory where registered were saved when CALL is made) */
offset = (pcxi & 0xFFFF) << 6;
segment = (pcxi & 0xF0000) << 12;
pcxi = offset | segment;
*(stk + stk_pos) = pcxi;
stk_pos++;
}
break;
case SFT_CMD_WR_REG:
if (stk_pos < 1) location_expression_error();
if (write_reg_value(frame, cmd->args.reg, *(stk + stk_pos - 1)) < 0) exception(errno);
stk_pos--;
break;
case SFT_CMD_FP:
if (frame == NULL) str_exception(ERR_INV_CONTEXT, "Invalid stack frame");
stk[stk_pos++] = frame->fp;
break;
case SFT_CMD_LOAD:
if (state->pieces_cnt > 0) {
size_t j;
size_t size = 0;
uint64_t n = 0;
void * buf = NULL;
read_location_pieces(state->ctx, state->stack_frame,
state->pieces, state->pieces_cnt, cmd->args.mem.big_endian, &buf, &size);
state->pieces_cnt = 0;
for (j = 0; j < size; j++) {
n = (n << 8) | ((uint8_t *)buf)[cmd->args.mem.big_endian ? j : size - j - 1];
}
stk[stk_pos++] = n;
break;
}
/* Fall through */
case SFT_CMD_RD_MEM:
if (stk_pos < 1) location_expression_error();
{
size_t j;
size_t size = cmd->args.mem.size;
uint64_t n = 0;
if (size <= sizeof(n)) {
uint8_t buf[8];
if (context_read_mem(ctx, (ContextAddress)stk[stk_pos - 1], buf, size) < 0) exception(errno);
for (j = 0; j < size; j++) {
n = (n << 8) | buf[cmd->args.mem.big_endian ? j : size - j - 1];
}
stk[stk_pos - 1] = n;
}
else if (state->pieces_cnt == 0 && i + 1 == cmd_cnt && stk_pos == 1) {
LocationPiece * piece = NULL;
if (state->pieces_cnt >= state->pieces_max) {
state->pieces_max += 4;
state->pieces = (LocationPiece *)tmp_realloc(state->pieces, state->pieces_max * sizeof(LocationPiece));
}
piece = state->pieces + state->pieces_cnt++;
memset(piece, 0, sizeof(LocationPiece));
piece->addr = (ContextAddress)stk[stk_pos - 1];
piece->size = size;
stk_pos--;
}
else {
exception(ERR_INV_DATA_SIZE);
}
}
break;
case SFT_CMD_WR_MEM:
if (stk_pos < 2) location_expression_error();
{
size_t j;
size_t size = cmd->args.mem.size;
uint64_t n = stk[stk_pos - 1];
uint8_t buf[8];
assert(size <= sizeof(buf));
for (j = 0; j < size; j++) {
buf[cmd->args.mem.big_endian ? size - j - 1 : j] = (uint8_t)n;
n >>= 8;
}
if (context_write_mem(ctx, (ContextAddress)stk[stk_pos - 2], buf, size) < 0) exception(errno);
stk_pos -= 2;
}
break;
case SFT_CMD_ADD:
if (stk_pos < 2) location_expression_error();
stk[stk_pos - 2] = stk[stk_pos - 2] + stk[stk_pos - 1];
stk_pos--;
break;
case SFT_CMD_SUB:
if (stk_pos < 2) location_expression_error();
stk[stk_pos - 2] = stk[stk_pos - 2] - stk[stk_pos - 1];
stk_pos--;
break;
case SFT_CMD_MUL:
if (stk_pos < 2) location_expression_error();
stk[stk_pos - 2] = stk[stk_pos - 2] * stk[stk_pos - 1];
stk_pos--;
break;
case SFT_CMD_DIV:
if (stk_pos < 2) location_expression_error();
if (stk[stk_pos - 1] == 0) str_exception(ERR_OTHER, "Division by zero in location expression");
stk[stk_pos - 2] = stk[stk_pos - 2] / stk[stk_pos - 1];
stk_pos--;
break;
case SFT_CMD_AND:
if (stk_pos < 2) location_expression_error();
stk[stk_pos - 2] = stk[stk_pos - 2] & stk[stk_pos - 1];
stk_pos--;
break;
case SFT_CMD_OR:
if (stk_pos < 2) location_expression_error();
stk[stk_pos - 2] = stk[stk_pos - 2] | stk[stk_pos - 1];
stk_pos--;
break;
case SFT_CMD_XOR:
if (stk_pos < 2) location_expression_error();
stk[stk_pos - 2] = stk[stk_pos - 2] ^ stk[stk_pos - 1];
stk_pos--;
break;
case SFT_CMD_NEG:
if (stk_pos < 1) location_expression_error();
stk[stk_pos - 1] = ~stk[stk_pos - 1];
stk_pos--;
break;
case SFT_CMD_GE:
if (stk_pos < 2) location_expression_error();
stk[stk_pos - 2] = stk[stk_pos - 2] >= stk[stk_pos - 1];
stk_pos--;
break;
case SFT_CMD_GT:
if (stk_pos < 2) location_expression_error();
stk[stk_pos - 2] = stk[stk_pos - 2] > stk[stk_pos - 1];
stk_pos--;
break;
case SFT_CMD_LE:
if (stk_pos < 2) location_expression_error();
stk[stk_pos - 2] = stk[stk_pos - 2] <= stk[stk_pos - 1];
stk_pos--;
break;
case SFT_CMD_LT:
if (stk_pos < 2) location_expression_error();
stk[stk_pos - 2] = stk[stk_pos - 2] < stk[stk_pos - 1];
stk_pos--;
break;
case SFT_CMD_SHL:
if (stk_pos < 2) location_expression_error();
stk[stk_pos - 2] <<= stk[stk_pos - 1];
stk_pos--;
break;
case SFT_CMD_SHR:
if (stk_pos < 2) location_expression_error();
stk[stk_pos - 2] >>= stk[stk_pos - 1];
stk_pos--;
break;
case SFT_CMD_ARG:
if (cmd->args.arg_no >= args_cnt) location_expression_error();
stk[stk_pos++] = args[cmd->args.arg_no];
break;
case SFT_CMD_SET_ARG:
if (stk_pos < 1) location_expression_error();
if (cmd->args.arg_no >= args_cnt) {
unsigned cnt = cmd->args.arg_no + 1;
uint64_t * buf = (uint64_t *)tmp_alloc_zero(sizeof(uint64_t) * cnt);
memcpy(buf, args, sizeof(uint64_t) * args_cnt);
args_cnt = cnt;
args = buf;
}
args[cmd->args.arg_no] = stk[stk_pos - 1];
stk_pos--;
break;
case SFT_CMD_LOCATION:
state->stk = stk;
state->type_stk = (uint8_t *)tmp_alloc_zero(stk_max);
state->stk_pos = stk_pos;
state->stk_max = stk_max;
state->reg_id_scope = cmd->args.loc.reg_id_scope;
state->code = cmd->args.loc.code_addr;
state->code_len = cmd->args.loc.code_size;
state->code_pos = 0;
state->addr_size = cmd->args.loc.addr_size;
state->client_op = NULL;
if (cmd->args.loc.func(state) < 0) exception(errno);
memset(&state->reg_id_scope, 0, sizeof(state->reg_id_scope));
state->code = NULL;
state->code_len = 0;
state->code_pos = 0;
state->addr_size = 0;
state->client_op = NULL;
stk_max = state->stk_max;
stk_pos = state->stk_pos;
stk = state->stk;
break;
case SFT_CMD_FCALL:
state->sft_cmd = cmd;
break;
case SFT_CMD_PIECE:
{
LocationPiece * piece = NULL;
if (state->pieces_cnt >= state->pieces_max) {
state->pieces_max += 4;
state->pieces = (LocationPiece *)tmp_realloc(state->pieces, state->pieces_max * sizeof(LocationPiece));
}
piece = state->pieces + state->pieces_cnt++;
memset(piece, 0, sizeof(LocationPiece));
if (cmd->args.piece.bit_offs == 0 && cmd->args.piece.bit_size % 8 == 0) {
piece->size = cmd->args.piece.bit_size / 8;
}
else {
piece->bit_offs = cmd->args.piece.bit_offs;
piece->bit_size = cmd->args.piece.bit_size;
}
if (cmd->args.piece.reg != NULL || cmd->args.piece.value != NULL) {
piece->reg = cmd->args.piece.reg;
piece->value = cmd->args.piece.value;
}
else if (stk_pos == 0) {
location_expression_error();
}
else {
stk_pos--;
piece->addr = (ContextAddress)stk[stk_pos];
}
}
break;
default:
location_expression_error();
break;
}
}
if (stk_pos == 2) {
/* This looks like a bug in GNU Ada 4.9.2 20141023 for GNAT Pro 7.3.0w
* See https://bugs.eclipse.org/bugs/show_bug.cgi?id=449802
*/
stk[0] += stk[1];
stk_pos = 1;
}
state->stk = stk;
state->stk_pos = stk_pos;
state->stk_max = stk_max;
return state;
}
#define bit_mask(n) (1u << (big_endian ? 7 - (n) % 8 : (n) % 8))
void read_location_pieces(Context * ctx, StackFrame * frame,
LocationPiece * pieces, unsigned pieces_cnt, int big_endian,
void ** value, size_t * size) {
/* Note: 'big_endian' should match endianness of LocationPiece.value in 'pieces' */
uint8_t * bf = NULL;
size_t bf_size = 0;
unsigned bf_bits = 0;
unsigned bf_offs = 0;
unsigned n = 0;
unsigned i = 0;
while (i < pieces_cnt) {
LocationPiece * piece = pieces + i++;
bf_bits += piece->bit_size ? piece->bit_size : piece->size * 8;
}
bf_size = (size_t)((bf_bits + 7) / 8);
bf = (uint8_t *)tmp_alloc_zero(bf_size);
if (big_endian) bf_offs = bf_size * 8 - bf_bits;
while (n < pieces_cnt) {
LocationPiece * piece = pieces + n++;
unsigned piece_size = piece->size ? piece->size : (piece->bit_offs + piece->bit_size + 7) / 8;
unsigned piece_bits = piece->bit_size ? piece->bit_size : piece->size * 8;
uint8_t * pbf = NULL;
uint8_t * rbf = NULL;
if (piece->optimized_away) {
set_errno(ERR_OTHER, "Cannot get symbol value: optimized away");
exception(errno);
}
if (piece->implicit_pointer) {
set_errno(ERR_OTHER, "Cannot get symbol value: implicit pointer");
exception(errno);
}
if (piece->reg) {
if (piece->reg->size < piece_size) {
rbf = pbf = (uint8_t *)tmp_alloc_zero(piece_size);
if (big_endian) rbf += piece_size - piece->reg->size;
}
else {
rbf = pbf = (uint8_t *)tmp_alloc(piece->reg->size);
}
if (frame == NULL) {
if (context_read_reg(ctx, piece->reg, 0, piece->reg->size, rbf) < 0) exception(errno);
}
else {
if (read_reg_bytes(frame, piece->reg, 0, piece->reg->size, rbf) < 0) exception(errno);
}
if (!piece->reg->big_endian != !big_endian) swap_bytes(rbf, piece->reg->size);
}
else if (piece->value) {
pbf = (uint8_t *)piece->value;
}
else {
pbf = (uint8_t *)tmp_alloc(piece_size);
if (context_read_mem(ctx, piece->addr, pbf, piece_size) < 0) exception(errno);
}
for (i = piece->bit_offs; i < piece->bit_offs + piece_bits; i++) {
if (pbf[i / 8] & bit_mask(i)) bf[bf_offs / 8] |= bit_mask(bf_offs);
bf_offs++;
}
}
*value = bf;
*size = bf_size;
}
void write_location_pieces(Context * ctx, StackFrame * frame,
LocationPiece * pieces, unsigned pieces_cnt, int big_endian,
void * value, size_t size) {
uint8_t * bf = (uint8_t *)value;
size_t bf_size = 0;
unsigned bf_bits = 0;
unsigned bf_offs = 0;
unsigned n = 0;
unsigned i = 0;
while (i < pieces_cnt) {
LocationPiece * piece = pieces + i++;
bf_bits += piece->bit_size ? piece->bit_size : piece->size * 8;
}
bf_size = (size_t)((bf_bits + 7) / 8);
if (big_endian && size >= bf_size) bf_offs = size * 8 - bf_bits;
while (n < pieces_cnt) {
LocationPiece * piece = pieces + n++;
unsigned piece_size = piece->size ? piece->size : (piece->bit_offs + piece->bit_size + 7) / 8;
unsigned piece_bits = piece->bit_size ? piece->bit_size : piece->size * 8;
uint8_t * pbf = NULL;
uint8_t * rbf = NULL;
if (piece->optimized_away) {
set_errno(ERR_OTHER, "Cannot set symbol value: optimized away");
exception(errno);
}
if (piece->implicit_pointer) {
set_errno(ERR_OTHER, "Cannot set symbol value: implicit pointer");
exception(errno);
}
if (piece->reg) {
if (piece->reg->size < piece_size) {
rbf = pbf = (uint8_t *)tmp_alloc_zero(piece_size);
if (big_endian) rbf += piece_size - piece->reg->size;
}
else {
rbf = pbf = (uint8_t *)tmp_alloc(piece->reg->size);
}
if (frame == NULL) {
if (context_read_reg(ctx, piece->reg, 0, piece->reg->size, rbf) < 0) exception(errno);
}
else {
if (read_reg_bytes(frame, piece->reg, 0, piece->reg->size, rbf) < 0) exception(errno);
}
if (!piece->reg->big_endian != !big_endian) swap_bytes(rbf, piece->reg->size);
}
else if (piece->value) {
str_exception(ERR_OTHER, "Cannot write to a constant value");
}
else {
pbf = (uint8_t *)tmp_alloc(piece_size);
if (context_read_mem(ctx, piece->addr, pbf, piece_size) < 0) exception(errno);
}
for (i = piece->bit_offs; i < piece->bit_offs + piece_bits; i++) {
if (bf_offs / 8 >= size) {
/* Leave unchanged? */
}
else if (bf[bf_offs / 8] & bit_mask(bf_offs)) {
pbf[i / 8] |= bit_mask(i);
}
else {
pbf[i / 8] &= ~bit_mask(i);
}
bf_offs++;
}
if (piece->reg) {
if (!piece->reg->big_endian != !big_endian) swap_bytes(rbf, piece->reg->size);
if (frame == NULL) {
if (context_write_reg(ctx, piece->reg, 0, piece->reg->size, rbf) < 0) exception(errno);
}
else {
if (write_reg_bytes(frame, piece->reg, 0, piece->reg->size, rbf) < 0) exception(errno);
if (!frame->is_top_frame) frame->has_reg_data = 1;
}
}
else if (piece->value) {
assert(0);
}
else {
if (context_write_mem(ctx, piece->addr, pbf, piece_size) < 0) exception(errno);
}
}
}
#if !defined(ENABLE_external_stepping_mode) || !ENABLE_external_stepping_mode
int cpu_enable_stepping_mode(Context * ctx, uint32_t * is_cont) {
* is_cont = 0;
return 0;
}
int cpu_disable_stepping_mode(Context * ctx) {
return 0;
}
#endif
#if !defined(ENABLE_HardwareBreakpoints) || !ENABLE_HardwareBreakpoints
int cpu_bp_get_capabilities(Context * ctx) {
return 0;
}
int cpu_bp_plant(ContextBreakpoint * bp) {
errno = ERR_UNSUPPORTED;
return -1;
}
int cpu_bp_remove(ContextBreakpoint * bp) {
errno = ERR_UNSUPPORTED;
return -1;
}
int cpu_bp_on_resume(Context * ctx, int * single_step) {
return 0;
}
int cpu_bp_on_suspend(Context * ctx, int * triggered) {
return 0;
}
#endif
void ini_cpu_disassembler(Context * cpu) {
#if defined(ENABLE_add_cpudefs_disassembler) && ENABLE_add_cpudefs_disassembler
add_cpudefs_disassembler(cpu);
#endif
}
void ini_cpudefs(void) {
#if defined(ENABLE_ini_cpudefs_mdep) && ENABLE_ini_cpudefs_mdep
ini_cpudefs_mdep();
#endif
}
#endif /* ENABLE_DebugContext */