2 * File source.c - source file handling for internal debugger.
4 * Copyright (C) 1997, Eric Youngdale.
12 #include <sys/types.h>
13 #ifdef HAVE_SYS_MMAN_H
22 #define PATH_MAX _MAX_PATH
30 struct searchlist
* next
;
38 struct open_filelist
* next
;
41 unsigned int * linelist
;
44 static struct open_filelist
* ofiles
;
46 static struct searchlist
* listhead
;
47 static char DEBUG_current_sourcefile
[PATH_MAX
];
48 static int DEBUG_start_sourceline
= -1;
49 static int DEBUG_end_sourceline
= -1;
54 struct searchlist
* sl
;
56 DEBUG_Printf(DBG_CHN_MESG
,"Search list :\n");
57 for(sl
= listhead
; sl
; sl
= sl
->next
)
59 DEBUG_Printf(DBG_CHN_MESG
, "\t%s\n", sl
->path
);
61 DEBUG_Printf(DBG_CHN_MESG
, "\n");
65 DEBUG_AddPath(const char * path
)
67 struct searchlist
* sl
;
69 sl
= (struct searchlist
*) DBG_alloc(sizeof(struct searchlist
));
76 sl
->path
= DBG_strdup(path
);
83 struct searchlist
* sl
;
84 struct searchlist
* nxt
;
86 for(sl
= listhead
; sl
; sl
= nxt
)
98 DEBUG_DisplaySource(char * sourcefile
, int start
, int end
)
104 struct open_filelist
* ol
;
106 char * basename
= NULL
;
109 struct searchlist
* sl
;
112 char tmppath
[PATH_MAX
];
115 * First see whether we have the file open already. If so, then
116 * use that, otherwise we have to try and open it.
118 for(ol
= ofiles
; ol
; ol
= ol
->next
)
120 if( strcmp(ol
->path
, sourcefile
) == 0 )
129 * Try again, stripping the path from the opened file.
131 basename
= strrchr(sourcefile
, '\\' );
133 basename
= strrchr(sourcefile
, '/' );
135 basename
= sourcefile
;
139 for(ol
= ofiles
; ol
; ol
= ol
->next
)
141 if( strcmp(ol
->path
, basename
) == 0 )
152 * Crapola. We need to try and open the file.
154 status
= stat(sourcefile
, &statbuf
);
157 strcpy(tmppath
, sourcefile
);
159 else if( (status
= stat(basename
, &statbuf
)) != -1 )
161 strcpy(tmppath
, basename
);
165 for(sl
= listhead
; sl
; sl
= sl
->next
)
167 strcpy(tmppath
, sl
->path
);
168 if( tmppath
[strlen(tmppath
)-1] != '/' )
170 strcat(tmppath
, "/");
173 * Now append the base file name.
175 strcat(tmppath
, basename
);
177 status
= stat(tmppath
, &statbuf
);
188 * Still couldn't find it. Ask user for path to add.
190 sprintf(zbuf
, "Enter path to file %s: ", sourcefile
);
191 lstrcpynA(tmppath
, readline(zbuf
), sizeof(tmppath
));
193 if( tmppath
[strlen(tmppath
)-1] == '\n' )
195 tmppath
[strlen(tmppath
)-1] = '\0';
198 if( tmppath
[strlen(tmppath
)-1] != '/' )
200 strcat(tmppath
, "/");
203 * Now append the base file name.
205 strcat(tmppath
, basename
);
207 status
= stat(tmppath
, &statbuf
);
211 * OK, I guess the user doesn't really want to see it
214 ol
= (struct open_filelist
*) DBG_alloc(sizeof(*ol
));
215 ol
->path
= DBG_strdup(sourcefile
);
216 ol
->real_path
= NULL
;
221 DEBUG_Printf(DBG_CHN_MESG
,"Unable to open file %s\n", tmppath
);
227 * Create header for file.
229 ol
= (struct open_filelist
*) DBG_alloc(sizeof(*ol
));
230 ol
->path
= DBG_strdup(sourcefile
);
231 ol
->real_path
= DBG_strdup(tmppath
);
235 ol
->size
= statbuf
.st_size
;
239 * Now open and map the file.
241 fd
= open(tmppath
, O_RDONLY
);
247 addr
= mmap(0, statbuf
.st_size
, PROT_READ
, MAP_PRIVATE
, fd
, 0);
248 if( addr
== (char *) -1 )
254 * Now build up the line number mapping table.
258 while(pnt
< addr
+ ol
->size
)
267 ol
->linelist
= (unsigned int*) DBG_alloc( ol
->nlines
* sizeof(unsigned int) );
271 ol
->linelist
[nlines
++] = 0;
272 while(pnt
< addr
+ ol
->size
)
276 ol
->linelist
[nlines
++] = pnt
- addr
;
279 ol
->linelist
[nlines
++] = pnt
- addr
;
285 * We know what the file is, we just need to reopen it and remap it.
287 fd
= open(ol
->real_path
, O_RDONLY
);
293 addr
= mmap(0, ol
->size
, PROT_READ
, MAP_PRIVATE
, fd
, 0);
294 if( addr
== (char *) -1 )
301 * All we need to do is to display the source lines here.
304 for(i
=start
- 1; i
<= end
- 1; i
++)
306 if( i
< 0 || i
>= ol
->nlines
- 1)
312 memset(&buffer
, 0, sizeof(buffer
));
313 if( ol
->linelist
[i
+1] != ol
->linelist
[i
] )
315 memcpy(&buffer
, addr
+ ol
->linelist
[i
],
316 (ol
->linelist
[i
+1] - ol
->linelist
[i
]) - 1);
318 DEBUG_Printf(DBG_CHN_MESG
,"%d\t%s\n", i
+ 1, buffer
);
321 munmap(addr
, ol
->size
);
329 DEBUG_List(struct list_id
* source1
, struct list_id
* source2
,
338 * We need to see what source file we need. Hopefully we only have
339 * one specified, otherwise we might as well punt.
343 && source1
->sourcefile
!= NULL
344 && source2
->sourcefile
!= NULL
345 && strcmp(source1
->sourcefile
, source2
->sourcefile
) != 0 )
347 DEBUG_Printf(DBG_CHN_MESG
, "Ambiguous source file specification.\n");
352 if( source1
!= NULL
&& source1
->sourcefile
!= NULL
)
354 sourcefile
= source1
->sourcefile
;
357 if( sourcefile
== NULL
359 && source2
->sourcefile
!= NULL
)
361 sourcefile
= source2
->sourcefile
;
364 if( sourcefile
== NULL
)
366 sourcefile
= (char *) &DEBUG_current_sourcefile
;
369 if( sourcefile
== NULL
)
371 DEBUG_Printf(DBG_CHN_MESG
, "No source file specified.\n");
376 * Now figure out the line number range to be listed.
381 if( source1
!= NULL
)
383 start
= source1
->line
;
386 if( source2
!= NULL
)
391 if( start
== -1 && end
== -1 )
395 end
= DEBUG_start_sourceline
;
400 start
= DEBUG_end_sourceline
;
404 else if( start
== -1 )
414 * Now call this function to do the dirty work.
416 rtn
= DEBUG_DisplaySource(sourcefile
, start
, end
);
418 if( sourcefile
!= (char *) &DEBUG_current_sourcefile
)
420 strcpy(DEBUG_current_sourcefile
, sourcefile
);
422 DEBUG_start_sourceline
= start
;
423 DEBUG_end_sourceline
= end
;
426 DBG_ADDR DEBUG_LastDisassemble
={0,0};
429 _disassemble(DBG_ADDR
*addr
)
433 DEBUG_PrintAddress( addr
, DEBUG_CurrThread
->dbg_mode
, TRUE
);
434 DEBUG_Printf(DBG_CHN_MESG
,": ");
435 if (!DEBUG_READ_MEM_VERBOSE((void*)DEBUG_ToLinear(addr
), &ch
, sizeof(ch
))) return 0;
436 DEBUG_Disasm( addr
, TRUE
);
437 DEBUG_Printf(DBG_CHN_MESG
,"\n");
442 _disassemble_fixaddr(DBG_VALUE
*value
) {
444 struct datatype
*testtype
;
446 assert(value
->cookie
== DV_TARGET
|| value
->cookie
== DV_HOST
);
449 DEBUG_FixAddress(&value
->addr
, DEBUG_context
.SegCs
);
452 if( value
->type
!= NULL
)
454 if( value
->type
== DEBUG_TypeIntConst
)
457 * We know that we have the actual offset stored somewhere
458 * else in 32-bit space. Grab it, and we
461 seg2
= value
->addr
.seg
;
463 value
->addr
.off
= DEBUG_GetExprValue(value
, NULL
);
464 value
->addr
.seg
= seg2
;
468 DEBUG_TypeDerefPointer(value
, &testtype
);
469 if( testtype
!= NULL
|| value
->type
== DEBUG_TypeIntConst
)
470 value
->addr
.off
= DEBUG_GetExprValue(value
, NULL
);
473 else if (!value
->addr
.seg
&& !value
->addr
.off
)
475 DEBUG_Printf(DBG_CHN_MESG
,"Invalid expression\n");
481 DEBUG_Disassemble(const DBG_VALUE
*xstart
,const DBG_VALUE
*xend
,int offset
)
489 _disassemble_fixaddr(&start
);
493 _disassemble_fixaddr(&end
);
495 if (!xstart
&& !xend
) {
496 last
= DEBUG_LastDisassemble
;
497 if (!last
.seg
&& !last
.off
)
498 DEBUG_GetCurrentAddress( &last
);
500 for (i
=0;i
<offset
;i
++)
501 if (!_disassemble(&last
)) break;
502 DEBUG_LastDisassemble
= last
;
507 for (i
=0;i
<offset
;i
++)
508 if (!_disassemble(&last
)) break;
509 DEBUG_LastDisassemble
= last
;
512 while (last
.off
<= end
.addr
.off
)
513 if (!_disassemble(&last
)) break;
514 DEBUG_LastDisassemble
= last
;
524 DEBUG_AddPath("../../de");
527 fscanf(stdin
,"%d %d", &i
, &j
);
528 DEBUG_DisplaySource("dumpexe.c", i
, j
);