Files
seta75D d6fe8fe829 Init
2021-10-11 22:19:34 -03:00

396 lines
9.2 KiB
C

static char sccsid[] = "@(#)79 1.9.1.4 src/bos/usr/ccs/lib/libdbx/dpi_stack.c, libdbx, bos411, 9428A410j 11/15/93 13:59:38";
/*
* COMPONENT_NAME: (CMDDBX) - dbx symbolic debugger
*
* FUNCTIONS: dpi_get_traceback, getcallinfo, printtb, tbfree, tbinit,
* tracebackList_append, traceback_alloc
*
* ORIGINS: 26, 27
*
* This module contains IBM CONFIDENTIAL code. -- (IBM
* Confidential Restricted when combined with the aggregated
* modules for this product)
* SOURCE MATERIALS
* (C) COPYRIGHT International Business Machines Corp. 1989
* All Rights Reserved
*
* US Government Users Restricted Rights - Use, duplication or
* disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
*
* Copyright (c) 1982 Regents of the University of California
*
*/
#ifdef KDBXRT
#include "rtnls.h" /* MUST BE FIRST */
#endif
#include <setjmp.h>
#include <signal.h>
#include <sys/termio.h>
#include "defs.h"
#include "envdefs.h"
#include "runtime.h"
#include "frame.h"
#include "events.h"
#include "lists.h"
#include "process.h"
#include "dbx_msg.h"
extern int *envptr; /* setjmp/longjmp data */
extern Ttyinfo ttyinfo;
extern Ttyinfo ttyinfo_in;
extern Boolean walkingstack;
extern nl_catd scmc_catd; /* Catalog descriptor for message conversion */
extern char *realloc();
char *srcfilename( );
private void getcallinfo();
typedef List TracebackList;
#define tracebackList_append(traceback, el) list_append(list_item(traceback), \
nil, el)
private TracebackList tracebackList; /* list of active tracebacks */
/*
* NAME: tbinit
*
* FUNCTION: Allocated and initializes the tracebackList by calling list_alloc()
*
* PARAMETERS: NONE
*
* RECOVERY OPERATION: NONE NEEDED
*
* DATA STRUCTURES: NONE
*
* RETURNS: NONE
*/
public void tbinit( )
{
tracebackList = list_alloc();
}
/*
* NAME: traceback_alloc
*
* FUNCTION: Allocates new traceback element and fills in with information;
* The new element is then appended to the end of tracebackList
*
* PARAMETERS:
* file - File name to be put in traceback element
* function - Function name to be put in traceback element
* line - Line number to be put in traceback element
* address - Address to be put in traceback element
*
* RECOVERY OPERATION: NONE NEEDED
*
* DATA STRUCTURES: NONE
*
* RETURNS: Newly allocated traceback element
*/
private ExecStruct traceback_alloc( file, function, line, address )
char *file;
char *function;
int line;
unsigned int address;
{
register ExecStruct tb;
/*
* Allocate new traceback table element and fill in
*/
tb = new(ExecStruct);
tb->file = file;
tb->function = function;
tb->line = line;
tb->address = address;
/*
* Append the new traceback table element to tracebackList
*/
tracebackList_append(tb, tracebackList);
return tb;
}
/*
* NAME: tbfree
*
* FUNCTION: Free the traceback table
*
* PARAMETERS: NONE
*
* RECOVERY OPERATION: NONE NEEDED
*
* DATA STRUCTURES: NONE
*
* RETURNS: NONE
*/
private void tbfree( )
{
ExecStruct tb;
ListItem cur_item;
foreach (ExecStruct, tb, tracebackList)
dispose(tb->file);
dispose(tb->function);
dispose( tb );
endfor
tracebackList->nitems = 0;
tracebackList->head = nil;
tracebackList->tail = nil;
}
/*
* NAME: dpi_get_traceback
*
* FUNCTION: Fills in dpi_info with the current traceback information
*
* PARAMETERS:
* dpi_info - Allocates an array to hold all items in the traceback
* list. Allocates an element for each of the items in
* the traceback list. The file and function name of
* each traceback element is either allocated or set to
* NULL. This array will have the last item set to NULL.
*
* RECOVERY OPERATION: NONE NEEDED
*
* DATA STRUCTURES: showaggrs - set to false so aggregate values will not be
* part of the name of the function, this is so
* the function can fit on a single line easily
*
* RETURNS: 0 for success
* -1 for failure
*/
public int dpi_get_traceback( dpi_info )
ExecStruct **dpi_info;
{
ExecStruct *tbptr;
ListItem tbitem;
register ExecStruct tb;
int tbnum;
Frame frp;
boolean save = walkingstack;
Symbol f;
struct Frame frame;
extern Boolean call_command;
jmp_buf env;
int *svenv;
svenv = envptr;
envptr = env;
/*
* Initialize dpi_info so that if we fail this will still be valid
*/
*dpi_info = (ExecStruct *) calloc( 1, sizeof( ExecStruct ));
if (setjmp( env )) {
restoretty(stdout, &ttyinfo );
restoretty(stdin, &ttyinfo_in );
envptr = svenv;
walkingstack = save;
return -1;
}
/*
* Free any old traceback table entries
*/
tbfree( );
if (notstarted(process) or isfinished(process)) {
error( catgets( scmc_catd, MS_runtime, MSG_265,
"program is not active" ));
envptr = svenv;
return -1;
} else {
walkingstack = true;
/*
* Set showaggrs so aggregate values won't be printed
*/
showaggrs = false;
/*
* Set f to the function associated with the current frame
*/
frp = &frame;
if (getcurfunc(frp, &f) < 0) {
error( catgets( scmc_catd, MS_runtime, MSG_269,
"Could not determine current function" ));
envptr = svenv;
return -1;
}
/*
* If this is not a call() command, then get the block information
* for the stack
*/
for (;
frp != nil and !call_command and !endofstack(frp);
frp = nextfunc( frp, &f )) {
/*
* Gets information about function f and appends to the
* tracebackList
*/
getcallinfo(f, frp);
}
/*
* Set tbnum to number of items in tracebackList
*/
tbnum = list_size( tracebackList );
/*
* Allocate enough storage for *dpi_info to hold array of traceback
* table elements
*/
*dpi_info = (ExecStruct *) realloc( *dpi_info,
(tbnum + 1) * sizeof( ExecStruct ));
/*
* Put each tracebackList item into *dpi_info array
*/
tbptr = *dpi_info;
foreach( ExecStruct, tb, tracebackList )
*tbptr++ = tb;
endfor
*tbptr = (ExecStruct) nil;
walkingstack = save;
}
envptr = svenv;
return 0;
}
/*
* NAME: getcallinfo
*
* FUNCTION: Get the information about a call, i.e. routine name, parameter
* values, and source location, put this information into a traceback
* table element and append it to tracebackList.
*
* PARAMETERS:
* f - Block to get information on
* frp - Current frame we are interested in
*
* RECOVERY OPERATION: NONE NEEDED
*
* DATA STRUCTURES: NONE
*
* RETURNS: NONE
*/
private void getcallinfo( f, frp )
Symbol f;
Frame frp;
{
Lineno line;
Address caller;
Address address;
char *function;
char *file;
char *tfile;
cases tempcase;
caller = frp->save_pc;
if (caller != reg(SYSREGNO(PROGCTR))) {
/*
* Unless we are in the current procedure, we should use pc - 1
* instruction for the traceback so that we see the call as the current
* location in the caller. The pc always points to the line following
* the call.
*/
/* Let's at least back it up to the previous instruction. */
caller -= 4;
}
/*
* Fill in function with the name of the function and its parameters and
* values
*/
msgbegin;
if (isinline(f)) {
(*rpt_output)(stdout, "unnamed block ");
}
/*
* Get the name of the function
*/
if (frp->tb.name_present && frp->name != nil && frp->name[0] != '\0')
(*rpt_output)(stdout, "%s", frp->name);
else
printname( rpt_output, stdout, f, false);
/*
* If f is a function get its parameters and their values if noargs is not
* set
*/
if ((not isinline(f)) && (!(varIsSet("$noargs")))) {
printparams(f, frp);
}
msgend( function );
if ( *function == '\0' ) {
function = realloc( function, 2 );
strcpy( function, "." );
}
/* get around side effect of srcfilename() modifying our current case */
tempcase = symcase;
/*
* Get source file name associated with caller's address
*/
tfile = srcfilename(caller);
symcase = tempcase;
/*
* Get the line number associated with address of caller;
* line num is no good if no file name
*/
line = ((tfile == nil) ? 0 : srcline(caller));
if (tfile != nil) {
file = malloc( (strlen( tfile ) + 1) * sizeof( char ) );
strcpy( file, tfile );
/*
* Get object address of line from the file
*/
address = objaddr( line, file );
} else {
address = caller;
file = nil;
}
/*
* Create traceback table element and append to tracebackList
*/
(void) traceback_alloc( file, function, line, address );
}
#ifdef ADCDEBUG
void printtb( dpi_info )
ExecStruct *dpi_info;
{
register ExecStruct tb;
register ExecStruct *tbptr;
for ( tbptr = dpi_info; *tbptr != nil; tbptr++ ) {
tb = *tbptr;
(*rpt_output)(stdout, "file: \t%s\n", tb->file);
(*rpt_output)(stdout, "function:\t%s\n", tb->function);
(*rpt_output)(stdout, "line: \t%d\n", tb->line);
(*rpt_output)(stdout, "address: \t0x%x\n\n", tb->address);
tbfree( );
}
}
#endif /* ADCDEBUG */