:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / apps / utils / pice / loader / main.c
1 /*++
2
3 Copyright (c) 1998-2001 Klaus P. Gerlicher
4
5 Module Name:
6
7     main.c
8
9 Abstract:
10
11     loader/translator for pIce LINUX
12
13 Environment:
14
15     User mode only
16
17 Author:
18
19     Klaus P. Gerlicher
20         Reactos Port by Eugene Ingerman
21
22 Revision History:
23
24     04-Aug-1998:        created
25     15-Nov-2000:    general cleanup of source files
26
27 Copyright notice:
28
29   This file may be distributed under the terms of the GNU Public License.
30
31 --*/
32
33 ///////////////////////////////////////////////////////////////////////////////////
34 // includes
35 #include "stdinc.h"
36 #include <wchar.h>
37
38 ///////////////////////////////////////////////////////////////////////////////////
39 // constant defines
40
41
42 ///////////////////////////////////////////////////////////////////////////////////
43 // global variables
44 char SrcFileNames[2048][2048];
45 ULONG ulCurrentSrcFile = 0;
46
47 HANDLE debugger_file;
48
49 ULONG ulGlobalVerbose = 0;
50
51
52 ///////////////////////////////////////////////////////////////////////////////////
53 // process_stabs()
54 //
55 ///////////////////////////////////////////////////////////////////////////////////
56 void process_stabs(
57         char* pExeName, // name of exe
58         HANDLE fileout, // symbol file handle
59         PIMAGE_SECTION_HEADER section, //Elf32_Shdr* pSHdr,
60         int sectionHeadersSize, //int   nSHdrSize,
61         void* p,                // ptr to memory where whole exe was read
62         PSTAB_ENTRY pStab,      // ptr to stabs
63         int nStabLen,           // size of stabs
64         char* pStr,                     // ptr to stabs strings
65         int nStrLen,            // sizeof stabs strings
66         char* pGlobals,         // ptr to global symbols
67         int nGlobalLen,         // sizeof of globals
68         char* pGlobalsStr,      // ptr to global strings
69         int nGlobalStrLen)      // size of global strings
70 {
71     unsigned i,strLen;
72     int nOffset=0,nNextOffset=0;
73     PSTAB_ENTRY pStabCopy = pStab;
74     char* pName,szCurrentPath[2048];
75         PICE_SYMBOLFILE_HEADER SymbolFileHeader;
76         LPSTR pSlash,pDot;
77         char temp[2048];
78         char* pCopyExeName = temp;
79         WCHAR tempstr[64];
80         DWORD wrote;
81
82     //printf("LOADER: enter process_stabs()\n");
83
84         //get the name of the executable file
85     memset((void*)&SymbolFileHeader,0,sizeof(SymbolFileHeader));
86         SymbolFileHeader.magic = PICE_MAGIC;
87         strcpy(temp,pExeName);
88         pSlash = strrchr(temp,'\\');
89         pDot = strchr(temp,'.');
90         if(pDot)
91         {
92                 *pDot = 0;
93         }
94         if(pSlash)
95         {
96                 pCopyExeName = pSlash+1;
97         }
98         strLen = MultiByteToWideChar(CP_ACP, NULL, pCopyExeName, -1, tempstr, 64 );
99         if( !strLen )
100                 printf("Cannot convert string to multibyte: %s\n", pCopyExeName );
101         wcscpy(SymbolFileHeader.name,tempstr);
102
103     for(i=0;i<(nStabLen/sizeof(STAB_ENTRY));i++)
104     {
105         pName = &pStr[pStabCopy->n_strx + nOffset];
106
107 #if 0
108         //printf("LOADER: \n%.8x %.2x %.2x %.4x %.8x %s\n",
109                 pStabCopy->n_strx,
110                 pStabCopy->n_type,
111                 pStabCopy->n_other,
112                 pStabCopy->n_desc,
113                 pStabCopy->n_value,
114                 pName
115                 );
116 #endif
117         switch(pStabCopy->n_type)
118         {
119             case N_UNDF:
120                 nOffset += nNextOffset;
121                 nNextOffset = pStabCopy->n_value;
122                 //printf("LOADER: changing string offset %x %x\n",nOffset,nNextOffset);
123                 break;
124             case N_SO:
125                 if((strLen = strlen(pName)))
126                 {
127                     if(pName[strLen-1]!='/')
128                     {
129                         if(strlen(szCurrentPath))
130                         {
131                             //printf("LOADER: ###########################################################################\n");
132                             strcat(szCurrentPath,pName);
133                             //printf("LOADER: changing source file %s\n",szCurrentPath);
134                             strcpy(SrcFileNames[ulCurrentSrcFile++],szCurrentPath);
135                             szCurrentPath[0]=0;
136                         }
137                         else
138                         {
139                             //printf("LOADER: ###########################################################################\n");
140                             //printf("LOADER: changing source file %s\n",pName);
141                             strcpy(SrcFileNames[ulCurrentSrcFile++],pName);
142                         }
143                     }
144                     else
145                         strcpy(szCurrentPath,pName);
146                 }
147                 else
148                 {
149                     //printf("LOADER: END source file\n");
150                     //printf("LOADER: ###########################################################################\n");
151                 }
152                 break;
153 /*            case N_SLINE:
154                 //printf("LOADER: code source line number #%u for addr. %x\n",pStabCopy->n_desc,pStabCopy->n_value);
155                 break;
156             case N_DSLINE:
157                 //printf("LOADER: data source line number #%u for addr. %x\n",pStabCopy->n_desc,pStabCopy->n_value);
158                 break;
159             case N_BSLINE:
160                 //printf("LOADER: BSS source line number #%u for addr. %x\n",pStabCopy->n_desc,pStabCopy->n_value);
161                 break;
162             case N_GSYM:
163                 //printf("LOADER: global symbol %s @ addr. %x (%x)\n",pName,pStabCopy->n_value,pStabCopy->n_desc);
164                 break;
165             case N_BINCL:
166                 //printf("LOADER: include file %s\n",pName);
167                 break;
168             case N_EINCL:
169                 break;
170             case N_FUN:
171                 if(strlen(pName))
172                     //printf("LOADER: function %s @ addr. %x (%x)\n",pName,pStabCopy->n_value,pStabCopy->n_desc);
173                 else
174                     //printf("LOADER: text segment %x (%x)\n",pName,pStabCopy->n_value,pStabCopy->n_desc);
175                 break;
176             case N_PSYM:
177                 //printf("LOADER: parameter %s @ [EBP%+d] (%x)\n",pName,pStabCopy->n_value,pStabCopy->n_desc);
178                 break;
179             case N_RSYM:
180                 //printf("LOADER: register variable %s @ reg. %x (%x)\n",pName,pStabCopy->n_value,pStabCopy->n_desc);
181                 break;
182             case N_LBRAC:
183                 //printf("LOADER: lexical block %s @ reg. %x (%x)\n",pName,pStabCopy->n_value,pStabCopy->n_desc);
184                 break;
185             case N_RBRAC:
186                 //printf("LOADER: END of lexical block %s @ reg. %x (%x)\n",pName,pStabCopy->n_value,pStabCopy->n_desc);
187                 break;
188             case N_STSYM:
189                 //printf("LOADER: static variable %s @ %x (%x)\n",pName,pStabCopy->n_value,pStabCopy->n_desc);
190                 break;
191             case N_LCSYM:
192                 //printf("LOADER: BSS variable %s @ %x (%x)\n",pName,pStabCopy->n_value,pStabCopy->n_desc);
193                 break;
194             case N_LSYM:
195                 if(pStabCopy->n_value)
196                 {
197                     //printf("LOADER: stack variable %s @ [EBP%+d] (%x)\n",pName,pStabCopy->n_value,pStabCopy->n_desc);
198                 }
199                 else
200                 {
201                     //printf("LOADER: global variable %s \n",pName);
202                 }
203                 break;
204 */
205         }
206
207         pStabCopy++;
208     }
209
210         //printf("LOADER: SymbolFileHeader.ulSizeOfHeader= %x (%x)\n",nSHdrSize,(LPSTR)pSHdr-(LPSTR)p);
211         //printf("LOADER: SymbolFileHeader.ulSizeOfGlobals = %x (%x)\n",nGlobalLen,(LPSTR)pGlobals-(LPSTR)p);
212         //printf("LOADER: SymbolFileHeader.ulSizeOfGlobalsStrings = %x (%x)\n",nGlobalStrLen,(LPSTR)pGlobalsStr-(LPSTR)p);
213         //printf("LOADER: SymbolFileHeader.ulSizeOfStabs = %x (%x)\n",nStabLen,(LPSTR)pStab-(LPSTR)p);
214         //printf("LOADER: SymbolFileHeader.ulSizeOfStabsStrings = %x (%x)\n",nStrLen,(LPSTR)pStr-(LPSTR)p);
215
216         SymbolFileHeader.ulOffsetToHeaders = sizeof(PICE_SYMBOLFILE_HEADER);
217         SymbolFileHeader.ulSizeOfHeader = sectionHeadersSize;
218         SymbolFileHeader.ulOffsetToGlobals = sizeof(PICE_SYMBOLFILE_HEADER)+sectionHeadersSize;
219         SymbolFileHeader.ulSizeOfGlobals = nGlobalLen;
220         SymbolFileHeader.ulOffsetToGlobalsStrings = sizeof(PICE_SYMBOLFILE_HEADER)+sectionHeadersSize+nGlobalLen;
221         SymbolFileHeader.ulSizeOfGlobalsStrings = nGlobalStrLen;
222         SymbolFileHeader.ulOffsetToStabs = sizeof(PICE_SYMBOLFILE_HEADER)+sectionHeadersSize+nGlobalLen+nGlobalStrLen;
223         SymbolFileHeader.ulSizeOfStabs = nStabLen;
224         SymbolFileHeader.ulOffsetToStabsStrings = sizeof(PICE_SYMBOLFILE_HEADER)+sectionHeadersSize+nGlobalLen+nGlobalStrLen+nStabLen;
225         SymbolFileHeader.ulSizeOfStabsStrings = nStrLen;
226     SymbolFileHeader.ulOffsetToSrcFiles = sizeof(PICE_SYMBOLFILE_HEADER)+sectionHeadersSize+nGlobalLen+nGlobalStrLen+nStabLen+nStrLen;
227     SymbolFileHeader.ulNumberOfSrcFiles = ulCurrentSrcFile;
228
229         printf("sectionHeaderSize: %ld, nGlobalLen: %ld, nGlobalStrLen: %ld, nStabLen: %ld, "
230                         "nStrLen: %ld, ulCurrentSrcFile: %ld, ulOffsetToStabs: %ld\n",
231                         sectionHeadersSize, nGlobalLen, nGlobalStrLen,
232                         nStabLen, nStrLen, ulCurrentSrcFile, SymbolFileHeader.ulOffsetToStabs);
233
234         WriteFile(fileout,&SymbolFileHeader,sizeof(PICE_SYMBOLFILE_HEADER),&wrote, NULL);
235         WriteFile(fileout,section,sectionHeadersSize,&wrote, NULL);
236         WriteFile(fileout,pGlobals,nGlobalLen,&wrote, NULL);
237         WriteFile(fileout,pGlobalsStr,nGlobalStrLen,&wrote, NULL);
238         WriteFile(fileout,pStab,nStabLen,&wrote, NULL);
239         WriteFile(fileout,pStr,nStrLen,&wrote, NULL);
240
241     for(i=0;i<ulCurrentSrcFile;i++)
242     {
243         HANDLE file;
244         int len;
245         PVOID pFile;
246         PICE_SYMBOLFILE_SOURCE pss;
247
248                 file = CreateFile(SrcFileNames[i],GENERIC_READ , 0, NULL, OPEN_EXISTING, 0, 0);
249                 //printf("Trying To Open: %s, result: %x\n", SrcFileNames[i], file );
250
251
252                 if( file == INVALID_HANDLE_VALUE ){
253                         //let's try win format drive:/file
254                         char srctmp[2048];
255                         strcpy(srctmp, SrcFileNames[i] );
256                         if(strncmp(srctmp,"//",2)==0){
257                                 *(srctmp) = *(srctmp+2);
258                                 *(srctmp+1) = ':';
259                                 *(srctmp+2) = '/';
260                                 file = CreateFile(srctmp,GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0);
261                                 //printf("Trying To Open: %s, handle: %x\n", srctmp, file );
262                                 if( file == INVALID_HANDLE_VALUE )
263                                         printf("Can't open file: %s\n", srctmp );
264                         }
265                 }
266         if(file != INVALID_HANDLE_VALUE)
267         {
268             //printf("LOADER: [%u] opened %s as FD %x\n",i,SrcFileNames[i],file);
269
270             len = SetFilePointer(file,0,NULL,FILE_END);
271             //printf("LOADER: length = %d\n",(int)len);
272
273             SetFilePointer(file,0,NULL,FILE_BEGIN);
274
275             strcpy(pss.filename,SrcFileNames[i]);
276             pss.ulOffsetToNext = len+sizeof(PICE_SYMBOLFILE_SOURCE);
277
278             pFile = malloc(len+1);
279             //printf("LOADER: memory for file @ %x\n",pFile);
280             if(pFile)
281             {
282                 //printf("LOADER: reading file...\n");
283                 ReadFile(file,pFile,len+1,&wrote,NULL);
284                                 //printf("read: %d, error: %d\n", wrote, GetLastError());
285                 WriteFile(fileout,&pss,sizeof(PICE_SYMBOLFILE_SOURCE),&wrote, NULL);
286                 WriteFile(fileout,pFile,len,&wrote, NULL);
287                 //printf("LOADER: writing file...%d\n%s\n",wrote,pFile );
288                 free(pFile);
289             }
290
291             CloseHandle(file);
292         }
293
294     }
295
296     //printf("LOADER: leave process_stabs()\n");
297 }
298
299 ///////////////////////////////////////////////////////////////////////////////////
300 // find_stab_sections()
301 //
302 ///////////////////////////////////////////////////////////////////////////////////
303 void find_stab_sections(void* p,PIMAGE_SECTION_HEADER section, unsigned cSections,
304                                                           PSTAB_ENTRY* ppStab,int* pLen,char** ppStr,int* pnStabStrLen)
305 {
306         unsigned i;
307     //printf("LOADER: enter find_stab_sections()\n");
308     *ppStab = 0;
309     *ppStr = 0;
310
311         for ( i=1; i <= cSections; i++, section++ )
312     {
313
314                 if(strcmp(section->Name,".stab") == 0)
315         {
316             *ppStab = (PSTAB_ENTRY)((int)p + section->PointerToRawData);
317             *pLen = section->SizeOfRawData;
318             printf("LOADER: .stab @ %x (offset %x) len = %x\n",*ppStab,section->PointerToRawData,section->SizeOfRawData);
319         }
320         else if(strncmp(section->Name,".stabstr",strlen(".stabstr")) == 0)
321         {
322             *ppStr = (char*)((int)p + section->PointerToRawData);
323                         *pnStabStrLen = section->SizeOfRawData;
324             printf("LOADER: .stabstr @ %x (offset %x) len = %x\n",*ppStab,section->PointerToRawData,section->SizeOfRawData);
325         }
326     }
327
328     //printf("LOADER: leave find_stab_sections()\n");
329 }
330
331 ///////////////////////////////////////////////////////////////////////////////////
332 // process_pe()
333 //
334 ///////////////////////////////////////////////////////////////////////////////////
335 int process_pe(char* filename,int file,void* p,int len)
336 {
337
338         PIMAGE_DOS_HEADER pDosHeader;
339         PIMAGE_NT_HEADERS pNTHeaders;
340
341         char* pStr;
342         PSTAB_ENTRY pStab;
343         DWORD nStabLen,nSym;
344         char* pStrTab;
345         char* pSymTab;
346
347         char szSymName[2048];
348         HANDLE fileout;
349         int nSymStrLen,nStabStrLen;
350     int iRetVal = 0;
351
352         pDosHeader = (PIMAGE_DOS_HEADER)p;
353         pNTHeaders = (PIMAGE_NT_HEADERS)((DWORD)p + pDosHeader->e_lfanew);
354
355     if ((pDosHeader->e_magic == IMAGE_DOS_SIGNATURE)
356        && (pDosHeader->e_lfanew != 0L)
357        && (pNTHeaders->Signature == IMAGE_NT_SIGNATURE))
358     {
359                 if( pNTHeaders->FileHeader.PointerToSymbolTable ){
360
361                         pSymTab = (char*)((DWORD)p + pNTHeaders->FileHeader.PointerToSymbolTable);
362                         nSym = pNTHeaders->FileHeader.NumberOfSymbols;
363                         //string table follows immediately after symbol table. first 4 bytes give the length of the table
364                         //references to string table include the first 4 bytes.
365                         pStrTab = (char*)((PIMAGE_SYMBOL)pSymTab + nSym);
366                         nSymStrLen = *((DWORD*)pStrTab);
367                         find_stab_sections(p,IMAGE_FIRST_SECTION(pNTHeaders),pNTHeaders->FileHeader.NumberOfSections,
368                                         &pStab,&nStabLen,&pStr,&nStabStrLen);
369
370                         if(pStab && nStabLen && pStr && nStabStrLen)
371                         {
372                                 LPSTR pDot;
373
374                                 strcpy(szSymName,filename);
375                                 //printf("LOADER: file name = %s\n",szSymName);
376                                 if((pDot = strchr(szSymName,'.')))
377                                 {
378                                         *pDot = 0;
379                                         strcat(pDot,".dbg");
380                                 }
381                                 else
382                                 {
383                                         strcat(szSymName,".dbg");
384                                 }
385                                 //printf("LOADER: symbol file name = %s\n",szSymName);
386                     printf("LOADER: creating symbol file %s for %s\n",szSymName,filename);
387
388                                 fileout = CreateFile(szSymName,
389                                                                      GENERIC_READ | GENERIC_WRITE,
390                                                                      0,
391                                                                      NULL,
392                                                                      CREATE_ALWAYS,
393                                                                      0,
394                                                                      0);
395
396                     if(fileout != INVALID_HANDLE_VALUE)
397                                 {
398                                         printf("NumberOfSections: %d, size: %d\n", pNTHeaders->FileHeader.NumberOfSections,sizeof(IMAGE_SECTION_HEADER));
399                                         process_stabs(szSymName,
400                                                                   fileout,
401                                                                   IMAGE_FIRST_SECTION(pNTHeaders),
402                                                                   pNTHeaders->FileHeader.NumberOfSections*sizeof(IMAGE_SECTION_HEADER),
403                                                                   p,
404                                                                   pStab,
405                                                                   nStabLen,
406                                                                   pStr,
407                                                                   nStabStrLen,
408                                                                   (char*)pSymTab,
409                                                                   nSym*sizeof(IMAGE_SYMBOL),
410                                                                   pStrTab,
411                                                                   nSymStrLen);
412
413                                         CloseHandle(fileout);
414                                 }
415                     else
416                     {
417                         printf("LOADER: creation of symbol file %s failed\n",szSymName);
418                                         iRetVal = 2;
419                     }
420
421                         }
422                 else
423                 {
424                     printf("LOADER: file %s has no data inside symbol tables\n",filename);
425                                 if( ulGlobalVerbose )
426                                 {
427                         if( !pStab || !nStabLen )
428                             printf("LOADER: - symbol table is empty or not present\n");
429                         if( !pStr  || !nStabStrLen )
430                             printf("LOADER: - string table is empty or not present\n");
431                                 }
432                     iRetVal = 2;
433                 }
434                 }
435                 else{
436             printf("LOADER: file %s does not have a symbol table\n",filename);
437             iRetVal = 2;
438                 }
439     }
440     else
441     {
442         printf("LOADER: file %s is not an ELF binary\n",filename);
443         iRetVal = 1;
444     }
445
446     //printf("LOADER: leave process_pe()\n");
447     return iRetVal;
448 }
449
450 ///////////////////////////////////////////////////////////////////////////////////
451 // process_file()
452 //
453 ///////////////////////////////////////////////////////////////////////////////////
454 int process_file(char* filename)
455 {
456         int file;
457         void* p;
458         off_t len;
459         int iRetVal=0;
460
461     //printf("LOADER: enter process_file()\n");
462     file = _open(filename,O_RDONLY|_O_BINARY);
463     if(file>0)
464     {
465         //printf("LOADER: opened %s as FD %x\n",filename,file);
466
467         len = _lseek(file,0,SEEK_END);
468         printf("LOADER: file %s is %u bytes\n",filename,(int)len);
469
470         _lseek(file,0,SEEK_SET);
471
472         p = malloc(len+16);
473         if(p)
474         {
475                         long count;
476             //printf("LOADER: malloc'd @ %x\n",p);
477             memset(p,0,len+16);
478             if(len == (count = _read(file,p,len)))
479             {
480                 //printf("LOADER: trying ELF format\n");
481                 iRetVal = process_pe(filename,file,p,len);
482             }
483         }
484         _close(file);
485     }
486     else
487     {
488         printf("LOADER: file %s could not be opened\n",filename);
489                 iRetVal = 1;
490     }
491
492     //printf("LOADER: leave process_file()\n");
493     return iRetVal;
494 }
495
496 ///////////////////////////////////////////////////////////////////////////////////
497 // open_debugger()
498 //
499 ///////////////////////////////////////////////////////////////////////////////////
500 HANDLE  open_debugger(void)
501 {
502     debugger_file = CreateFile("\\Device\\Pice",GENERIC_READ,0,NULL,OPEN_EXISTING,NULL,NULL);
503         if(debugger_file == INVALID_HANDLE_VALUE)
504         {
505                 printf("LOADER: debugger is not loaded. Last Error: %ld\n", GetLastError());
506         }
507
508         return debugger_file;
509 }
510
511 ///////////////////////////////////////////////////////////////////////////////////
512 // close_debugger()
513 //
514 ///////////////////////////////////////////////////////////////////////////////////
515 void close_debugger(void)
516 {
517         if( !CloseHandle(debugger_file) ){
518                 printf("Error closing debugger handle: %ld\n", GetLastError());
519         }
520 }
521
522 int ioctl( HANDLE device, DWORD ioctrlcode, PDEBUGGER_STATUS_BLOCK psb)
523 {
524          DEBUGGER_STATUS_BLOCK tsb;
525          DWORD bytesreturned;
526          if( !DeviceIoControl( device, ioctrlcode, psb, sizeof(DEBUGGER_STATUS_BLOCK),
527                         &tsb, sizeof(DEBUGGER_STATUS_BLOCK),&bytesreturned, NULL) ){
528                 printf("Error in DeviceIoControl: %ld\n", GetLastError());
529                 return -EINVAL;
530          }
531          else{
532                 memcpy( psb, &tsb, sizeof(DEBUGGER_STATUS_BLOCK) );
533          }
534          return 0;
535 }
536
537 ///////////////////////////////////////////////////////////////////////////////////
538 // banner()
539 //
540 ///////////////////////////////////////////////////////////////////////////////////
541 void banner(void)
542 {
543     printf("#########################################################\n");
544     printf("####       Symbols LOADER/TRANSLATOR for PICE        ####\n");
545     printf("#########################################################\n");
546 }
547
548 #define ACTION_NONE             0
549 #define ACTION_LOAD             1
550 #define ACTION_UNLOAD           2
551 #define ACTION_TRANS            3
552 #define ACTION_RELOAD           4
553 #define ACTION_INSTALL          5
554 #define ACTION_UNINSTALL        6
555 #define ACTION_STATUS           7
556 #define ACTION_BREAK            8
557 #define ACTION_TERMINAL         9
558
559 ///////////////////////////////////////////////////////////////////////////////////
560 // change_symbols()
561 //
562 ///////////////////////////////////////////////////////////////////////////////////
563 void change_symbols(int action,char* pfilename)
564 {
565     int iRetVal = 0;
566         DEBUGGER_STATUS_BLOCK sb;
567
568         strcpy(sb.filename, pfilename);
569
570         switch(action)
571         {
572                 case ACTION_LOAD:
573                         printf("LOADER: loading symbols from %s\n",pfilename);
574                         if(open_debugger() != INVALID_HANDLE_VALUE)
575                         {
576                                 iRetVal = ioctl(debugger_file,PICE_IOCTL_LOAD,&sb);
577                                 close_debugger();
578                         }
579                         break;
580                 case ACTION_UNLOAD:
581                         printf("LOADER: unloading symbols from %s\n",pfilename);
582                         if(open_debugger() != INVALID_HANDLE_VALUE)
583                         {
584                                 iRetVal = ioctl(debugger_file,PICE_IOCTL_UNLOAD,&sb);
585                                 close_debugger();
586                         }
587                         break;
588                 case ACTION_RELOAD:
589                         printf("LOADER: reloading all symbols\n");
590                         if(open_debugger() != INVALID_HANDLE_VALUE)
591                         {
592                                 ioctl(debugger_file,PICE_IOCTL_RELOAD,NULL);
593                                 close_debugger();
594                         printf("LOADER: reloading DONE!\n");
595                         }
596                         break;
597         default :
598             printf("LOADER: an internal error has occurred at change_symbols\n");
599         }
600
601     switch( iRetVal )
602         {
603             case -EINVAL :
604                         printf("LOADER: debugger return value = -EINVAL, operation has failed\n");
605                         break;
606                 case 0 :
607                         // success - silently proceed
608                         break;
609                 default :
610                         printf("LOADER: debugger return value = %i, operation possibly failed\n",iRetVal);
611         }
612 }
613
614 // Dynamic install to be added later
615 #if 0
616 ///////////////////////////////////////////////////////////////////////////////////
617 // tryinstall()
618 //
619 ///////////////////////////////////////////////////////////////////////////////////
620 int tryinstall(void)
621 {
622     char *argv[]={"/sbin/insmod","pice.o",NULL};
623     int err = 0;
624     int pid,status;
625
626     banner();
627     printf("LOADER: trying to install debugger...\n");
628
629     if( open_debugger() != INVALID_HANDLE_VALUE  )
630     {
631         printf("LOADER: debugger already installed...\n");
632         close_debugger();
633         return 0;
634     }
635
636     // create a separate thread
637     pid = fork();
638     switch(pid)
639     {
640         case -1:
641             // error when forking, i.e. out E_NOMEM
642             err = errno;
643             printf("LOADER: fork failed for execution of '%s' (errno = %u).\n",argv[0],err);
644             break;
645         case 0:
646             // child process handler
647             execve(argv[0],argv,NULL);
648             // returns only on error, with return value -1, errno is set
649             printf("LOADER: couldn't execute '%s' (errno = %u)\n",argv[0],errno);
650             exit(255);
651             break;
652         default:
653             // parent process handler
654             printf("LOADER: waiting for debugger to load...\n");
655             pid = waitpid(pid, &status, 0); // suspend until child is done
656             if( (pid>0) && WIFEXITED(status) && (WEXITSTATUS(status) == 0) )
657                 printf("LOADER: debugger loaded!\n");
658             else if( pid<=0 )
659             {
660                 printf("LOADER: Error on loading debugger! (waitpid() = %i)\n",pid);
661                 err = -1;
662             }
663             else if( !WIFEXITED(status) )
664             {
665                 printf("LOADER: Error on loading debugger! (ifexited = %i)\n",WIFEXITED(status));
666                 err = -1;
667             }
668             else
669             {
670                 printf("LOADER: Error on loading debugger! (exitstatus = %u)\n",WEXITSTATUS(status));
671                 err = WEXITSTATUS(status);
672             }
673             break;
674     }
675
676     return err;
677 }
678
679 ///////////////////////////////////////////////////////////////////////////////////
680 // tryuninstall()
681 //
682 ///////////////////////////////////////////////////////////////////////////////////
683 int tryuninstall(void)
684 {
685     char *argv[]={"/sbin/rmmod","pice",NULL};
686     int err = 0;
687     int pid,status;
688
689     banner();
690     printf("LOADER: trying to remove debugger...\n");
691
692     // check for loaded debugger
693     if(open_debugger() == INVALID_HANDLE_VALUE)
694     {
695         return -1;
696     }
697     // don't to close, else we'll have a reference count != 0
698     close_debugger();
699
700     // create a separate thread
701     pid = fork();
702     switch(pid)
703     {
704         case -1:
705             // error when forking, i.e. out E_NOMEM
706             err = errno;
707             printf("LOADER: fork failed for execution of '%s' (errno=%u).\n",argv[0],err);
708             break;
709         case 0:
710             // child process handler
711             execve(argv[0],argv,NULL);
712             // returns only on error, with return value -1, errno is set
713             printf("LOADER: couldn't execute '%s' (errno = %u)\n",argv[0],errno);
714             exit(255);
715             break;
716         default:
717             // parent process handler
718             printf("LOADER: waiting for debugger to unload...\n");
719             pid = waitpid(pid, &status, 0); // suspend until child is done
720
721             if( (pid>0) && WIFEXITED(status) && (WEXITSTATUS(status) == 0) )
722                 printf("LOADER: debugger removed!\n");
723             else if( pid<=0 )
724             {
725                 printf("LOADER: Error on removing debugger! (waitpid() = %i)\n",pid);
726                 err = -1;
727             }
728             else if( !WIFEXITED(status) )
729             {
730                 printf("LOADER: Error on removing debugger! (ifexited = %i)\n",WIFEXITED(status));
731                 err = -1;
732             }
733             else
734             {
735                 printf("LOADER: Error on removing debugger! (exitstatus = %u)\n",WEXITSTATUS(status));
736                 err = WEXITSTATUS(status);
737             }
738             break;
739     }
740     return err;
741 }
742 #endif
743
744 ///////////////////////////////////////////////////////////////////////////////////
745 // showstatus()
746 //
747 ///////////////////////////////////////////////////////////////////////////////////
748 void showstatus(void)
749 {
750     DEBUGGER_STATUS_BLOCK sb;
751     int iRetVal;
752
753         if(open_debugger() != INVALID_HANDLE_VALUE)
754         {
755                 iRetVal = ioctl(debugger_file,PICE_IOCTL_STATUS,&sb);
756
757         //printf("LOADER: Test = %X\n",sb.Test);
758                 close_debugger();
759         }
760 }
761
762 ///////////////////////////////////////////////////////////////////////////////////
763 // dobreak()
764 //
765 ///////////////////////////////////////////////////////////////////////////////////
766 void dobreak(void)
767 {
768     int iRetVal;
769
770         if(open_debugger() != INVALID_HANDLE_VALUE)
771         {
772                 iRetVal = ioctl(debugger_file,PICE_IOCTL_BREAK,NULL);
773                 close_debugger();
774         }
775 }
776
777 ///////////////////////////////////////////////////////////////////////////////////
778 // doterminal()
779 //
780 ///////////////////////////////////////////////////////////////////////////////////
781 #if 0
782 void doterminal(void)
783 {
784     if(SetupSerial(2,B115200))
785     {
786         DebuggerShell();
787         CloseSerial();
788     }
789 }
790 #endif
791
792 ///////////////////////////////////////////////////////////////////////////////////
793 // process_switches()
794 //
795 // returns !=0 in case of a commandline error
796 //
797 ///////////////////////////////////////////////////////////////////////////////////
798 int process_switches(int argc,char* argv[])
799 {
800         int i;
801         char* parg,*pfilename = NULL;
802         int action = ACTION_NONE;
803         int error = 0;
804
805     // parse commandline arguments
806         for(i=1;i<argc;i++)
807         {
808                 parg = argv[i];
809                 if(*parg == '-')
810                 {
811                     int new_action=ACTION_NONE;
812
813                         parg++;
814                         if(strcmp(parg,"load")==0 || strcmp(parg,"l")==0)
815                         {
816                                 new_action = ACTION_LOAD;
817                         }
818                         else if(strcmp(parg,"unload")==0 || strcmp(parg,"u")==0)
819                         {
820                                 new_action = ACTION_UNLOAD;
821                         }
822                         else if(strcmp(parg,"trans")==0 || strcmp(parg,"t")==0)
823             {
824                 new_action = ACTION_TRANS;
825             }
826                         else if(strcmp(parg,"reload")==0 || strcmp(parg,"r")==0)
827             {
828                 new_action = ACTION_RELOAD;
829             }
830                         else if(strcmp(parg,"verbose")==0 || strcmp(parg,"v")==0)
831             {
832                             if( ulGlobalVerbose+1 > ulGlobalVerbose )
833                                     ulGlobalVerbose++;
834             }
835                         else if(strcmp(parg,"install")==0 || strcmp(parg,"i")==0)
836             {
837                 new_action = ACTION_INSTALL;
838             }
839                         else if(strcmp(parg,"uninstall")==0 || strcmp(parg,"x")==0)
840             {
841                 new_action = ACTION_UNINSTALL;
842             }
843                         else if(strcmp(parg,"status")==0 || strcmp(parg,"s")==0)
844             {
845                 new_action = ACTION_STATUS;
846             }
847                         else if(strcmp(parg,"break")==0 || strcmp(parg,"b")==0)
848             {
849                 new_action = ACTION_BREAK;
850             }
851                         else if(strcmp(parg,"serial")==0 || strcmp(parg,"ser")==0)
852             {
853                 new_action = ACTION_TERMINAL;
854             }
855                         else
856                         {
857                                 printf("LOADER: error: unknown switch %s", argv[i]);
858                                 error = 1;
859                         }
860
861             if( new_action != ACTION_NONE )
862             {
863                 if( action == ACTION_NONE )
864                     action = new_action;
865                 else
866                 if( action == new_action )
867                 {
868                     // identical, just ignore
869                 }
870                 else
871                 {
872                     printf("LOADER: error: conflicting switch %s", argv[i]);
873                     error = 1;
874                 }
875             }
876                 }
877                 else
878                 {
879             if( pfilename )
880             {
881                 printf("LOADER: error: additional filename %s", parg);
882                 error = 1;
883             }
884                         pfilename = parg;
885                 }
886         }
887
888     // check number of required parameters
889     switch( action )
890     {
891         case ACTION_TRANS :
892         case ACTION_LOAD :
893         case ACTION_UNLOAD :
894             if( !pfilename )
895             {
896                 printf("LOADER: error: missing filename\n");
897                 error = 1;
898             }
899             break;
900         case ACTION_RELOAD :
901             /* filename parameter is optional */
902             break;
903 #if 0
904         case ACTION_UNINSTALL:
905             close_debugger();
906             tryuninstall();
907             break;
908         case ACTION_INSTALL:
909             tryinstall();
910             break;
911 #endif
912         case ACTION_STATUS:
913             showstatus();
914             break;
915         case ACTION_BREAK:
916             dobreak();
917             break;
918 #if 0
919         case ACTION_TERMINAL:
920             doterminal();
921             break;
922 #endif
923         case ACTION_NONE :
924             printf("LOADER: no action specified specifed on commandline\n");
925             error = 1;
926
927             break;
928         default :
929             printf("LOADER: an internal error has occurred at commandline parsing\n");
930             error = 1;
931     }
932
933     if( !error )    // commandline was fine, now start processing
934     {
935         switch( action )
936         {
937             case ACTION_TRANS :
938                 printf("LOADER: trying to translate file %s...\n",pfilename);
939                 if( process_file(pfilename)==0 )
940                     printf("LOADER: file %s has been translated\n",pfilename);
941                 else
942                     printf("LOADER: error while translating file %s\n",pfilename);
943                 break;
944             case ACTION_LOAD :
945             case ACTION_UNLOAD :
946             case ACTION_RELOAD :
947                 change_symbols(action,pfilename);
948                 break;
949         }
950     }
951
952     return error;
953 }
954
955
956 ///////////////////////////////////////////////////////////////////////////////////
957 // showhelp()
958 //
959 ///////////////////////////////////////////////////////////////////////////////////
960 void showhelp(void)
961 {
962     banner();
963     printf("LOADER: Syntax:\n");
964     printf("LOADER:         loader [switches] [executable/object file path]\n");
965     printf("LOADER: Switches:\n");
966     printf("LOADER:         -trans      (-t):   translate from exe to sym\n");
967     printf("LOADER:         -load       (-l):   load symbols\n");
968     printf("LOADER:         -unload     (-u):   unload symbols\n");
969     printf("LOADER:         -reload     (-r):   reload some/all symbols\n");
970     printf("LOADER:         -verbose    (-v):   be a bit more verbose\n");
971     printf("LOADER:         -install    (-i):   install pICE debugger\n");
972     printf("LOADER:         -uninstall  (-x):   uninstall pICE debugger\n");
973     printf("LOADER:         -break      (-b):   break into debugger\n");
974     printf("LOADER:         -serial     (-ser): start serial line terminal\n");
975 }
976
977 ///////////////////////////////////////////////////////////////////////////////////
978 // showpermission()
979 //
980 ///////////////////////////////////////////////////////////////////////////////////
981 void showpermission(void)
982 {
983     banner();
984     printf("LOADER: You must be superuser!\n");
985 }
986
987 ///////////////////////////////////////////////////////////////////////////////////
988 // main()
989 //
990 ///////////////////////////////////////////////////////////////////////////////////
991 int main(int argc,char* argv[])
992 {
993     if(argc==1 || argc>3)
994     {
995                 showhelp();
996
997                 return 1;
998     }
999
1000         return process_switches(argc,argv);
1001 }