📄 gdb-jtag-arm.c
字号:
/* * Copyright (C) 2004 Lars Kristian Klauske * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. *//* GDB remote server */#include <stdlib.h>#include <stdio.h>#include "jtag.h"#include "debug.h"#include "memory.h"#include "ice.h"#include "lpec.h"/* network functions */#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <sys/poll.h>#define GDB_ANSWER_OK "OK"#define GDB_ANSWER_S05 "S05" /* breakpoint happened */#define GDB_ANSWER_W07 "W07" /* breakpoint happened */#define GDB_ANSWER_W02 "W02" /* interrupt occured */#define GDB_ANSWER_S03 "S03" /* interrupt occured */#define GDB_ANSWER_W00 "W00" /* process stopped */#define GDB_ANSWER_S17 "S17" /* process stopped */#define GDB_ANSWER_E01 "E01" /* error */#define GDB_ANSWER_E02 "E02" /* error */unsigned long SW_BP_PATTERN = 0xe7ffdefe;/* implemented GDB commands:D detachg read registersG<XX...> write registersm<addr>,<length> read memoryM<addr>,<length>:<XX...> write memoryc<addr> continues<addr> step*/int client_socket;long buffersize=10000;int last_running=1;#define sw_bp_max 99unsigned long sw_bp_addr[sw_bp_max+1];unsigned long sw_bp_memdata[sw_bp_max+1];void execute_command(long length, char *cmd);void gdb_write_memory(unsigned long addr, unsigned long length, char *buffer);void gdb_step(void);char HexByte_to_Value(char input) { // is it a number? if ( (input>=0x30) && (input<=0x39) ) return (input-0x30); // or is it a lowercase if ( (input>=0x61) && (input<=0x66) ) return (input-0x57); // or is it an uppercase if ( (input>=0x41) && (input<=0x46) ) return (input-0x37); return 0;}int Calculate_Checksum(long length, char *input) { int ret=0; //int i; for (; length>0; length--) { ret += input[length-1]; ret = ret & 0xff; } return ret;}unsigned long HexString_to_Long (char *input) { #define longsize 8 unsigned long ret; ret = strtoul(input,NULL,16); //printf("Converting: %s - Result: %8.8x\n",input, ret); return ret;}/*unsigned long HexString_to_ULong (char *input) { #define longsize 8 unsigned long ret; ret = strtoul(input,NULL,16); printf("Converting: %s - Result: %8.8x\n",input, ret); return ret; }*/void answer_gdb(long length, char *text) { int checksum=Calculate_Checksum(length, text); char cs_string[5]; sprintf (cs_string, "%02.2x", checksum); if ((text[0]=='+') || (text[0]=='-')) { //printf ("Sending: %c\n",text[0]); write(client_socket, text, 1); } else { printf ("Sending: $%s#%02.2x\n", text, checksum); write(client_socket,"$",1); if (length) write(client_socket,text,length); write(client_socket,"#",1); write(client_socket,cs_string,2); } // fflush(&new_socket); return;} void do_gdb(void) { int socket_desc; struct sockaddr_in address; int addrlen; //int new_socket; struct pollfd ufds = { 0, POLLIN+POLLPRI, 0 }; char buffer[buffersize]; long bufferfill=0; char byte; int state=0; int checksum; for (checksum=0; checksum<=sw_bp_max; checksum++) { sw_bp_memdata[checksum]=SW_BP_PATTERN; sw_bp_addr[checksum]=0; } /* create the master socket and check it worked */ if ((socket_desc=socket(AF_INET,SOCK_STREAM,0))==0) { /* if socket failed then display error and exit */ perror("Create socket"); exit(EXIT_FAILURE); } /* type of socket created */ address.sin_family = AF_INET; address.sin_addr.s_addr = INADDR_ANY; /* use port 8888 */ address.sin_port = htons(8888); /* bind the socket to port 8888 */ if (bind(socket_desc,(struct sockaddr *)&address,sizeof(address))<0) { /* if bind failed then display error message and exit */ perror("bind"); exit(EXIT_FAILURE); } /* accept connection, wait if no connection pending */ addrlen=sizeof(address); listen(socket_desc,1) ; printf("Listening for Connection...\n"); client_socket=accept(socket_desc,(struct sockaddr *)&address,&addrlen); /* inform user of socket number - used in send and receive commands */ printf("Client socket is %d\n",client_socket); state=0; ufds.fd=client_socket; /* stopping target for gdb */ debug_stop(); ice_set_software_breakpoint(0, SW_BP_PATTERN); lpec_init(); last_running=0;// while ( read(client_socket, &byte, 1) == 1 ) { while (client_socket) { if (poll( &ufds, 1, 0 ) > 0) { read(client_socket, &byte, 1); printf("%c",byte); fflush(stdout); switch (state) { case 0: if (byte == '$') { bufferfill=0; state = 1; } break; case 1: if (byte != '#') { if (bufferfill < buffersize-1) { buffer[bufferfill]=byte; /*if (bufferfill==0) { switch (buffer[0]) { case 'M': state=0; execute_command(bufferfill, buffer); break; default: break; } }*/ bufferfill++; } else { bufferfill=0; printf ("Error! Buffer overflow while reading from Socket.\n"); answer_gdb(1,"-"); state=0; } } else { buffer[bufferfill]='\0'; state=2; } break; case 2: checksum=HexByte_to_Value(byte); checksum*=16; state=3; break; case 3: checksum += HexByte_to_Value(byte); printf ("\nCommand: %s", buffer); printf (" - Checksum IN:%02.2x, CA:%02.2x\n",checksum,Calculate_Checksum(bufferfill, buffer)); if (checksum == Calculate_Checksum(bufferfill, buffer)) { answer_gdb(1,"+"); //printf("Answered: Checksum Ok\n"); //printf("Doing Work: %s\n", buffer); execute_command(bufferfill, buffer); } else { answer_gdb(1,"-"); printf("Answered: Checksum Mismatch\n"); } state=0; break; default: break; } fflush(stdout); } else { // invoming Event is not invoked by GDB if (last_running) { printf("."); if (ice_halted()) { debug_save_regs(); answer_gdb(3, "S05"); last_running=0; } } } } /* shutdown master socket properly */ close(socket_desc); return; }void execute_command(long length, char *cmd) { int retsize=0; //char *MemoryAdressString; //char *MemoryLengthString; long MemoryAddress; long MemoryLength; char *MemoryData; unsigned long *MemoryLongData; long MemoryDataLength=0; long MemoryTemp=0; long MemoryFirstValue=0; long MemoryBlah=0; char MemoryTempString[10]; int tempI=0; long tempL=0; switch (cmd[0]) { case 'H': // set thread answer_gdb(2,"OK"); printf("(set thread)\n"); break; case 'g': // read registers retsize = gdb_read_registers(buffersize, cmd); answer_gdb(retsize,cmd); printf("(read registers)\n"); break; case 'G': // write registers //answer_gdb(0,"\0"); retsize=gdb_write_registers(cmd); answer_gdb(2,"OK"); printf("(write registers)\n"); break; case 'P': // write a particular register answer_gdb(0,"\0"); printf("(write a particular register)\n"); break; case 'm': // read memory for (tempL=1; ((tempL<=8) && (cmd[tempL]!=',')); tempL++); cmd[tempL]='\0'; MemoryAddress=HexString_to_Long(cmd+1); MemoryLength=HexString_to_Long(cmd+tempL+1); MemoryLength = MemoryLength >> 2; // read full 32bit only // printf("Reading %8.8x Longs from %8.8x\n",MemoryLength,MemoryAddress); MemoryLongData = malloc(sizeof(long)*MemoryLength); MemoryData = malloc(sizeof(long)*(MemoryLength+1)*2); memory_read(MemoryAddress, MemoryLongData, MemoryLength); for (tempL=0; tempL<MemoryLength; tempL++) { MemoryTemp=tempL*sizeof(long)*2; sprintf( MemoryData+MemoryTemp, "%8.8x", MemoryLongData[tempL]); } answer_gdb(MemoryLength*2*sizeof(long), MemoryData); printf("(read memory)\n"); free(MemoryLongData); free(MemoryData); break; case 'M': // write memory cmd ++; /* read address */ for (tempL=0; ((tempL<8) && (cmd[tempL]!=',')); tempL++); cmd[tempL]='\0'; MemoryAddress=HexString_to_Long(cmd); cmd += tempL+1; /* read length */ for (tempL=0; ((tempL<8) && (cmd[tempL]!=':')); tempL++); cmd[tempL]='\0'; MemoryLength=HexString_to_Long(cmd); cmd += tempL+1; gdb_write_memory(MemoryAddress, MemoryLength, cmd); answer_gdb(2,"OK"); printf("(write memory)\n"); break; case 'X': // write memory, binary data answer_gdb(0,"\0"); printf("(write memory, binary data)\n"); break; case 'z': // delete breakpoint printf("(delete breakpoint)\n"); retsize = gdb_remove_breakpoint(buffersize, cmd+1); if (retsize) { answer_gdb(0, "\0"); } else { answer_gdb(2, "OK"); } break; case 'Z': // set breakpoint printf("(set breakpoint)\n"); retsize = gdb_insert_breakpoint(buffersize, cmd+1); if (retsize) { answer_gdb(0, "\0"); } else { answer_gdb(2, "OK"); } break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -