/*++ Copyright (c) 1998-2001 Klaus P. Gerlicher Module Name: main.c Abstract: loader/translator for pIce LINUX Environment: User mode only Author: Klaus P. Gerlicher Reactos Port by Eugene Ingerman Revision History: 04-Aug-1998: created 15-Nov-2000: general cleanup of source files Copyright notice: This file may be distributed under the terms of the GNU Public License. --*/ /////////////////////////////////////////////////////////////////////////////////// // includes #include "stdinc.h" #include /////////////////////////////////////////////////////////////////////////////////// // constant defines /////////////////////////////////////////////////////////////////////////////////// // global variables char SrcFileNames[2048][2048]; ULONG ulCurrentSrcFile = 0; HANDLE debugger_file; ULONG ulGlobalVerbose = 0; /////////////////////////////////////////////////////////////////////////////////// // process_stabs() // /////////////////////////////////////////////////////////////////////////////////// void process_stabs( char* pExeName, // name of exe HANDLE fileout, // symbol file handle PIMAGE_SECTION_HEADER section, //Elf32_Shdr* pSHdr, int sectionHeadersSize, //int nSHdrSize, void* p, // ptr to memory where whole exe was read PSTAB_ENTRY pStab, // ptr to stabs int nStabLen, // size of stabs char* pStr, // ptr to stabs strings int nStrLen, // sizeof stabs strings char* pGlobals, // ptr to global symbols int nGlobalLen, // sizeof of globals char* pGlobalsStr, // ptr to global strings int nGlobalStrLen) // size of global strings { unsigned i,strLen; int nOffset=0,nNextOffset=0; PSTAB_ENTRY pStabCopy = pStab; char* pName,szCurrentPath[2048]; PICE_SYMBOLFILE_HEADER SymbolFileHeader; LPSTR pSlash,pDot; char temp[2048]; char* pCopyExeName = temp; WCHAR tempstr[64]; DWORD wrote; //printf("LOADER: enter process_stabs()\n"); //get the name of the executable file memset((void*)&SymbolFileHeader,0,sizeof(SymbolFileHeader)); SymbolFileHeader.magic = PICE_MAGIC; strcpy(temp,pExeName); pSlash = strrchr(temp,'\\'); pDot = strchr(temp,'.'); if(pDot) { *pDot = 0; } if(pSlash) { pCopyExeName = pSlash+1; } strLen = MultiByteToWideChar(CP_ACP, NULL, pCopyExeName, -1, tempstr, 64 ); if( !strLen ) printf("Cannot convert string to multibyte: %s\n", pCopyExeName ); wcscpy(SymbolFileHeader.name,tempstr); for(i=0;i<(nStabLen/sizeof(STAB_ENTRY));i++) { pName = &pStr[pStabCopy->n_strx + nOffset]; #if 0 //printf("LOADER: \n%.8x %.2x %.2x %.4x %.8x %s\n", pStabCopy->n_strx, pStabCopy->n_type, pStabCopy->n_other, pStabCopy->n_desc, pStabCopy->n_value, pName ); #endif switch(pStabCopy->n_type) { case N_UNDF: nOffset += nNextOffset; nNextOffset = pStabCopy->n_value; //printf("LOADER: changing string offset %x %x\n",nOffset,nNextOffset); break; case N_SO: if((strLen = strlen(pName))) { if(pName[strLen-1]!='/') { if(strlen(szCurrentPath)) { //printf("LOADER: ###########################################################################\n"); strcat(szCurrentPath,pName); //printf("LOADER: changing source file %s\n",szCurrentPath); strcpy(SrcFileNames[ulCurrentSrcFile++],szCurrentPath); szCurrentPath[0]=0; } else { //printf("LOADER: ###########################################################################\n"); //printf("LOADER: changing source file %s\n",pName); strcpy(SrcFileNames[ulCurrentSrcFile++],pName); } } else strcpy(szCurrentPath,pName); } else { //printf("LOADER: END source file\n"); //printf("LOADER: ###########################################################################\n"); } break; /* case N_SLINE: //printf("LOADER: code source line number #%u for addr. %x\n",pStabCopy->n_desc,pStabCopy->n_value); break; case N_DSLINE: //printf("LOADER: data source line number #%u for addr. %x\n",pStabCopy->n_desc,pStabCopy->n_value); break; case N_BSLINE: //printf("LOADER: BSS source line number #%u for addr. %x\n",pStabCopy->n_desc,pStabCopy->n_value); break; case N_GSYM: //printf("LOADER: global symbol %s @ addr. %x (%x)\n",pName,pStabCopy->n_value,pStabCopy->n_desc); break; case N_BINCL: //printf("LOADER: include file %s\n",pName); break; case N_EINCL: break; case N_FUN: if(strlen(pName)) //printf("LOADER: function %s @ addr. %x (%x)\n",pName,pStabCopy->n_value,pStabCopy->n_desc); else //printf("LOADER: text segment %x (%x)\n",pName,pStabCopy->n_value,pStabCopy->n_desc); break; case N_PSYM: //printf("LOADER: parameter %s @ [EBP%+d] (%x)\n",pName,pStabCopy->n_value,pStabCopy->n_desc); break; case N_RSYM: //printf("LOADER: register variable %s @ reg. %x (%x)\n",pName,pStabCopy->n_value,pStabCopy->n_desc); break; case N_LBRAC: //printf("LOADER: lexical block %s @ reg. %x (%x)\n",pName,pStabCopy->n_value,pStabCopy->n_desc); break; case N_RBRAC: //printf("LOADER: END of lexical block %s @ reg. %x (%x)\n",pName,pStabCopy->n_value,pStabCopy->n_desc); break; case N_STSYM: //printf("LOADER: static variable %s @ %x (%x)\n",pName,pStabCopy->n_value,pStabCopy->n_desc); break; case N_LCSYM: //printf("LOADER: BSS variable %s @ %x (%x)\n",pName,pStabCopy->n_value,pStabCopy->n_desc); break; case N_LSYM: if(pStabCopy->n_value) { //printf("LOADER: stack variable %s @ [EBP%+d] (%x)\n",pName,pStabCopy->n_value,pStabCopy->n_desc); } else { //printf("LOADER: global variable %s \n",pName); } break; */ } pStabCopy++; } //printf("LOADER: SymbolFileHeader.ulSizeOfHeader= %x (%x)\n",nSHdrSize,(LPSTR)pSHdr-(LPSTR)p); //printf("LOADER: SymbolFileHeader.ulSizeOfGlobals = %x (%x)\n",nGlobalLen,(LPSTR)pGlobals-(LPSTR)p); //printf("LOADER: SymbolFileHeader.ulSizeOfGlobalsStrings = %x (%x)\n",nGlobalStrLen,(LPSTR)pGlobalsStr-(LPSTR)p); //printf("LOADER: SymbolFileHeader.ulSizeOfStabs = %x (%x)\n",nStabLen,(LPSTR)pStab-(LPSTR)p); //printf("LOADER: SymbolFileHeader.ulSizeOfStabsStrings = %x (%x)\n",nStrLen,(LPSTR)pStr-(LPSTR)p); SymbolFileHeader.ulOffsetToHeaders = sizeof(PICE_SYMBOLFILE_HEADER); SymbolFileHeader.ulSizeOfHeader = sectionHeadersSize; SymbolFileHeader.ulOffsetToGlobals = sizeof(PICE_SYMBOLFILE_HEADER)+sectionHeadersSize; SymbolFileHeader.ulSizeOfGlobals = nGlobalLen; SymbolFileHeader.ulOffsetToGlobalsStrings = sizeof(PICE_SYMBOLFILE_HEADER)+sectionHeadersSize+nGlobalLen; SymbolFileHeader.ulSizeOfGlobalsStrings = nGlobalStrLen; SymbolFileHeader.ulOffsetToStabs = sizeof(PICE_SYMBOLFILE_HEADER)+sectionHeadersSize+nGlobalLen+nGlobalStrLen; SymbolFileHeader.ulSizeOfStabs = nStabLen; SymbolFileHeader.ulOffsetToStabsStrings = sizeof(PICE_SYMBOLFILE_HEADER)+sectionHeadersSize+nGlobalLen+nGlobalStrLen+nStabLen; SymbolFileHeader.ulSizeOfStabsStrings = nStrLen; SymbolFileHeader.ulOffsetToSrcFiles = sizeof(PICE_SYMBOLFILE_HEADER)+sectionHeadersSize+nGlobalLen+nGlobalStrLen+nStabLen+nStrLen; SymbolFileHeader.ulNumberOfSrcFiles = ulCurrentSrcFile; printf("sectionHeaderSize: %ld, nGlobalLen: %ld, nGlobalStrLen: %ld, nStabLen: %ld, " "nStrLen: %ld, ulCurrentSrcFile: %ld, ulOffsetToStabs: %ld\n", sectionHeadersSize, nGlobalLen, nGlobalStrLen, nStabLen, nStrLen, ulCurrentSrcFile, SymbolFileHeader.ulOffsetToStabs); WriteFile(fileout,&SymbolFileHeader,sizeof(PICE_SYMBOLFILE_HEADER),&wrote, NULL); WriteFile(fileout,section,sectionHeadersSize,&wrote, NULL); WriteFile(fileout,pGlobals,nGlobalLen,&wrote, NULL); WriteFile(fileout,pGlobalsStr,nGlobalStrLen,&wrote, NULL); WriteFile(fileout,pStab,nStabLen,&wrote, NULL); WriteFile(fileout,pStr,nStrLen,&wrote, NULL); for(i=0;iName,".stab") == 0) { *ppStab = (PSTAB_ENTRY)((int)p + section->PointerToRawData); *pLen = section->SizeOfRawData; printf("LOADER: .stab @ %x (offset %x) len = %x\n",*ppStab,section->PointerToRawData,section->SizeOfRawData); } else if(strncmp(section->Name,".stabstr",strlen(".stabstr")) == 0) { *ppStr = (char*)((int)p + section->PointerToRawData); *pnStabStrLen = section->SizeOfRawData; printf("LOADER: .stabstr @ %x (offset %x) len = %x\n",*ppStab,section->PointerToRawData,section->SizeOfRawData); } } //printf("LOADER: leave find_stab_sections()\n"); } /////////////////////////////////////////////////////////////////////////////////// // process_pe() // /////////////////////////////////////////////////////////////////////////////////// int process_pe(char* filename,int file,void* p,int len) { PIMAGE_DOS_HEADER pDosHeader; PIMAGE_NT_HEADERS pNTHeaders; char* pStr; PSTAB_ENTRY pStab; DWORD nStabLen,nSym; char* pStrTab; char* pSymTab; char szSymName[2048]; HANDLE fileout; int nSymStrLen,nStabStrLen; int iRetVal = 0; pDosHeader = (PIMAGE_DOS_HEADER)p; pNTHeaders = (PIMAGE_NT_HEADERS)((DWORD)p + pDosHeader->e_lfanew); if ((pDosHeader->e_magic == IMAGE_DOS_SIGNATURE) && (pDosHeader->e_lfanew != 0L) && (pNTHeaders->Signature == IMAGE_NT_SIGNATURE)) { if( pNTHeaders->FileHeader.PointerToSymbolTable ){ pSymTab = (char*)((DWORD)p + pNTHeaders->FileHeader.PointerToSymbolTable); nSym = pNTHeaders->FileHeader.NumberOfSymbols; //string table follows immediately after symbol table. first 4 bytes give the length of the table //references to string table include the first 4 bytes. pStrTab = (char*)((PIMAGE_SYMBOL)pSymTab + nSym); nSymStrLen = *((DWORD*)pStrTab); find_stab_sections(p,IMAGE_FIRST_SECTION(pNTHeaders),pNTHeaders->FileHeader.NumberOfSections, &pStab,&nStabLen,&pStr,&nStabStrLen); if(pStab && nStabLen && pStr && nStabStrLen) { LPSTR pDot; strcpy(szSymName,filename); //printf("LOADER: file name = %s\n",szSymName); if((pDot = strchr(szSymName,'.'))) { *pDot = 0; strcat(pDot,".dbg"); } else { strcat(szSymName,".dbg"); } //printf("LOADER: symbol file name = %s\n",szSymName); printf("LOADER: creating symbol file %s for %s\n",szSymName,filename); fileout = CreateFile(szSymName, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0); if(fileout != INVALID_HANDLE_VALUE) { printf("NumberOfSections: %d, size: %d\n", pNTHeaders->FileHeader.NumberOfSections,sizeof(IMAGE_SECTION_HEADER)); process_stabs(szSymName, fileout, IMAGE_FIRST_SECTION(pNTHeaders), pNTHeaders->FileHeader.NumberOfSections*sizeof(IMAGE_SECTION_HEADER), p, pStab, nStabLen, pStr, nStabStrLen, (char*)pSymTab, nSym*sizeof(IMAGE_SYMBOL), pStrTab, nSymStrLen); CloseHandle(fileout); } else { printf("LOADER: creation of symbol file %s failed\n",szSymName); iRetVal = 2; } } else { printf("LOADER: file %s has no data inside symbol tables\n",filename); if( ulGlobalVerbose ) { if( !pStab || !nStabLen ) printf("LOADER: - symbol table is empty or not present\n"); if( !pStr || !nStabStrLen ) printf("LOADER: - string table is empty or not present\n"); } iRetVal = 2; } } else{ printf("LOADER: file %s does not have a symbol table\n",filename); iRetVal = 2; } } else { printf("LOADER: file %s is not an ELF binary\n",filename); iRetVal = 1; } //printf("LOADER: leave process_pe()\n"); return iRetVal; } /////////////////////////////////////////////////////////////////////////////////// // process_file() // /////////////////////////////////////////////////////////////////////////////////// int process_file(char* filename) { int file; void* p; off_t len; int iRetVal=0; //printf("LOADER: enter process_file()\n"); file = _open(filename,O_RDONLY|_O_BINARY); if(file>0) { //printf("LOADER: opened %s as FD %x\n",filename,file); len = _lseek(file,0,SEEK_END); printf("LOADER: file %s is %u bytes\n",filename,(int)len); _lseek(file,0,SEEK_SET); p = malloc(len+16); if(p) { long count; //printf("LOADER: malloc'd @ %x\n",p); memset(p,0,len+16); if(len == (count = _read(file,p,len))) { //printf("LOADER: trying ELF format\n"); iRetVal = process_pe(filename,file,p,len); } } _close(file); } else { printf("LOADER: file %s could not be opened\n",filename); iRetVal = 1; } //printf("LOADER: leave process_file()\n"); return iRetVal; } /////////////////////////////////////////////////////////////////////////////////// // open_debugger() // /////////////////////////////////////////////////////////////////////////////////// HANDLE open_debugger(void) { debugger_file = CreateFile("\\Device\\Pice",GENERIC_READ,0,NULL,OPEN_EXISTING,NULL,NULL); if(debugger_file == INVALID_HANDLE_VALUE) { printf("LOADER: debugger is not loaded. Last Error: %ld\n", GetLastError()); } return debugger_file; } /////////////////////////////////////////////////////////////////////////////////// // close_debugger() // /////////////////////////////////////////////////////////////////////////////////// void close_debugger(void) { if( !CloseHandle(debugger_file) ){ printf("Error closing debugger handle: %ld\n", GetLastError()); } } int ioctl( HANDLE device, DWORD ioctrlcode, PDEBUGGER_STATUS_BLOCK psb) { DEBUGGER_STATUS_BLOCK tsb; DWORD bytesreturned; if( !DeviceIoControl( device, ioctrlcode, psb, sizeof(DEBUGGER_STATUS_BLOCK), &tsb, sizeof(DEBUGGER_STATUS_BLOCK),&bytesreturned, NULL) ){ printf("Error in DeviceIoControl: %ld\n", GetLastError()); return -EINVAL; } else{ memcpy( psb, &tsb, sizeof(DEBUGGER_STATUS_BLOCK) ); } return 0; } /////////////////////////////////////////////////////////////////////////////////// // banner() // /////////////////////////////////////////////////////////////////////////////////// void banner(void) { printf("#########################################################\n"); printf("#### Symbols LOADER/TRANSLATOR for PICE ####\n"); printf("#########################################################\n"); } #define ACTION_NONE 0 #define ACTION_LOAD 1 #define ACTION_UNLOAD 2 #define ACTION_TRANS 3 #define ACTION_RELOAD 4 #define ACTION_INSTALL 5 #define ACTION_UNINSTALL 6 #define ACTION_STATUS 7 #define ACTION_BREAK 8 #define ACTION_TERMINAL 9 /////////////////////////////////////////////////////////////////////////////////// // change_symbols() // /////////////////////////////////////////////////////////////////////////////////// void change_symbols(int action,char* pfilename) { int iRetVal = 0; DEBUGGER_STATUS_BLOCK sb; strcpy(sb.filename, pfilename); switch(action) { case ACTION_LOAD: printf("LOADER: loading symbols from %s\n",pfilename); if(open_debugger() != INVALID_HANDLE_VALUE) { iRetVal = ioctl(debugger_file,PICE_IOCTL_LOAD,&sb); close_debugger(); } break; case ACTION_UNLOAD: printf("LOADER: unloading symbols from %s\n",pfilename); if(open_debugger() != INVALID_HANDLE_VALUE) { iRetVal = ioctl(debugger_file,PICE_IOCTL_UNLOAD,&sb); close_debugger(); } break; case ACTION_RELOAD: printf("LOADER: reloading all symbols\n"); if(open_debugger() != INVALID_HANDLE_VALUE) { ioctl(debugger_file,PICE_IOCTL_RELOAD,NULL); close_debugger(); printf("LOADER: reloading DONE!\n"); } break; default : printf("LOADER: an internal error has occurred at change_symbols\n"); } switch( iRetVal ) { case -EINVAL : printf("LOADER: debugger return value = -EINVAL, operation has failed\n"); break; case 0 : // success - silently proceed break; default : printf("LOADER: debugger return value = %i, operation possibly failed\n",iRetVal); } } // Dynamic install to be added later #if 0 /////////////////////////////////////////////////////////////////////////////////// // tryinstall() // /////////////////////////////////////////////////////////////////////////////////// int tryinstall(void) { char *argv[]={"/sbin/insmod","pice.o",NULL}; int err = 0; int pid,status; banner(); printf("LOADER: trying to install debugger...\n"); if( open_debugger() != INVALID_HANDLE_VALUE ) { printf("LOADER: debugger already installed...\n"); close_debugger(); return 0; } // create a separate thread pid = fork(); switch(pid) { case -1: // error when forking, i.e. out E_NOMEM err = errno; printf("LOADER: fork failed for execution of '%s' (errno = %u).\n",argv[0],err); break; case 0: // child process handler execve(argv[0],argv,NULL); // returns only on error, with return value -1, errno is set printf("LOADER: couldn't execute '%s' (errno = %u)\n",argv[0],errno); exit(255); break; default: // parent process handler printf("LOADER: waiting for debugger to load...\n"); pid = waitpid(pid, &status, 0); // suspend until child is done if( (pid>0) && WIFEXITED(status) && (WEXITSTATUS(status) == 0) ) printf("LOADER: debugger loaded!\n"); else if( pid<=0 ) { printf("LOADER: Error on loading debugger! (waitpid() = %i)\n",pid); err = -1; } else if( !WIFEXITED(status) ) { printf("LOADER: Error on loading debugger! (ifexited = %i)\n",WIFEXITED(status)); err = -1; } else { printf("LOADER: Error on loading debugger! (exitstatus = %u)\n",WEXITSTATUS(status)); err = WEXITSTATUS(status); } break; } return err; } /////////////////////////////////////////////////////////////////////////////////// // tryuninstall() // /////////////////////////////////////////////////////////////////////////////////// int tryuninstall(void) { char *argv[]={"/sbin/rmmod","pice",NULL}; int err = 0; int pid,status; banner(); printf("LOADER: trying to remove debugger...\n"); // check for loaded debugger if(open_debugger() == INVALID_HANDLE_VALUE) { return -1; } // don't to close, else we'll have a reference count != 0 close_debugger(); // create a separate thread pid = fork(); switch(pid) { case -1: // error when forking, i.e. out E_NOMEM err = errno; printf("LOADER: fork failed for execution of '%s' (errno=%u).\n",argv[0],err); break; case 0: // child process handler execve(argv[0],argv,NULL); // returns only on error, with return value -1, errno is set printf("LOADER: couldn't execute '%s' (errno = %u)\n",argv[0],errno); exit(255); break; default: // parent process handler printf("LOADER: waiting for debugger to unload...\n"); pid = waitpid(pid, &status, 0); // suspend until child is done if( (pid>0) && WIFEXITED(status) && (WEXITSTATUS(status) == 0) ) printf("LOADER: debugger removed!\n"); else if( pid<=0 ) { printf("LOADER: Error on removing debugger! (waitpid() = %i)\n",pid); err = -1; } else if( !WIFEXITED(status) ) { printf("LOADER: Error on removing debugger! (ifexited = %i)\n",WIFEXITED(status)); err = -1; } else { printf("LOADER: Error on removing debugger! (exitstatus = %u)\n",WEXITSTATUS(status)); err = WEXITSTATUS(status); } break; } return err; } #endif /////////////////////////////////////////////////////////////////////////////////// // showstatus() // /////////////////////////////////////////////////////////////////////////////////// void showstatus(void) { DEBUGGER_STATUS_BLOCK sb; int iRetVal; if(open_debugger() != INVALID_HANDLE_VALUE) { iRetVal = ioctl(debugger_file,PICE_IOCTL_STATUS,&sb); //printf("LOADER: Test = %X\n",sb.Test); close_debugger(); } } /////////////////////////////////////////////////////////////////////////////////// // dobreak() // /////////////////////////////////////////////////////////////////////////////////// void dobreak(void) { int iRetVal; if(open_debugger() != INVALID_HANDLE_VALUE) { iRetVal = ioctl(debugger_file,PICE_IOCTL_BREAK,NULL); close_debugger(); } } /////////////////////////////////////////////////////////////////////////////////// // doterminal() // /////////////////////////////////////////////////////////////////////////////////// #if 0 void doterminal(void) { if(SetupSerial(2,B115200)) { DebuggerShell(); CloseSerial(); } } #endif /////////////////////////////////////////////////////////////////////////////////// // process_switches() // // returns !=0 in case of a commandline error // /////////////////////////////////////////////////////////////////////////////////// int process_switches(int argc,char* argv[]) { int i; char* parg,*pfilename = NULL; int action = ACTION_NONE; int error = 0; // parse commandline arguments for(i=1;i ulGlobalVerbose ) ulGlobalVerbose++; } else if(strcmp(parg,"install")==0 || strcmp(parg,"i")==0) { new_action = ACTION_INSTALL; } else if(strcmp(parg,"uninstall")==0 || strcmp(parg,"x")==0) { new_action = ACTION_UNINSTALL; } else if(strcmp(parg,"status")==0 || strcmp(parg,"s")==0) { new_action = ACTION_STATUS; } else if(strcmp(parg,"break")==0 || strcmp(parg,"b")==0) { new_action = ACTION_BREAK; } else if(strcmp(parg,"serial")==0 || strcmp(parg,"ser")==0) { new_action = ACTION_TERMINAL; } else { printf("LOADER: error: unknown switch %s", argv[i]); error = 1; } if( new_action != ACTION_NONE ) { if( action == ACTION_NONE ) action = new_action; else if( action == new_action ) { // identical, just ignore } else { printf("LOADER: error: conflicting switch %s", argv[i]); error = 1; } } } else { if( pfilename ) { printf("LOADER: error: additional filename %s", parg); error = 1; } pfilename = parg; } } // check number of required parameters switch( action ) { case ACTION_TRANS : case ACTION_LOAD : case ACTION_UNLOAD : if( !pfilename ) { printf("LOADER: error: missing filename\n"); error = 1; } break; case ACTION_RELOAD : /* filename parameter is optional */ break; #if 0 case ACTION_UNINSTALL: close_debugger(); tryuninstall(); break; case ACTION_INSTALL: tryinstall(); break; #endif case ACTION_STATUS: showstatus(); break; case ACTION_BREAK: dobreak(); break; #if 0 case ACTION_TERMINAL: doterminal(); break; #endif case ACTION_NONE : printf("LOADER: no action specified specifed on commandline\n"); error = 1; break; default : printf("LOADER: an internal error has occurred at commandline parsing\n"); error = 1; } if( !error ) // commandline was fine, now start processing { switch( action ) { case ACTION_TRANS : printf("LOADER: trying to translate file %s...\n",pfilename); if( process_file(pfilename)==0 ) printf("LOADER: file %s has been translated\n",pfilename); else printf("LOADER: error while translating file %s\n",pfilename); break; case ACTION_LOAD : case ACTION_UNLOAD : case ACTION_RELOAD : change_symbols(action,pfilename); break; } } return error; } /////////////////////////////////////////////////////////////////////////////////// // showhelp() // /////////////////////////////////////////////////////////////////////////////////// void showhelp(void) { banner(); printf("LOADER: Syntax:\n"); printf("LOADER: loader [switches] [executable/object file path]\n"); printf("LOADER: Switches:\n"); printf("LOADER: -trans (-t): translate from exe to sym\n"); printf("LOADER: -load (-l): load symbols\n"); printf("LOADER: -unload (-u): unload symbols\n"); printf("LOADER: -reload (-r): reload some/all symbols\n"); printf("LOADER: -verbose (-v): be a bit more verbose\n"); printf("LOADER: -install (-i): install pICE debugger\n"); printf("LOADER: -uninstall (-x): uninstall pICE debugger\n"); printf("LOADER: -break (-b): break into debugger\n"); printf("LOADER: -serial (-ser): start serial line terminal\n"); } /////////////////////////////////////////////////////////////////////////////////// // showpermission() // /////////////////////////////////////////////////////////////////////////////////// void showpermission(void) { banner(); printf("LOADER: You must be superuser!\n"); } /////////////////////////////////////////////////////////////////////////////////// // main() // /////////////////////////////////////////////////////////////////////////////////// int main(int argc,char* argv[]) { if(argc==1 || argc>3) { showhelp(); return 1; } return process_switches(argc,argv); }