macosx-metrowerks.c [plain text]
#include "macosx-nat-inferior.h"
#include "macosx-nat-cfm.h"
#include "macosx-nat-dyld-info.h"
#define TRUE_FALSE_ALREADY_DEFINED
#include "defs.h"
#include "inferior.h"
#include "gdbcmd.h"
#include "symfile.h"
#include "frame.h"
#include "breakpoint.h"
#include "symtab.h"
#include "annotate.h"
#include "target.h"
#include "breakpoint.h"
#include "gdbcore.h"
#include "event-top.h"
#include "objfiles.h"
#define IS_BC_x(instruction) \
((((instruction) & 0xFC000000) >> 26) == 16)
#define IS_B_x(instruction) \
((((instruction) & 0xFC000000) >> 26) == 18)
#define IS_BCLR_x(instruction) \
(((((instruction) & 0xFC000000) >> 26) == 19) && ((((instruction) & 0x000007FE) >> 1) == 16))
#define IS_BCCTR_x(instruction) \
(((((instruction) & 0xFC000000) >> 26) == 19) && ((((instruction) & 0x000007FE) >> 1) == 528))
#define WILL_LINK(instruction) \
(((instruction) & 0x00000001) != 0)
extern int metrowerks_stepping;
extern CORE_ADDR metrowerks_step_func_start;
extern CORE_ADDR metrowerks_step_func_end;
static void
metrowerks_stepping_cleanup (void *unusued)
{
metrowerks_stepping = 0;
metrowerks_step_func_start = 0;
metrowerks_step_func_end = 0;
}
static void
metrowerks_step (CORE_ADDR range_start, CORE_ADDR range_stop, int step_into)
{
struct frame_info *frame = NULL;
CORE_ADDR pc = 0;
if ((range_stop & ~0x3) != range_stop)
range_stop = ((range_stop + 4) & ~0x3);
pc = read_pc();
if (range_start >= range_stop)
error ("invalid step range (the stop address must be greater than the start address)");
if (pc < range_start)
error ("invalid step range ($pc is 0x%lx, less than the stop address of 0x%lx)",
(unsigned long) pc, (unsigned long) range_start);
if (pc == range_stop)
error ("invalid step range ($pc is 0x%lx, equal to the stop address of 0x%lx)",
(unsigned long) pc, (unsigned long) range_stop);
if (pc > range_stop)
error ("invalid step range ($pc is 0x%lx, greater than the stop address of 0x%lx)",
(unsigned long) pc, (unsigned long) range_stop);
clear_proceed_status ();
frame = get_current_frame ();
if (frame == NULL)
error ("No current frame");
step_frame_id = get_frame_id (frame);
step_sp = read_sp ();
step_range_start = range_start;
step_range_end = range_stop;
step_over_calls = step_into ? STEP_OVER_NONE : STEP_OVER_ALL;
step_multi = 0;
metrowerks_stepping = 1;
proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 1);
make_exec_cleanup (metrowerks_stepping_cleanup, NULL);
}
extern int strip_bg_char (char **);
static void
metrowerks_step_command (char *args, int from_tty)
{
int async_exec = 0;
CORE_ADDR range_start = 0;
CORE_ADDR range_stop = 0;
int step_into = 0;
int num_args = 0;
char **argv = NULL;
if (args != NULL)
async_exec = strip_bg_char (&args);
if (event_loop_p && async_exec && !target_can_async_p ())
error ("Asynchronous execution not supported on this target.");
if (event_loop_p && !async_exec && target_can_async_p ())
{
async_disable_stdin ();
}
argv = buildargv (args);
if (argv == NULL)
{
num_args = 0;
}
else
{
num_args = 0;
while (argv[num_args] != NULL)
num_args++;
}
if (num_args != 3 && num_args != 5)
error ("Usage: metrowerks-step <start> <stop> <step-into> ?<func_start> <func_end>?");
range_start = strtoul (argv[0], NULL, 16);
range_stop = strtoul (argv[1], NULL, 16);
step_into = strtoul (argv[2], NULL, 16);
if (num_args == 5)
{
metrowerks_step_func_start = strtoul (argv[3], NULL, 16);
metrowerks_step_func_end = strtoul (argv[4], NULL, 16);
}
else
{
metrowerks_step_func_start = 0;
metrowerks_step_func_end = 0;
}
if (!target_has_execution)
error ("The program is not being run.");
metrowerks_step (range_start, range_stop, step_into);
}
static void
metrowerks_address_to_name_command (char* args, int from_tty)
{
CORE_ADDR address;
struct obj_section *osection;
errno = 0;
address = strtoul (args, NULL, 16);
if (errno == 0)
{
osection = find_pc_sect_in_ordered_sections (address, NULL);
if (osection != NULL)
{
printf_unfiltered ("%s\n", osection->objfile->name);
return;
}
}
printf_unfiltered ("[unknown]\n");
}
void
_initialize_metrowerks(void)
{
add_com ("metrowerks-step", class_obscure, metrowerks_step_command,
"GDB as MetroNub command");
add_com ("metrowerks-address-to-name", class_obscure, metrowerks_address_to_name_command,
"GDB as MetroNub command");
}