blob: d7523f1a4c4055e44ffcdc47124349988c1329b7 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007, 2012 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 file provides debug context register definitions and lookup functions.
* It is included into cpudefs.c.
* The code assumes that all contexts share same register definitions.
* If it is not the case, this file needs to be substituted with alternative implementation.
*/
#include <tcf/config.h>
#if ENABLE_ContextMux
#include <tcf/framework/cpudefs-mux.h>
#endif
#include <tcf/cpudefs-mdep.h>
struct RegisterData {
REG_SET data;
REG_SET mask;
};
RegisterDefinition * get_reg_definitions(Context * ctx) {
if (context_has_state(ctx)) return regs_index;
return NULL;
}
uint8_t * get_break_instruction(Context * ctx, size_t * size) {
*size = sizeof(BREAK_INST);
return BREAK_INST;
}
static RegisterDefinition * get_reg_by_dwarf_id(unsigned id) {
static RegisterDefinition ** map = NULL;
static unsigned map_length = 0;
if (map == NULL) {
RegisterDefinition * r;
for (r = regs_index; r->name != NULL; r++) {
if (r->dwarf_id >= (int)map_length) map_length = r->dwarf_id + 1;
}
map = (RegisterDefinition **)loc_alloc_zero(sizeof(RegisterDefinition *) * map_length);
for (r = regs_index; r->name != NULL; r++) {
if (r->dwarf_id >= 0) map[r->dwarf_id] = r;
}
}
return id < map_length ? map[id] : NULL;
}
static RegisterDefinition * get_reg_by_eh_frame_id(unsigned id) {
static RegisterDefinition ** map = NULL;
static unsigned map_length = 0;
if (map == NULL) {
RegisterDefinition * r;
for (r = regs_index; r->name != NULL; r++) {
if (r->eh_frame_id >= (int)map_length) map_length = r->eh_frame_id + 1;
}
map = (RegisterDefinition **)loc_alloc_zero(sizeof(RegisterDefinition *) * map_length);
for (r = regs_index; r->name != NULL; r++) {
if (r->eh_frame_id >= 0) map[r->eh_frame_id] = r;
}
}
return id < map_length ? map[id] : NULL;
}
RegisterDefinition * get_reg_by_id(Context * ctx, unsigned id, RegisterIdScope * scope) {
RegisterDefinition * def = NULL;
#ifdef GET_REG_BY_ID_HOOK
GET_REG_BY_ID_HOOK;
#endif
if (context_has_state(ctx)) {
switch (scope->id_type) {
case REGNUM_DWARF: def = get_reg_by_dwarf_id(id); break;
case REGNUM_EH_FRAME: def = get_reg_by_eh_frame_id(id); break;
}
}
if (def == NULL) set_errno(ERR_OTHER, "Invalid register ID");
return def;
}
int read_reg_bytes(StackFrame * frame, RegisterDefinition * reg_def, unsigned offs, unsigned size, uint8_t * buf) {
if (reg_def != NULL && frame != NULL) {
if (frame->is_top_frame) {
return context_read_reg(frame->ctx, reg_def, offs, size, buf);
}
if (frame->regs != NULL) {
size_t i;
uint8_t * r_addr = (uint8_t *)&frame->regs->data + reg_def->offset;
uint8_t * m_addr = (uint8_t *)&frame->regs->mask + reg_def->offset;
for (i = 0; i < size; i++) {
if (m_addr[offs + i] != 0xff) {
errno = ERR_INV_CONTEXT;
return -1;
}
}
assert(reg_def->offset + reg_def->size <= sizeof(REG_SET));
if (offs + size > reg_def->size) {
errno = ERR_INV_DATA_SIZE;
return -1;
}
memcpy(buf, r_addr + offs, size);
return 0;
}
}
errno = ERR_INV_CONTEXT;
return -1;
}
int write_reg_bytes(StackFrame * frame, RegisterDefinition * reg_def, unsigned offs, unsigned size, uint8_t * buf) {
if (reg_def != NULL && frame != NULL) {
if (frame->is_top_frame) {
return context_write_reg(frame->ctx, reg_def, offs, size, buf);
}
if (frame->regs == NULL && context_has_state(frame->ctx)) {
frame->regs = (RegisterData *)loc_alloc_zero(sizeof(RegisterData));
}
if (frame->regs != NULL) {
uint8_t * r_addr = (uint8_t *)&frame->regs->data + reg_def->offset;
uint8_t * m_addr = (uint8_t *)&frame->regs->mask + reg_def->offset;
assert(reg_def->offset + reg_def->size <= sizeof(REG_SET));
if (offs + size > reg_def->size) {
errno = ERR_INV_DATA_SIZE;
return -1;
}
memcpy(r_addr + offs, buf, size);
memset(m_addr + offs, 0xff, size);
return 0;
}
}
errno = ERR_INV_CONTEXT;
return -1;
}