#include "ppc-reg.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 "nextstep-nat-inferior.h" #include "nextstep-nat-cfm.h" #include "nextstep-nat-dyld-info.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) static unsigned long mread (CORE_ADDR addr, unsigned long len, unsigned long mask) { long ret = read_memory_unsigned_integer (addr, len); if (mask) { ret &= mask; } return ret; } 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; /* When single stepping in assembly, the plugin passes (start + 1) as the stop address. Round the stop address up to the next valid instruction */ 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_address = FRAME_FP (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); } 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 we don't get a request of running in the bg, then we need to simulate synchronous (fg) execution. */ 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 ? ?"); 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); } bfd *FindContainingBFD (CORE_ADDR address) { struct target_stack_item *aTarget; bfd *result = NULL; for (aTarget = target_stack; (result == NULL) && (aTarget != NULL); aTarget = aTarget->next) { struct section_table* sectionTable; if ((NULL == aTarget->target_ops) || (NULL == aTarget->target_ops->to_sections)) { continue; } for (sectionTable = &aTarget->target_ops->to_sections[0]; (result == NULL) && (sectionTable < aTarget->target_ops->to_sections_end); sectionTable++) { if ((address >= sectionTable->addr) && (address < sectionTable->endaddr)) { result = sectionTable->bfd; } } } return result; } static void metrowerks_address_to_name_command (char* args, int from_tty) { CORE_ADDR address; bfd *aBFD; address = strtoul (args, NULL, 16); if (annotation_level > 1) { printf("\n\032\032fragment-name "); } aBFD = FindContainingBFD (address); if (aBFD != NULL) { printf_unfiltered ("%s\n", aBFD->filename); 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"); }