#include "defs.h"
#include "target.h"
#include "breakpoint.h"
#include "linespec.h"
#include "block.h"
#include "dictionary.h"
#include <tcl.h>
#include "gdbtk.h"
#include "gdbtk-cmds.h"
#include "gdbtk-wrapper.h"
static int gdb_block_vars (ClientData clientData,
Tcl_Interp * interp, int objc,
Tcl_Obj * CONST objv[]);
static int gdb_get_args_command (ClientData, Tcl_Interp *, int,
Tcl_Obj * CONST objv[]);
static int gdb_get_blocks (ClientData clientData,
Tcl_Interp * interp, int objc,
Tcl_Obj * CONST objv[]);
static int gdb_get_locals_command (ClientData, Tcl_Interp *, int,
Tcl_Obj * CONST objv[]);
static int gdb_get_vars_command (ClientData, Tcl_Interp *, int,
Tcl_Obj * CONST objv[]);
static int gdb_selected_block (ClientData clientData,
Tcl_Interp * interp, int argc,
Tcl_Obj * CONST objv[]);
static int gdb_selected_frame (ClientData clientData,
Tcl_Interp * interp, int argc,
Tcl_Obj * CONST objv[]);
static int gdb_stack (ClientData, Tcl_Interp *, int, Tcl_Obj * CONST[]);
static void get_frame_name (Tcl_Interp *interp, Tcl_Obj *list,
struct frame_info *fi);
int
Gdbtk_Stack_Init (Tcl_Interp *interp)
{
Tcl_CreateObjCommand (interp, "gdb_block_variables", gdbtk_call_wrapper,
gdb_block_vars, NULL);
Tcl_CreateObjCommand (interp, "gdb_get_blocks", gdbtk_call_wrapper,
gdb_get_blocks, NULL);
Tcl_CreateObjCommand (interp, "gdb_get_args", gdbtk_call_wrapper,
gdb_get_args_command, NULL);
Tcl_CreateObjCommand (interp, "gdb_get_locals", gdbtk_call_wrapper,
gdb_get_locals_command, NULL);
Tcl_CreateObjCommand (interp, "gdb_selected_block", gdbtk_call_wrapper,
gdb_selected_block, NULL);
Tcl_CreateObjCommand (interp, "gdb_selected_frame", gdbtk_call_wrapper,
gdb_selected_frame, NULL);
Tcl_CreateObjCommand (interp, "gdb_stack", gdbtk_call_wrapper, gdb_stack, NULL);
return TCL_OK;
}
static int
gdb_block_vars (ClientData clientData, Tcl_Interp *interp,
int objc, Tcl_Obj *CONST objv[])
{
struct block *block;
struct dict_iterator iter;
struct symbol *sym;
CORE_ADDR start, end;
if (objc < 3)
{
Tcl_WrongNumArgs (interp, 1, objv, "startAddr endAddr");
return TCL_ERROR;
}
Tcl_SetListObj (result_ptr->obj_ptr, 0, NULL);
if (deprecated_selected_frame == NULL)
return TCL_OK;
start = string_to_core_addr (Tcl_GetStringFromObj (objv[1], NULL));
end = string_to_core_addr (Tcl_GetStringFromObj (objv[2], NULL));
block = get_frame_block (deprecated_selected_frame, 0);
while (block != 0)
{
if (BLOCK_START (block) == start && BLOCK_END (block) == end)
{
ALL_BLOCK_SYMBOLS (block, iter, sym)
{
switch (SYMBOL_CLASS (sym))
{
case LOC_ARG:
case LOC_REF_ARG:
case LOC_REGPARM:
case LOC_REGPARM_ADDR:
case LOC_LOCAL_ARG:
case LOC_BASEREG_ARG:
case LOC_LOCAL:
case LOC_BASEREG:
case LOC_STATIC:
case LOC_REGISTER:
case LOC_COMPUTED:
case LOC_COMPUTED_ARG:
Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr,
Tcl_NewStringObj (DEPRECATED_SYMBOL_NAME (sym),
-1));
break;
default:
break;
}
}
return TCL_OK;
}
else if (BLOCK_FUNCTION (block))
break;
else
block = BLOCK_SUPERBLOCK (block);
}
return TCL_OK;
}
static int
gdb_get_blocks (ClientData clientData, Tcl_Interp *interp,
int objc, Tcl_Obj *CONST objv[])
{
struct block *block;
struct dict_iterator iter;
int junk;
struct symbol *sym;
CORE_ADDR pc;
Tcl_SetListObj (result_ptr->obj_ptr, 0, NULL);
if (deprecated_selected_frame != NULL)
{
block = get_frame_block (deprecated_selected_frame, 0);
pc = get_frame_pc (deprecated_selected_frame);
while (block != 0)
{
junk = 0;
ALL_BLOCK_SYMBOLS (block, iter, sym)
{
switch (SYMBOL_CLASS (sym))
{
default:
case LOC_UNDEF:
case LOC_CONST:
case LOC_TYPEDEF:
case LOC_LABEL:
case LOC_BLOCK:
case LOC_CONST_BYTES:
case LOC_UNRESOLVED:
case LOC_OPTIMIZED_OUT:
junk = 1;
break;
case LOC_ARG:
case LOC_REF_ARG:
case LOC_REGPARM:
case LOC_REGPARM_ADDR:
case LOC_LOCAL_ARG:
case LOC_BASEREG_ARG:
case LOC_COMPUTED_ARG:
case LOC_LOCAL:
case LOC_BASEREG:
case LOC_STATIC:
case LOC_REGISTER:
case LOC_COMPUTED:
junk = 0;
break;
}
}
if (!junk && pc < BLOCK_END (block))
{
char *addr;
Tcl_Obj *elt = Tcl_NewListObj (0, NULL);
xasprintf (&addr, "0x%s", paddr_nz (BLOCK_START (block)));
Tcl_ListObjAppendElement (interp, elt,
Tcl_NewStringObj (addr, -1));
free(addr);
xasprintf (&addr, "0x%s", paddr_nz (BLOCK_END (block)));
Tcl_ListObjAppendElement (interp, elt,
Tcl_NewStringObj (addr, -1));
Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr, elt);
free(addr);
}
if (BLOCK_FUNCTION (block))
break;
else
block = BLOCK_SUPERBLOCK (block);
}
}
return TCL_OK;
}
static int
gdb_get_args_command (ClientData clientData, Tcl_Interp *interp,
int objc, Tcl_Obj *CONST objv[])
{
return gdb_get_vars_command ((ClientData) 1, interp, objc, objv);
}
static int
gdb_get_locals_command (ClientData clientData, Tcl_Interp *interp,
int objc, Tcl_Obj *CONST objv[])
{
return gdb_get_vars_command ((ClientData) 0, interp, objc, objv);
}
static int
gdb_get_vars_command (ClientData clientData, Tcl_Interp *interp,
int objc, Tcl_Obj *CONST objv[])
{
struct symtabs_and_lines sals;
struct symbol *sym;
struct block *block;
char **canonical, *args;
struct dict_iterator iter;
int i, arguments;
if (objc > 2)
{
Tcl_WrongNumArgs (interp, 1, objv,
"[function:line|function|line|*addr]");
return TCL_ERROR;
}
arguments = (int) clientData;
Tcl_SetListObj (result_ptr->obj_ptr, 0, NULL);
if (objc == 2)
{
args = Tcl_GetStringFromObj (objv[1], NULL);
sals = decode_line_1 (&args, 1, NULL, 0, &canonical, NULL);
if (sals.nelts == 0)
{
gdbtk_set_result (interp, "error decoding line");
return TCL_ERROR;
}
for (i = 0; i < sals.nelts; i++)
resolve_sal_pc (&sals.sals[i]);
block = block_for_pc (sals.sals[0].pc);
}
else
{
if (deprecated_selected_frame == NULL)
return TCL_OK;
block = get_frame_block (deprecated_selected_frame, 0);
}
while (block != 0)
{
ALL_BLOCK_SYMBOLS (block, iter, sym)
{
switch (SYMBOL_CLASS (sym))
{
default:
case LOC_UNDEF:
case LOC_CONST:
case LOC_TYPEDEF:
case LOC_LABEL:
case LOC_BLOCK:
case LOC_CONST_BYTES:
case LOC_UNRESOLVED:
case LOC_OPTIMIZED_OUT:
break;
case LOC_ARG:
case LOC_REF_ARG:
case LOC_REGPARM:
case LOC_REGPARM_ADDR:
case LOC_LOCAL_ARG:
case LOC_BASEREG_ARG:
case LOC_COMPUTED_ARG:
if (arguments)
Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr,
Tcl_NewStringObj (DEPRECATED_SYMBOL_NAME (sym), -1));
break;
case LOC_LOCAL:
case LOC_BASEREG:
case LOC_STATIC:
case LOC_REGISTER:
case LOC_COMPUTED:
if (!arguments)
Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr,
Tcl_NewStringObj (DEPRECATED_SYMBOL_NAME (sym), -1));
break;
}
}
if (BLOCK_FUNCTION (block))
break;
else
block = BLOCK_SUPERBLOCK (block);
}
return TCL_OK;
}
static int
gdb_selected_block (ClientData clientData, Tcl_Interp *interp,
int objc, Tcl_Obj *CONST objv[])
{
char *start = NULL;
char *end = NULL;
if (deprecated_selected_frame == NULL)
{
xasprintf (&start, "%s", "");
xasprintf (&end, "%s", "");
}
else
{
struct block *block;
block = get_frame_block (deprecated_selected_frame, 0);
xasprintf (&start, "0x%s", paddr_nz (BLOCK_START (block)));
xasprintf (&end, "0x%s", paddr_nz (BLOCK_END (block)));
}
Tcl_SetListObj (result_ptr->obj_ptr, 0, NULL);
Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr,
Tcl_NewStringObj (start, -1));
Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr,
Tcl_NewStringObj (end, -1));
free(start);
free(end);
return TCL_OK;
}
static int
gdb_selected_frame (ClientData clientData, Tcl_Interp *interp,
int objc, Tcl_Obj *CONST objv[])
{
char *frame;
if (deprecated_selected_frame == NULL)
xasprintf (&frame, "%s","");
else
xasprintf (&frame, "0x%s",
paddr_nz (get_frame_base (deprecated_selected_frame)));
Tcl_SetStringObj (result_ptr->obj_ptr, frame, -1);
free(frame);
return TCL_OK;
}
static int
gdb_stack (ClientData clientData, Tcl_Interp *interp,
int objc, Tcl_Obj *CONST objv[])
{
int start, count;
if (objc < 3)
{
Tcl_WrongNumArgs (interp, 1, objv, "start count");
return TCL_ERROR;
}
if (Tcl_GetIntFromObj (NULL, objv[1], &start))
{
result_ptr->flags |= GDBTK_IN_TCL_RESULT;
return TCL_ERROR;
}
if (Tcl_GetIntFromObj (NULL, objv[2], &count))
{
result_ptr->flags |= GDBTK_IN_TCL_RESULT;
return TCL_ERROR;
}
if (target_has_stack)
{
gdb_result r;
struct frame_info *top;
struct frame_info *fi;
r = GDB_get_current_frame (&fi);
if (r != GDB_OK)
return TCL_ERROR;
while (fi != NULL)
{
top = fi;
r = GDB_get_prev_frame (fi, &fi);
if (r != GDB_OK)
fi = NULL;
}
start = -start;
r = GDB_find_relative_frame (top, &start, &top);
result_ptr->obj_ptr = Tcl_NewListObj (0, NULL);
if (r != GDB_OK)
return TCL_OK;
if (start == 0)
{
fi = top;
while (fi && count--)
{
get_frame_name (interp, result_ptr->obj_ptr, fi);
r = GDB_get_next_frame (fi, &fi);
if (r != GDB_OK)
break;
}
}
}
return TCL_OK;
}
static void
get_frame_name (Tcl_Interp *interp, Tcl_Obj *list, struct frame_info *fi)
{
struct symtab_and_line sal;
struct symbol *func = NULL;
register char *funname = 0;
enum language funlang = language_unknown;
Tcl_Obj *objv[1];
if (get_frame_type (fi) == DUMMY_FRAME)
{
objv[0] = Tcl_NewStringObj ("<function called from gdb>\n", -1);
Tcl_ListObjAppendElement (interp, list, objv[0]);
return;
}
if ((get_frame_type (fi) == SIGTRAMP_FRAME))
{
objv[0] = Tcl_NewStringObj ("<signal handler called>\n", -1);
Tcl_ListObjAppendElement (interp, list, objv[0]);
return;
}
sal =
find_pc_line (get_frame_pc (fi),
get_next_frame (fi) != NULL
&& !(get_frame_type (fi) == SIGTRAMP_FRAME)
&& !(get_frame_type (fi) == DUMMY_FRAME));
func = find_pc_function (get_frame_pc (fi));
if (func)
{
struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (get_frame_pc (fi));
if (msymbol != NULL
&& (SYMBOL_VALUE_ADDRESS (msymbol)
> BLOCK_START (SYMBOL_BLOCK_VALUE (func))))
{
func = 0;
funname = GDBTK_SYMBOL_SOURCE_NAME (msymbol);
funlang = SYMBOL_LANGUAGE (msymbol);
}
else
{
funname = GDBTK_SYMBOL_SOURCE_NAME (func);
funlang = SYMBOL_LANGUAGE (func);
}
}
else
{
struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (get_frame_pc (fi));
if (msymbol != NULL)
{
funname = GDBTK_SYMBOL_SOURCE_NAME (msymbol);
funlang = SYMBOL_LANGUAGE (msymbol);
}
}
if (sal.symtab)
{
objv[0] = Tcl_NewStringObj (funname, -1);
Tcl_ListObjAppendElement (interp, list, objv[0]);
}
else
{
#if 0
if (fi->pc != sal.pc || !sal.symtab)
{
print_address_numeric (fi->pc, 1, gdb_stdout);
printf_filtered (" in ");
}
printf_symbol_filtered (gdb_stdout, funname ? funname : "??", funlang,
DMGL_ANSI);
#endif
objv[0] = Tcl_NewStringObj (funname != NULL ? funname : "??", -1);
#ifdef PC_LOAD_SEGMENT
if (!funname)
{
Tcl_AppendStringsToObj (objv[0], " from ", PC_LOAD_SEGMENT (fi->pc),
(char *) NULL);
}
#endif
#ifdef PC_SOLIB
if (!funname)
{
char *lib = PC_SOLIB (get_frame_pc (fi));
if (lib)
{
Tcl_AppendStringsToObj (objv[0], " from ", lib, (char *) NULL);
}
}
#endif
Tcl_ListObjAppendElement (interp, list, objv[0]);
}
}