📄 rdi150-low.c
字号:
/* RDI 1.5 translation code for Arm Multi-ice server for GDB. Copyright (C) 1999 Free Software Foundation, Inc.This file is part of GDB.This program is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2 of the License, or(at your option) any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */typedef unsigned int unsigned32;typedef unsigned short unsigned16;typedef unsigned char unsigned8;typedef int bool;#include "defs.h"#include "target.h" /* For "enum target_signal" */#include "server.h"#include "low.h"#include "remote-utils.h"#include "tm.h"/* These are all the WinRDI defines that we need. */#include "windows.h"#include "host.h"#include "rdi.h"#include "rdi150.h"#include "rdi_hif.h"#include "rdi_conf.h"#include "rdi_info.h"#include "winrdi.h"/* This is set in low_resume, it indicates when we are running. This is so that a call to low_close_target can know to stop the target before it tries to shut down.*/int currently_running = 0;/* * We will keep a linked list of the RDI "points" that have been set. * We need these tokens to delete the points again. */struct rdi_points { RDI_PointHandle handle; CORE_ADDR addr; struct rdi_points *next;};struct rdi_points *breakpoint_list; /* This one keeps the breakpoints. */struct rdi_points *watchpoint_list; /* This one the watchpoints. *//* * Really have to do better than this... I don't want to put routines * that need platform types in server.h, so I need to abstract the "window" * type, and coerce on the other end. For another day. */extern HWND get_main_window (void);/* Pointers to the functions we have dug out of the Multi-ICE DLL. */WinRDI_funcGetVersion winRDI_GetVersion;WinRDI_funcValid_RDI_DLL winRDI_Valid_RDI_DLL;WinRDI_funcGet_DLL_Description winRDI_Get_DLL_Description;WinRDI_funcGetRDIProcVec winRDI_GetRDIProcVec;WinRDI_funcInitialise winRDI_Initialise;WinRDI_funcConsoleInitialise winRDI_ConsoleInitialise;WinRDI_funcConfig winRDI_Config;WinRDI_funcRegister_Yield_Callback winRDI_Register_Yield_Callback;/* * This is the RDI proc vector */struct RDI_ProcVec * rdi_proc_vec;/* This is the that we need to pass to WinRDI_Initialise. There are a lot of * other calls that this also gets passed to, but according to the docs, it is * ignored in all of them. */RDI_ConfigPointer gdb_config;/* * This is the agent handle for the arm processor. It is filled out * in the initialisation section. */RDI_AgentHandle gdb_agent;RDI_DbgState *gdb_debug_state;/* * This is the interface for debug messages used by the Multi-ICE. */struct RDI_HostosInterface gdb_IO_struct;/* * proc_desc_array is the Array of processor modules for the ARM's * et al on the * board. num_procs is the number of processers on board. */unsigned num_procs;RDI_ModuleDesc *proc_desc_array = NULL;/* * TARGET_ARM_CORE is the index in the proc_desc_array for the arm * core we are debugging. We are not currently prepared to debug more * than one Arm core, and have no interface to set which core * to debug, so for now this is just set to the first arm we find. * Set it to -1 on startup, and then low_open_target will set it to * the correct value. * * TARGET_ARM_MODULE is just a convenience for * * proc_desc_array[target_arm_core].handle * * which we use all the time. */int target_arm_core = -1;RDI_ModuleHandle target_arm_module = NULL;/* Gives the target byte order returned from the RDI initialization for the "target_arm_core" processor. I don't understand the response that I get back from the RDI info call for ByteSex, so for now, initialize this to the same value you put in the cfnArray's BYTESEX parameter below. */int target_byte_order = BIG_ENDIAN;/* Does the target_arm_core support single-stepping? */int target_step = 0;/* TARGET_LOAD_SIZE is the largest Memory write that the target supports Not all targets support reporting this, -1 indicates unknown. */int target_load_size = -1;/* If TARGET_STOP_OTHERS = 1, then a resume stops all the other processors. */int target_stop_others = 0;/* * This is the default Toolconf database that we will use. * Because the RDIinfo ByteSex call comes back with some * response I don't understand, be sure to initialize * target_byte_order to the value in the BYTESEX field below. * Also, the array needs to end with a NULL element. *//* This was the original version of the array that I cooked up based on Multi-ICE 1.0. It doesn't work with versions >= 1.3, however.*/char *cfnArray[] = {"MEMORYSIZE=0","SERIALPORT=1","SERIALLINESPEED=0","PARALLELPORT=1","PARALLELLINESPEED=1","LLSYMSNEEDPREFIX=TRUE","RDITYPE=0","HEARTBEAT=TRUE","MICETAPPOS1=0","RESET=FALSE","MICEDBGCONN=","MICEDRIVER1=","MICESERVER=localhost","MICETAPPOS0=0","FPE=TRUE",/* These fields were added from on the advice of David Adshead from ARM. They work with versions > 1.3 of the Multi-ICE DLL. Some of these fields need to get filled in for the DLL to start properly. If they are not filled the get_agent call will report success, but will return a null agent token, which is not good. I haven't played around with which ones are needed, however.*/"Multi-ICE_Tap1_Position=0","Multi-ICE_Connection_Name=","Multi-ICE_Driver1_Name=","Multi-ICE_Server_Location=localhost","Multi-ICE_Tap0_Position=0","Multi-ICE_DLL_Settings=0",NULL};char *target_driver_name = "ARM7TDMI"; /* Default driver *//* Define the registers array here. */char *aregisters;char hold_registers[REGISTER_BYTES]; /* Used while running thread code on target */int registers_up_to_date = 0;int registers_are_dirty = 0;int need_to_abort = 0;/* * Defines for functions used only in this file. */RDI_Hif_DbgPrint my_IO_dbgprint;RDI_Hif_DbgPause my_IO_dbgpause;void my_IO_dbgarg(RDI_Hif_DbgArg *arg);RDI_Hif_WriteC my_IO_writec;RDI_Hif_ReadC my_IO_readc;RDI_Hif_Write my_IO_write;RDI_Hif_GetS my_IO_gets;RDI_Hif_ResetProc my_IO_reset;void my_IO_resetarg(RDI_Hif_ResetArg *arg); char *rdi_error_message (int err);static int rdi_to_gdb_signal (int rdi_error);void record_register (int regno, ARMword val);ARMword restore_register (int regno);/* These functions come from arm-singlestep.c */extern CORE_ADDR server_arm_get_next_pc (CORE_ADDR pc, unsigned short *is_thumb);extern int arm_pc_is_thumb (bfd_vma memaddr);/* Yield callback */static int yield_arg;static int yield_count;#define YIELD_PERIOD 10voidyield_func(WinRDI_YieldArg *arg){ ARMword empty; if (++yield_count == YIELD_PERIOD) { yield_count = 0; check_for_SIGIO(); } if (need_to_abort) { need_to_abort = 0; rdi_proc_vec->info (target_arm_module, RDISignal_Stop, &empty, &empty); }}/* * low_open_target * * This opens the connection to the target board. TARGET_PORT * gives the port address for the board. If QUERY is 1, the * user is queried for the setup of the connection parameters. */intlow_open_target (char *target_port, char *byte_sex, int query){ int vers; int valid, result = 0; unsigned i; unsigned write_mask = 0; ARMword null_value[2] = {0, 0}; unsigned open_type; ARMword flags, dummy; HINSTANCE handle; HWND main_win; char driver[64]; /* * First, we will open the Multi-ICE DLL and dig all the procs * that we need out of it. */ handle = LoadLibrary ("Multi-ICE.dll"); if (handle == NULL) { output_error ("Could not load the Multi-ICE DLL\n"); return 0; } winRDI_GetVersion = WinRDI_GetProcAddress (handle, GetVersion); if (winRDI_GetVersion == NULL) { output_error ("Could not get GetVersion from the Multi-ICE DLL\n"); return 0; } winRDI_Valid_RDI_DLL = WinRDI_GetProcAddress (handle, Valid_RDI_DLL); if (winRDI_Valid_RDI_DLL == NULL) { output_error ("Could not get Valid_RDI_DLL from the Multi-ICE DLL\n"); return 0; } winRDI_Get_DLL_Description = WinRDI_GetProcAddress (handle, Get_DLL_Description); if (winRDI_Get_DLL_Description == NULL) { output_error ("Could not get Get_DLL_Description from the Multi-ICE DLL\n"); return 0; } winRDI_Config = WinRDI_GetProcAddress (handle, Config); if (winRDI_Config == NULL) { output_error ("Could not get Config from the Multi-ICE DLL\n"); return 0; } winRDI_Initialise = WinRDI_GetProcAddress (handle, Initialise); if (winRDI_Initialise == NULL) { output_error ("Could not get Initialise from the Multi-ICE DLL\n"); return 0; } winRDI_GetRDIProcVec = WinRDI_GetProcAddress (handle, GetRDIProcVec); if (winRDI_GetRDIProcVec == NULL) { output_error ("Could not get GetRDIProcVec from the Multi-ICE DLL\n"); return 0; } winRDI_Register_Yield_Callback = WinRDI_GetProcAddress (handle, Register_Yield_Callback); if (winRDI_Register_Yield_Callback == NULL) { output_error ("Could not get Register_Yield_Callback from the Multi-ICE DLL\n"); return 0; } /* Register a "yield" callback so we can regain control while 'executing' */ winRDI_Register_Yield_Callback(yield_func, (WinRDI_YieldArg *)&yield_arg); /* * Okay, now we are ready to start the actual initialization process. * First we check that the DLL is copasetic, then start to open the * connection to the target. */ valid = winRDI_Valid_RDI_DLL (); if (!valid) { output_error ("RDI DLL says it is not valid\n"); return 0; } vers = winRDI_GetVersion (); if (vers < 150 || vers >= 200) { output_error ("RDI version mismatch, expected 150 <> 200, got %d\n", vers); return 0; } rdi_proc_vec = winRDI_GetRDIProcVec (); if (rdi_proc_vec == NULL) { output_error ("Got null proc vector from GetRDIProcVec\n"); return 0; } /* * Now fill the ToolConf database. Some of these have to be * filled BEFORE you call winRDI_Initialise, or the DLL will * crash in random places... This is supposed to be fixed in * the 1.4 version of the DLL. */ gdb_config = ToolConf_New (30); for (i = 0; cfnArray[i] != NULL; i++) { ToolConf_Add (gdb_config, cfnArray[i]); } if (target_port != NULL) { char buffer[256]; /* This is the Multi-ICE DLL < 1.3 version. */ sprintf (buffer, "MICESERVER=%s", target_port); ToolConf_Update (gdb_config, buffer); /* This is the Multi-ICE DLL >= 1.3 version. */ sprintf (buffer, "Multi-ICE_Server_Location=%s", target_port); ToolConf_Update (gdb_config, buffer); } if (byte_sex != NULL) { if (*byte_sex == 'b' || *byte_sex == 'B') { ToolConf_Update (gdb_config, "BYTESEX=BIG"); target_byte_order = BIG_ENDIAN; } else if (*byte_sex == 'l' || *byte_sex == 'L') { ToolConf_Update (gdb_config, "BYTESEX=LITTLE"); target_byte_order = LITTLE_ENDIAN; } } sprintf(driver, "Multi-ICE_Driver0_Name=%s", target_driver_name); ToolConf_Update (gdb_config, driver); /* There seems to be some confusion about the real name here */ sprintf(driver, "MICEDRIVER0=%s", target_driver_name); ToolConf_Update (gdb_config, driver); main_win = get_main_window (); if (main_win == NULL) { output_error ("The main window handle was null.\n"); return 0; } if (query) { result = winRDI_Config (gdb_config, main_win); if (!result) { output_error ("Configure failed...\n"); return 0; } } result = winRDI_Initialise (main_win, gdb_config); if (!result) { output_error ("Initialise failed...\n"); return 0; } /* * Set the open type to cold boot, reset comm, byte sex dont care */ open_type = (0 << RDIOpen_BootLevel); open_type |= (1 << RDIOpen_CommsReset); open_type |= (RDISex_DontCare << RDIOpen_ByteSexShift); /* * Fill the IO structure with the appropriate functions. */ gdb_IO_struct.dbgprint = my_IO_dbgprint; gdb_IO_struct.dbgpause = my_IO_dbgpause; gdb_IO_struct.writec = my_IO_writec; gdb_IO_struct.readc = my_IO_readc; gdb_IO_struct.write = my_IO_write; gdb_IO_struct.gets = my_IO_gets; result = rdi_proc_vec->openagent (&gdb_agent, open_type, gdb_config, &gdb_IO_struct, gdb_debug_state); if (result != RDIError_NoError) { output_error ("RDI_OpenAgent failed with error %d.\n", result); if (gdb_agent != NULL) { rdi_proc_vec->closeagent (gdb_agent); } return 0; } /* * Next, query the agent to find out how many processors are on * board, get the info for these, and open them all. Note that * you have to open all of them even though you only intend to * talk to one of them. */ num_procs = 0; result = rdi_proc_vec->info (gdb_agent, RDIInfo_Modules, (ARMword *) &num_procs, (ARMword *) NULL); if (num_procs == 0) { output_error ("Found no processors for agent %d\n", gdb_agent); return 0; } proc_desc_array = (RDI_ModuleDesc *) malloc(sizeof(RDI_ModuleDesc) * num_procs); result = rdi_proc_vec->info(gdb_agent, RDIInfo_Modules, (ARMword *) &num_procs, (ARMword *) proc_desc_array); for (i = 0; i < num_procs; i++) { /* * Some modules may have their own RDI vectors, use it if * it is present. */ if (proc_desc_array[i].rdi == NULL) { result = rdi_proc_vec->open (proc_desc_array[i].handle, open_type, gdb_config, &gdb_IO_struct, gdb_debug_state); } else { result = proc_desc_array[i].rdi->open (proc_desc_array[i].handle, open_type, gdb_config, &gdb_IO_struct, gdb_debug_state); } if (result != RDIError_NoError && result != RDIError_LittleEndian && result != RDIError_BigEndian) { int j; output_error ("Error #%d opening module module %d\n%s\n", result, i, rdi_error_message(result)); for (j = 0; j < i; j++) { if (proc_desc_array[j].rdi == NULL) { result = rdi_proc_vec->close (proc_desc_array[j].handle); } else { result = proc_desc_array[j].rdi->close (proc_desc_array[j].handle); } } rdi_proc_vec->closeagent (gdb_agent); return 0; } /* * For now there is no interface to tell us which ARM core * you want to debug. We default to the first one found. * At this point we also get its byte order. */ if (target_arm_core < 0) { if (strcmp (proc_desc_array[i].type, "ARM") == 0) { unsigned32 sex; target_arm_core = i; target_arm_module = proc_desc_array[i].handle; #if 0 rdi_proc_vec->info(target_arm_module, RDIInfo_ByteSex, &sex, NULL); /* The "sex" value is coming back with some bogus value, so if I don't recognize it, just leave it alone, since the code above sets it to whatever I have requested... */ if (sex == RDISex_Big) { target_byte_order = BIG_ENDIAN; } else if (sex == RDISex_Little) { target_byte_order = LITTLE_ENDIAN; } #else if (result == RDIError_BigEndian) target_byte_order = BIG_ENDIAN; else if (result == RDIError_LittleEndian) target_byte_order = LITTLE_ENDIAN; else output_error ("Target didn't return ARM endianness");#endif } } } if (target_arm_core < 0) { low_close_target(); output_error ("Didn't find a core of type \"ARM\" on target.\n"); return 0; } /* * Set the frame pointer to zero. Sometimes if you power-cycle * the board this can be pointing off into never-never land, and * that can confuse GDB no end. */ write_mask = ( 1 << 11 ); write_mask |= (1 << 15); rdi_proc_vec->CPUwrite (target_arm_module, RDIMode_Curr, write_mask, null_value); /* * Finally, write out some information on the processor we * are connected to: */ output ("\nConnected to the Multi-Ice target.\n\n"); output ("Targeted ARM core: %s\n", proc_desc_array[target_arm_core].name);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -