blob: 749e94c976db08e02130bf4046bfefcdf38235b5 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007, 2017 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.
*/
#ifndef D_cpudefs
#define D_cpudefs
#include <tcf/config.h>
typedef struct Context Context;
typedef struct ContextBreakpoint ContextBreakpoint;
/* Type to represent byte address inside context memory */
#if ENABLE_ContextProxy
typedef uint64_t ContextAddress;
#else
typedef uintptr_t ContextAddress;
#endif
#if ENABLE_DebugContext
#ifndef ENABLE_StackRegisterLocations
#define ENABLE_StackRegisterLocations 0
#endif
#define REGNUM_DWARF 1
#define REGNUM_EH_FRAME 2
typedef struct RegisterData RegisterData;
typedef struct RegisterDefinition RegisterDefinition;
typedef struct NamedRegisterValue NamedRegisterValue;
struct NamedRegisterValue {
uint8_t * value;
const char * name;
const char * description;
};
struct RegisterDefinition {
const char * name; /* pointer to register name */
size_t offset; /* byte offset in the regsiers data cache */
size_t size; /* register size in bytes */
int16_t dwarf_id; /* ID of the register in DWARF sections, or -1 */
int16_t eh_frame_id; /* ID of the register in .eh_frame section, or -1 */
uint8_t big_endian; /* 0 - little endian, 1 - big endian */
uint8_t fp_value; /* true if the register value is a floating-point value */
uint8_t no_read; /* true if context value can not be read */
uint8_t no_write; /* true if context value can not be written */
uint8_t read_once; /* true if reading the context (register) destroys its current value */
uint8_t write_once; /* true if register value can not be overwritten - every write counts */
uint8_t side_effects; /* true if writing the context can change values of other registers */
uint8_t volatile_value;/* true if the register value can change even when target is stopped */
uint8_t left_to_right; /* true if the lowest numbered bit should be shown to user as the left-most bit */
int first_bit; /* bit numbering base (0 or 1) to use when showing bits to user */
int * bits; /* if context is a bit field, contains the field bit numbers in the parent register definition, -1 marks end of the list */
RegisterDefinition * parent; /* parent register definition, NULL for top level definitions */
NamedRegisterValue ** values; /* predefined names (mnemonics) for some of register values */
ContextAddress memory_address;/* the address of a memory mapped register */
const char * memory_context;/* the context ID of a memory context in which a memory mapped register is located */
const char * role; /* the role the register plays in a program execution */
const char * description; /* the description of the register */
void * ext; /* to be used by debug context implementation */
};
typedef struct RegisterIdScope {
uint16_t machine;
uint8_t os_abi;
uint8_t fp_abi;
uint8_t elf64;
uint8_t big_endian;
uint8_t id_type;
} RegisterIdScope;
/* Location expression command codes */
#define SFT_CMD_NUMBER 1
#define SFT_CMD_RD_REG 2
#define SFT_CMD_FP 3
#define SFT_CMD_RD_MEM 4
#define SFT_CMD_ADD 5
#define SFT_CMD_SUB 6
#define SFT_CMD_MUL 7
#define SFT_CMD_DIV 8
#define SFT_CMD_AND 9
#define SFT_CMD_OR 10
#define SFT_CMD_XOR 11
#define SFT_CMD_NEG 12
#define SFT_CMD_GE 13
#define SFT_CMD_GT 14
#define SFT_CMD_LE 15
#define SFT_CMD_LT 16
#define SFT_CMD_SHL 17
#define SFT_CMD_SHR 18
#define SFT_CMD_ARG 19
#define SFT_CMD_LOCATION 20 /* A DWARF location expression */
#define SFT_CMD_FCALL 21
#define SFT_CMD_WR_REG 22
#define SFT_CMD_WR_MEM 23
#define SFT_CMD_PIECE 24
#define SFT_CMD_LOAD 25
#define SFT_CMD_STORE 26
#define SFT_CMD_SET_ARG 27
#define SFT_CMD_RD_REG_PCXI_TRICORE 28
#define SFT_CMD_REGISTER 2 /* Deprecated, use SFT_CMD_RD_REG */
#define SFT_CMD_DEREF 4 /* Deprecated, use SFT_CMD_RD_MEM */
typedef struct LocationExpressionCommand LocationExpressionCommand;
typedef struct LocationPiece {
int optimized_away; /* present in the source but not in the object code (perhaps due to optimization) */
ContextAddress addr;
RegisterDefinition * reg;
void * value;
size_t size;
unsigned bit_offs; /* bit numbering is right-to-left (LSB-to-MSB) for little-endian, and left-to-right for big-endian */
unsigned bit_size;
unsigned implicit_pointer; /* >0 if the value is result of implicit pointer dereference */
} LocationPiece;
typedef struct LocationExpressionState {
/* Evaluation context */
Context * ctx;
struct StackFrame * stack_frame;
uint64_t * args;
unsigned args_cnt;
/* Note: DWARF expression fields hold temporary data,
they are valid only during evaluate_vm_expression() call */
/* DWARF expression code to execute */
uint8_t * code;
size_t code_pos;
size_t code_len;
RegisterIdScope reg_id_scope;
size_t addr_size;
/* DWARF expression client callback */
void (*client_op)(uint8_t op);
/* Result */
LocationExpressionCommand * sft_cmd;
LocationPiece * pieces;
unsigned pieces_cnt;
unsigned pieces_max;
/* Evaluation stack */
unsigned stk_pos;
unsigned stk_max;
uint64_t * stk;
uint8_t * type_stk;
} LocationExpressionState;
typedef int LocationExpressionCallback(LocationExpressionState *);
/* Location expression command */
struct LocationExpressionCommand {
int cmd;
union {
int64_t num;
RegisterDefinition * reg;
struct {
size_t size;
int big_endian;
} deref; /* Deprecated, use .mem */
struct {
size_t size;
int big_endian;
} mem;
struct {
LocationExpressionCallback * func;
RegisterIdScope reg_id_scope;
uint8_t * code_addr;
size_t code_size;
size_t addr_size;
} loc;
struct {
void * value;
RegisterDefinition * reg;
unsigned bit_offs;
unsigned bit_size;
} piece;
unsigned arg_no;
} args;
};
typedef struct CodeArea {
const char * directory;
const char * file;
uint32_t file_mtime;
uint32_t file_size;
ContextAddress start_address;
int start_line;
int start_column;
ContextAddress end_address;
int end_line;
int end_column;
ContextAddress next_address; /* Address of next area - in source text order */
int isa;
int is_statement;
int basic_block;
int prologue_end;
int epilogue_begin;
int op_index;
int discriminator;
ContextAddress next_stmt_address; /* Address of next statement - in source text order */
} CodeArea;
#define STACK_NO_FRAME (-1)
#define STACK_TOP_FRAME (-2)
#define STACK_BOTTOM_FRAME (-3)
typedef struct StackFrame {
int frame;
int is_top_frame;
int is_walked; /* Data collected by: 0 - crawl, 1 - walk */
int has_reg_data;
int inlined;
CodeArea * area; /* if the frame is call site of inlined function */
char * func_id; /* function symbol ID - optional */
Context * ctx;
ContextAddress fp; /* frame address */
RegisterData * regs; /* register values */
} StackFrame;
/* Return array of CPU register definitions. Last item in the array has name == NULL */
extern RegisterDefinition * get_reg_definitions(Context * ctx);
/* Search register definition for given register ID, return NULL if not found */
extern RegisterDefinition * get_reg_by_id(Context * ctx, unsigned id, RegisterIdScope * scope);
/* Return register definition of instruction pointer */
extern RegisterDefinition * get_PC_definition(Context * ctx);
/* Read register value from stack frame data, return 0 on success, return -1 and set errno if register is not available */
extern int read_reg_value(StackFrame * frame, RegisterDefinition * reg_def, uint64_t * value);
/* Write register value into stack frame data, return 0 on success, return -1 and set errno if register is not available */
extern int write_reg_value(StackFrame * frame, RegisterDefinition * reg_def, uint64_t value);
/* Read register bytes from stack frame data, return 0 on success, return -1 and set errno if register is not available */
extern int read_reg_bytes(StackFrame * frame, RegisterDefinition * reg_def, unsigned offs, unsigned size, uint8_t * buf);
/* Write register bytes into stack frame data, return 0 on success, return -1 and set errno if register is not available */
extern int write_reg_bytes(StackFrame * frame, RegisterDefinition * reg_def, unsigned offs, unsigned size, uint8_t * buf);
#if ENABLE_StackRegisterLocations
/* Write register location into stack frame data, return 0 on success, return -1 and set errno if register is not available */
extern int write_reg_location(StackFrame * frame, RegisterDefinition * reg_def, LocationExpressionCommand * cmds, unsigned cmds_cnt);
#endif
/* Get instruction pointer (PC) value.
* Deprecated: use get_PC() */
extern ContextAddress get_regs_PC(Context * ctx);
/* Set instruction pointer (PC) value.
* Deprecated: use set_PC() */
extern void set_regs_PC(Context * ctx, ContextAddress y);
/* Get instruction pointer (PC) value, return 0 on success, return -1 and set errno on error */
extern int get_PC(Context * ctx, ContextAddress * pc);
/* Set instruction pointer (PC) value, return 0 on success, return -1 and set errno on error */
extern int set_PC(Context * ctx, ContextAddress pc);
/* Get TCF ID of a stack frame */
extern const char * frame2id(Context * ctx, int frame);
/* Get stack frame for TCF ID */
extern int id2frame(const char * id, Context ** ctx, int * frame);
/* Get TCF ID of a register */
extern const char * register2id(Context * ctx, int frame, RegisterDefinition * reg);
/* Get register for TCF ID */
extern int id2reg_num(const char * id, const char ** ctx_id, int * frame, unsigned * reg_num);
extern int id2register(const char * id, Context ** ctx, int * frame, RegisterDefinition ** reg_def);
/* Get breakpoint instruction code and size.
* Return NULL if the context does not support software breakpoints. */
extern uint8_t * get_break_instruction(Context * ctx, size_t * size);
/*
* Retrieve stack frame information by examining stack data in memory.
*
* "frame" is current frame info, it should have frame->regs and frame->mask filled with
* proper values before this function is called.
*
* "down" is next frame - moving from stack top to the bottom.
*
* The function uses register values in current frame to calculate frame address "frame->fp",
* and calculate register values in the next frame.
*/
extern int crawl_stack_frame(StackFrame * frame, StackFrame * down);
/* Execute location expression. Throw an exception if error. */
extern LocationExpressionState * evaluate_location_expression(
Context * ctx, StackFrame * frame,
LocationExpressionCommand * cmds, unsigned cmds_cnt,
uint64_t * args, unsigned args_cnt);
extern void read_location_pieces(
Context * ctx, StackFrame * frame,
LocationPiece * pieces, unsigned pieces_cnt, int big_endian,
void ** value, size_t * size);
extern void write_location_pieces(
Context * ctx, StackFrame * frame,
LocationPiece * pieces, unsigned pieces_cnt, int big_endian,
void * value, size_t size);
/* Deprecated misspelled function names */
#define read_location_peices read_location_pieces
#define write_location_peices write_location_pieces
/*** CPU hardware breakpoints API ***/
/* Get supported memory access modes */
extern int cpu_bp_get_capabilities(Context * ctx);
/* Plant hardware breakpoint */
extern int cpu_bp_plant(ContextBreakpoint * bp);
/* Remove hardware breakpoint */
extern int cpu_bp_remove(ContextBreakpoint * bp);
/* Setup breakpoint registers for a context that is about to resume */
extern int cpu_bp_on_resume(Context * ctx, int * single_step);
/* Check breakpoint registers for a context that has stopped */
extern int cpu_bp_on_suspend(Context * ctx, int * triggered);
/*** CPU external stepping mode API ***/
/* Disable the stepping mode */
extern int cpu_disable_stepping_mode(Context * ctx);
/* Enable the stepping mode */
extern int cpu_enable_stepping_mode(Context * ctx, uint32_t * is_cont);
/*** Initialization functions ***/
extern void ini_cpu_disassembler(Context * cpu);
extern void ini_cpudefs(void);
#endif /* ENABLE_DebugContext */
#endif /* D_cpudefs */