309ee03f38ac2cc48b167f64bc73f4c5106f8b51
[reactos.git] / rosapps / applications / sysutils / 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 }