/******************************************************************** * DMW_TargetShell.c * - Simple target shell * * Copyright (c)2004 Digital STREAM Tech, Inc. * All Rights Reserved * * $Id: DMW_TargetShell.c,v 1.3 2011/11/18 04:08:33 megakiss Exp $ * *********************************************************************/ #include "stdlib.h" #include "dsthalcommon.h" #include "dstoslayer.h" //#include "DMW_Common.h" //#include "DMW_Errors.h" // #include "DMW_SymTbl.h" //#include "DMW_TargetShell.h" //#include "DMW_ChannelAPI.h" //#include "DMW_DebugUtil.h"//debug //#include "DST_Common.h" //#define _TSHELL_DEBUG_ #ifdef UCOS #define TSHELL_TASK_PRIORITY DMW_TASK_PRIO_TARGET_SHELL #else #define TSHELL_TASK_PRIORITY 128 #endif #define TSHELL_TASK_STACKSIZE 4096 #define TSHELL_MAX_LENGTH 85 #define whitespace(c) (((c)==' ') || ((c) == '\t')|| ((c) == '\n')) #define TSHELL_MAX_NUM_PARAM 10 // tshell¿¡¼­ ÃÖ´ë 10°³ÀÇ ÀÎÀÚ¸¦ ¹ÞÀ» ¼ö ÀÖ´Ù. // µû¶ó¼­ ¾Æ·¡ÀÇ function pointer¸¦ 5°³±îÁö ¹ÞÀ» ¼ö ÀÖ°Ô ¸¸µç´Ù. // debug static int tsprint(char *fmt, ...); int g_Trace_TShell = DS_TRUE; // master dbg mode ON/OFF // function pointer definition. ÀÎÀÚ´Â ¸ðµÎ int¸¸ Áö¿øÇÑ´Ù. typedef char (*FUNCPTR_10)(int,int,int,int,int,int,int,int,int,int); // command completion typedef char (*compentry_func_t)(const char *,int); static DS_BOOL g_TShellInitialized=DS_FALSE; static DS_BOOL g_TShellTerminted=DS_FALSE; OS_TASK_ID DMW_TShellTaskID=0; int quit() { exit(0); g_TShellTerminted=DS_TRUE; return 0; } const char * DMW_SymbolTypeString(unsigned char type) { if(type&0x1){//global return ((type&0x1e)==SYM_TEXT?"G_TEXT": (type&0x1e)==SYM_DATA?"G_DATA": (type&0x1e)==SYM_ABS?"G_ABS": (type&0x1e)==SYM_BSS?"G_BSS": (type&0x1e)==SYM_COMM?"G_COMM":"UnKnown"); }else{//local or unde return ("UNDF or LOCAL"); } } void help() { tsprint("========================================\n"); tsprint(" TShell Help\n"); tsprint(" [command] : [description] \n"); tsprint("----------------------------------------\n"); tsprint(" [?] : [print help] \n"); tsprint(" [/] : [repeat command] \n"); tsprint("========================================\n"); } ///////////////////////////////////////////////////////// ///////////////////////////////////////////////////////// /// string utilities.. DS_BOOL isHexString(char *s) { DS_BOOL result=DS_FALSE; //check hex if ((*s == '0' && *(s + 1) == 'X')|| (*s == '0' && *(s + 1) == 'x') ) { result=DS_TRUE; } return result; } unsigned int string2unint(char *value) { typedef struct CHexMap_T { char chr; int value; } CHexMap; int HexMapL = 22;//16; CHexMap HexMap[22] = { {'0', 0}, {'1', 1}, {'2', 2}, {'3', 3}, {'4', 4}, {'5', 5}, {'6', 6}, {'7', 7}, {'8', 8}, {'9', 9}, {'A', 10}, {'B', 11}, {'C', 12}, {'D', 13}, {'E', 14}, {'F', 15}, {'a', 10}, {'b', 11}, {'c', 12}, {'d', 13}, {'e', 14}, {'f', 15} }; char *s = value; int result = 0; unsigned int uresult=0; int i; DS_BOOL firsttime = DS_TRUE; //check hex if(isHexString(s)){ s += 2; }else{ printf("[Warning] It is not hexa. \n"); //result=atoi(s); uresult=0; return uresult; } while (*s != '\0') { DS_BOOL found = DS_FALSE; for (i = 0; i < HexMapL; i++) { if (*s == HexMap[i].chr) { if (!firsttime) { result <<= 4; uresult <<=4; } result |= HexMap[i].value; uresult |= HexMap[i].value; found = DS_TRUE; break; } } if (!found) break; s++; firsttime = DS_FALSE; } // printf("result =%d lresult =%d,(0x%x)\n",result,uresult,uresult); return uresult; } char *dupstr(char *s) { char *r; r=OS_malloc(strlen(s) +1); if(r==0){ printf("Error! Can't allocate memory! \n"); return NULL; } strcpy(r,s); return (r); } /* Look up NAME as the name of a command, and return a pointer to that command. Return a NULL pointer if NAME isn't a command name. */ DMW_SYMBOL_T * find_command ( char *name) { #ifdef _MAKEFILE_INCLUDE_TSHELL_ register int i=0; for (i = 0; DMW_SymbolTbl[i].name; i++) if (strcmp (name, DMW_SymbolTbl[i].name) == 0) return (&DMW_SymbolTbl[i]); #endif return ((DMW_SYMBOL_T *)NULL); } //execute_line->DMW_ExecuteSymbol À̸§ º¯°æ. 2005.12.13 /* Execute a command line. */ int DMW_ExecuteSymbol (char *line) { register int i; int k=0; DMW_SYMBOL_T *command; char *word; int nParamCnt=0; char *param[TSHELL_MAX_NUM_PARAM]; int paramint[TSHELL_MAX_NUM_PARAM]; int return_value=0; /* Isolate the command word. */ i = 0; while (line[i] && whitespace (line[i])) i++; word = line + i; while (line[i] && !whitespace (line[i])) i++; if (line[i]) line[i++] = '\0'; tsprint("[INFO] cmd: [%s] \n",word); command = find_command (word); if (!command){ fprintf (stderr, "%s: No such command for TShell.\n", word); return (-1); } /* Get argument to command, if any. */ for(k=0;ktype==(SYM_TEXT|SYM_GLOBAL)){//text=>function #ifdef _TSHELL_DEBUG_ tsprint("[INFO]Fucntion(%s) %s = 0x%x\n",DMW_SymbolTypeString(command->type),command->name,*(command->value)); #endif return_value=(*(FUNCPTR_10)(command->value))(paramint[0], paramint[1], paramint[2], paramint[3], paramint[4], paramint[5], paramint[6], paramint[7], paramint[8], paramint[9]); tsprint("[INFO] return of [%s] func : %d[0x%x] \n",command->name,return_value,return_value); }else{//data if(nParamCnt>1){//set: º¯¼ö = 1 ÀÌ·± ÇüÅÂÀÓ. if ((strcmp (param[0], "=") == 0) ){ *(command->value)= paramint[1]; tsprint("[INFO]Set Data %s = %d\n",command->name,*(command->value)); }else{ tsprint("[ERROR] Invalid set format:[ variable] = [decima_number] param:%s %s\n",param[0],param[1]); } }else{//get tsprint("[INFO]Get Data(%s) %s = 0x%x\n",DMW_SymbolTypeString(command->type),command->name,*(command->value)); } } return 0; } // ÀÌ ÇÔ¼ö´Â string¿¡¼­ white space(' ', '\t')¸¦ ¾ø¾ÖÁÖ°í // ù¹øÂ° non-null word¸¦ °¡Á®¿Â´Ù.(¸¶Áö¸·¿¡ \0¸¦ ºÙÀδÙ.) /* Strip whitespace from the start and end of STRING. Return a pointer into STRING. */ char * stripwhite(char * string) { register char *s, *t; for(s= string; whitespace(*s);s++); if(*s ==0) return (s); t = s + strlen(s) -1; while(t > s && whitespace(*t)) t--; *++t = '\0'; return s; } #if 0 ___completion___() #endif //first time if state=DS_FALSE char * command_generator (const char *text,int state) { #ifdef _MAKEFILE_INCLUDE_TSHELL_ static int list_index = 0; static int len = 0; char *name; // first time if(!state){ list_index=0; len=strlen(text); } //return the next name which partially matches from symbol table while((name=DMW_SymbolTbl[list_index].name)!=NULL){ list_index++; if(strncmp(name,text,len)==0) return (dupstr(name)); } #endif //if no mateched return ((char*)NULL); } #if 0 /* Find the common prefix of the list of matches, and put it into matches[0]. */ static int compute_lcd_of_matches (char **match_list, int matches, const char *text) { register int i, c1, c2, si; int low; /* Count of max-matched characters. */ /* If only one match, just use that. Otherwise, compare each member of the list with the next, finding out where they stop matching. */ if (matches == 1){ match_list[0] = match_list[1]; match_list[1] = (char *)NULL; return 1; } for (i = 1, low = 100000; i < matches; i++){ for (si = 0; (c1 = match_list[i][si]) && (c2 = match_list[i + 1][si]); si++) if (c1 != c2) break; if (low > si) low = si; } /* If there were multiple matches, but none matched up to even the first character, and the user typed something, use that as the value of matches[0]. */ if (low == 0 && text && *text){ match_list[0] = (char *)OS_Malloc (strlen (text) + 1); strcpy (match_list[0], text); }else{ match_list[0] = (char *)OS_Malloc (low + 1); strncpy (match_list[0], match_list[1], low); match_list[0][low] = '\0'; } return matches; } #endif /* Return an array of (char *) which is a list of completions for TEXT. If there are no completions, return a NULL pointer. The first entry in the returned array is the substitution for TEXT. The remaining entries are the possible completions. The array is terminated with a NULL pointer. ENTRY_FUNCTION is a function of two args, and returns a (char *). The first argument is TEXT. The second is a state argument; it should be zero on the first call, and non-zero on subsequent calls. It returns a NULL pointer to the caller when there are no more matches. */ #if 0 char ** completion_matches(const char *text, compentry_func_t *entry_function) { /* Number of slots in match_list. */ int match_list_size; /* The list of matches. */ char **match_list; /* Number of matches actually found. */ int matches; /* Temporary string binder. */ char *string; matches = 0; match_list_size = 10; match_list = (char **)OS_Malloc ((match_list_size + 1) * sizeof (char *)); match_list[1] = (char *)NULL; while ((compentry_func_t *)string = (*entry_function) (text, matches)){ if (matches + 1 == match_list_size) OS_Realloc(&match_list, 0, ((match_list_size += 10) + 1) * sizeof (char *)); match_list[++matches] = string; match_list[matches + 1] = (char *)NULL; } /* If there were any matches, then look through them finding out the lowest common denominator. That then becomes match_list[0]. */ if (matches) compute_lcd_of_matches (match_list, matches, text); else /* There were no matches. */ { OS_Free (&match_list); match_list = (char **)NULL; } return (match_list); } #endif void free_match_list(char **matches) { register int i; if(matches==0) return; for(i=0;matches[i];i++) OS_free(&matches[i]); OS_free(&matches); } #ifdef UCOS //read a line int s, return length // lim is maximum s length int getline(char s[], int lim) { int c=0,i=0; while(--lim > 0 && (c=getchar()) !=EOF && c != '\n'){ //while(--lim > 0 && (c=getchar()) !=EOF && c != '\n' && c != '\t'){ s[i++]=c; } if(c == '\n') s[i++]=c; s[i] = '\0'; return i; } #endif #if 0 ___TShell___() #endif //tShell Task void tDMW_TShellTask() { char userInput[TSHELL_MAX_LENGTH]; char *s; // leon 2004.08.17: #last_cmd char lastuserInput[TSHELL_MAX_LENGTH]; while(1){ if(g_TShellTerminted){ break; } //tshell prompt #if 1 printf("\r\n[tShell]# "); #else printf("\r\n[tShell]# "); #endif //get line #ifdef UCOS getline(userInput,sizeof(userInput)); #else fgets(userInput,sizeof(userInput),stdin); #endif //process with userInput s = stripwhite(userInput); // spetial command process! if(strcmp(s,"/")==0){ tsprint(" >>repeat cmd: [%s]\n",lastuserInput); memcpy(s,lastuserInput,sizeof(lastuserInput)); }else if(strcmp(s,"")!=0){ memcpy(lastuserInput,userInput,sizeof(userInput)); tsprint(" last input: [%s]\n",lastuserInput); } if(strcmp(s,"?")==0){ help(); continue; } if(*s){ DMW_ExecuteSymbol(s);//execute_line -> DMW_ExecuteSymbol } OS_Delay(1); }//while tsprint("[INFO] TShell is self-deleted! \n"); OS_SelfDeleteTask(); } #ifndef USE_CYGWIN void seg_dbg(void); #endif int DMW_TargetShellInit() { int err=0; OS_TASK_ID tid=0; // target shell thread¸¦ ¸¸µç´Ù. if(!g_TShellInitialized){ tid = OS_SpawnTask((void (*)(DS_U32))tDMW_TShellTask, "tShell", TSHELL_TASK_PRIORITY, TSHELL_TASK_STACKSIZE, 0); if (tid == 0) { tsprint("!!! OS_SpawnTask error! dmc_TaskID %x\n", tid); return 3703;//outOfOSResourcesError; } *(OS_TASK_ID *)&DMW_TShellTaskID = tid; g_TShellInitialized = DS_TRUE; tsprint("[INFO] DMW Target Shell is created! tid=%d\n",tid); } #ifndef USE_CYGWIN //seg_dbg(); #endif return err; } int DMW_TargetShellClose() { int err=0; //target shell thread¸¦ Á×ÀδÙ. quit(); //¹Ù·Î Á×Áö ¾ÊÀ» ¼ö ÀÖ´Ù. ¿Ö³Ä¸é ÀԷºκп¡¼­ hold // ³ªÁß¿¡ ÀÛ¾÷ÇØ¾ßµÈ´Ù. return err; } int DSTAPI_ExecuteDSTSymbol(char *pUserInput) { int err = 0;//statusOK; #ifdef _MAKEFILE_INCLUDE_TSHELL_ if ( DMW_ExecuteSymbol (pUserInput) < 0 ) err = -7100;//statusError; #endif return err; } /******************************************************** Debug routines ********************************************************/ #if 0 _____Debug_____() #endif static int tsprint(char *fmt, ...) { // extern int DMW_DBG_Print(char *prefix, char *fmt, ...); // extern int DMW_DBG_Print3(char *prefix, char *fmt,va_list ap); static char msgPrefix[256]; // ¶ç¾î¾²±â¿ë °ø¹éµµ Æ÷ÇÔ½Ãų°Í. va_list v; int n=0; if (!g_Trace_TShell) return 0; // printf(""); sprintf(msgPrefix, "[TShell] %s", fmt);//taskName va_start(v, fmt); n = printf(msgPrefix, v); va_end(v); // printf(""); return n; } #ifndef USE_CYGWIN #include #include #ifndef USE_CYGWIN #include #endif #include //#include #define DEBUG 0 typedef enum tag_SMMType { SMMType_CODE, // Read & Execute SMMType_DATA, // Read & Write SMMType_OTHER, // Read Only or All SMMType_STACK, SMMType_UNUSED // None of Read/Write/Execute } SMMType; typedef struct tag_SharedMemoryMap { SMMType Type; unsigned long StartAddress; unsigned long EndAddress; char name[256]; } SharedMemoryMap; SharedMemoryMap g_SMMTbl[256]; int g_SMMTblCount = 0; // // --> Shared Memory ¿µ¿ªÀº??? // #define ISDATAADDR(v) isStackAddress(v) #define ISCODEADDR(v) isCodeAddress(v) int isStackAddress( unsigned long Address ); int isCodeAddress( unsigned long Address ); int ParseMaps( FILE *fp ); unsigned long gpdDrvrGetErrLoc( void ) { register unsigned long __r; #ifdef USE_X86 __r = 0; #else asm ("move %0,$%1" : "=d" (__r) : "JK" (31)); #endif return __r; } unsigned long gpdDrvrGetErrContext( void ) { register unsigned long __r; #ifdef USE_X86 __r = 0; #else asm ("move %0,$%1" : "=d" (__r) : "JK" (29)); #endif return __r; } unsigned long kMaxStackCheck = 100; unsigned int gpdDrvrGetCallChain( unsigned int skip, unsigned int store, unsigned long *buf, unsigned long *stack ) { unsigned int result = 0; // register unsigned long __r; unsigned long stackCheck = 0; register unsigned long v ; // printf("|%s:%d| stack = 0x%x\n", __func__, __LINE__, (unsigned int)stack); #ifdef USE_X86 if (stack == NULL) return 0; #else if (stack == NULL) { // get our stack pointer asm ("move %0,$%1" : "=d" (__r) : "JK" (29)); stack = (unsigned long *) (__r & 0xfffffffc); } #endif // move up the stack and look for value. while ((stackCheck < kMaxStackCheck) && (result < store)) { if (!ISDATAADDR((unsigned long)stack)) break; v = *stack--; // printf("|%s:%d| stack = 0x%x ==> 0x%x\n", __func__, __LINE__, stack, v); if (ISCODEADDR(v)) // ISCODEADDR must be defined by Orion. It should validate that the memory is in the correct range. { if (skip) { // just skip this one skip--; } else { // store this one *buf++ = v; result++; } } stackCheck++; } return result; } #ifdef _MAKEFILE_INCLUDE_TSHELL_ char *find_function( unsigned long addr ) { int i; char *ptr; // char *fptr; volatile unsigned long diff, old_diff=0xFFFFFFFF; int found = 0; ptr = (char *)0; for (i=0; DMW_SymbolTbl[i].name; i++) { if (!(ISCODEADDR((unsigned long)DMW_SymbolTbl[i].value))) continue; diff = addr - ((unsigned long)DMW_SymbolTbl[i].value); if (old_diff > diff) { old_diff = diff; ptr = DMW_SymbolTbl[i].name; found = 1; // fptr = DMW_SymbolTbl[i].value; } } if ( found ) { if ( strcmp("_etext", ptr) == 0 ) { return (char *)0; } else return ptr; } else return (char *)0; } #endif void (*old_sigfunc[32+1])(int, int, struct sigcontext *sc); unsigned long IBuf[256]; void sig_handler( int signo, int arg2, struct sigcontext *sc ) { unsigned long pc; unsigned long sp; unsigned int i, j; unsigned long *ptr; if ( signo != SIGSEGV ) return; printf("!!! %s (%d) !!!\n", signo == SIGSEGV ? "Segmentation Fault" : "Unknown", signo ); #if 0 sigfillset( &sigset ); if ( sigprocmask( SIG_BLOCK, &sigset, &oldset ) < 0 ) { printf("sigprocmask(): line=%d\n", __LINE__); return; } #endif { #ifndef USE_CYGWIN #ifdef USE_X86 unsigned long long *t = (unsigned long long *)&sc->eip; #else unsigned long long *t = &sc->sc_pc; #endif ptr = (unsigned long *)t; #endif } ptr += 1; pc = *(ptr); #ifdef USE_X86 ptr = (unsigned long *)&sc->esp; #else ptr = (unsigned long *)&sc->sc_regs[29]; #endif ptr += 1; sp = *(ptr); // curpc = gpdDrvrGetErrLoc(); // cursp = gpdDrvrGetErrContext(); #if 1 printf(" PC = 0x%08lX\n", pc ); printf(" SP = 0x%08lX\n", sp ); #endif i = gpdDrvrGetCallChain( 0, 10, IBuf, (unsigned long *)sp ); #if 1 printf(" Call Chain = %d\n", i ); #ifdef _MAKEFILE_INCLUDE_TSHELL_ printf(" SP[%d] = 0x%08lX (%s)\n", -1, pc, find_function(pc) ); #else printf(" SP[%d] = 0x%08lX\n", -1, pc ); #endif for ( j=0; j == break; // // parse it. // // 1 ptr = strchr( tempMapBuf, '-' ); if ( !ptr ) break; *ptr = ' '; ptr = tempMapBuf; sscanf( ptr, "%lx", &StartAddress ); // 2 ptr = strchr( tempMapBuf, ' ' ); if ( !ptr ) break; ptr++; sscanf( ptr, "%lx", &EndAddress ); // 3 ptr += 9; flag = 0; if ( ptr[0] == 'r' ) flag |= 0x8; if ( ptr[1] == 'w' ) flag |= 0x4; if ( ptr[2] == 'x' ) flag |= 0x2; if ( ptr[3] == 'p' ) flag |= 0x1; if ( (flag & 0xE) == 0xA ) Type = SMMType_CODE; else if ( (flag & 0xE) == 0xC ) Type = SMMType_DATA; else if ( (flag & 0xE) == 0x0 ) Type = SMMType_UNUSED; else if ( (flag & 0xF) == 0xF ) Type = SMMType_STACK; else Type = SMMType_OTHER; // save it. g_SMMTbl[count].StartAddress = StartAddress; g_SMMTbl[count].EndAddress = EndAddress; g_SMMTbl[count].Type = Type; ptr = strchr( tempMapBuf, '/' ); if ( ptr ) strncpy( g_SMMTbl[count].name, ptr, 256 ); else { g_SMMTbl[count].name[0] = '\n'; g_SMMTbl[count].name[1] = '\0'; } count++; } ; g_SMMTblCount = count; return count; } int MakeMap(void) { FILE *fp; int ret = 0; #if DEBUG int i; int init=0; #endif fp = OpenMaps(); if ( !fp ) { printf("|%s| ERROR, LINE=%d\n", __func__, __LINE__); return -1; } ret = ParseMaps( fp ); if ( ret < 0 ) { printf("|%s| ERROR, LINE=%d\n", __func__, __LINE__); return -1; } #if DEBUG if ( init == 0 ) { for (i=0; i= g_SMMTbl[i].StartAddress && Address <= g_SMMTbl[i].EndAddress ) { found = 1; break; } } if ( found ) return g_SMMTbl[i].Type; else return SMMType_UNUSED; } char *FindLibrary( unsigned long Address ) { int i; int found = 0; for (i=0; i= g_SMMTbl[i].StartAddress && Address <= g_SMMTbl[i].EndAddress ) { found = 1; break; } } if ( found ) { if ( g_SMMTbl[i].name[0] != '\0' ) return g_SMMTbl[i].name; } return NULL; } int isStackAddress( unsigned long Address ) { SMMType type; extern unsigned int _init; extern unsigned int _etext; if (Address >= (unsigned int)&_init && Address <= (unsigned int)&_etext) return 1; type = FindMemory( Address ); if ( type == SMMType_STACK ) return 1; return 0; } int isCodeAddress( unsigned long Address ) { SMMType type; extern unsigned int _init; extern unsigned int _etext; if (Address >= (unsigned int)&_init && Address <= (unsigned int)&_etext) return 1; // // hwatk/050720 // OTHER´Â ¾û¶×ÇÑ °ø°£±îÁö Æ÷ÇԵǴ °æ¿ì°¡ ÀÖ¾î »°´Ù. // type = FindMemory( Address ); if ( type == SMMType_CODE /*|| type == SMMType_OTHER*/ ) return 1; return 0; } int isDataAddress( unsigned long Address ) { SMMType type; // extern unsigned int _init; // extern unsigned int _etext; type = FindMemory( Address ); if ( type == SMMType_DATA ) return 1; return 0; } void seg_dbg(void) { printf("Start debug function for segmentation fault.\n"); MakeMap(); RegisterSignalHandler(); } #endif