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
25 #include "wine/winbase16.h"
34 struct searchlist
* next
;
42 struct open_filelist
* next
;
45 unsigned int * linelist
;
48 static struct open_filelist
* ofiles
;
50 static struct searchlist
* listhead
;
51 static char DEBUG_current_sourcefile
[PATH_MAX
];
52 static int DEBUG_start_sourceline
= -1;
53 static int DEBUG_end_sourceline
= -1;
58 struct searchlist
* sl
;
60 fprintf(stderr
,"Search list :\n");
61 for(sl
= listhead
; sl
; sl
= sl
->next
)
63 fprintf(stderr
, "\t%s\n", sl
->path
);
65 fprintf(stderr
, "\n");
69 DEBUG_AddPath(const char * path
)
71 struct searchlist
* sl
;
73 sl
= (struct searchlist
*) DBG_alloc(sizeof(struct searchlist
));
80 sl
->path
= DBG_strdup(path
);
87 struct searchlist
* sl
;
88 struct searchlist
* nxt
;
90 for(sl
= listhead
; sl
; sl
= nxt
)
102 DEBUG_DisplaySource(char * sourcefile
, int start
, int end
)
108 struct open_filelist
* ol
;
113 struct searchlist
* sl
;
116 char tmppath
[PATH_MAX
];
119 * First see whether we have the file open already. If so, then
120 * use that, otherwise we have to try and open it.
122 for(ol
= ofiles
; ol
; ol
= ol
->next
)
124 if( strcmp(ol
->path
, sourcefile
) == 0 )
133 * Try again, stripping the path from the opened file.
135 basename
= strrchr(sourcefile
, '\\' );
137 basename
= strrchr(sourcefile
, '/' );
139 basename
= sourcefile
;
143 for(ol
= ofiles
; ol
; ol
= ol
->next
)
145 if( strcmp(ol
->path
, basename
) == 0 )
156 * Crapola. We need to try and open the file.
158 status
= stat(sourcefile
, &statbuf
);
161 strcpy(tmppath
, sourcefile
);
163 else if( (status
= stat(basename
, &statbuf
)) != -1 )
165 strcpy(tmppath
, basename
);
169 for(sl
= listhead
; sl
; sl
= sl
->next
)
171 strcpy(tmppath
, sl
->path
);
172 if( tmppath
[strlen(tmppath
)-1] != '/' )
174 strcat(tmppath
, "/");
177 * Now append the base file name.
179 strcat(tmppath
, basename
);
181 status
= stat(tmppath
, &statbuf
);
191 * Still couldn't find it. Ask user for path to add.
193 fprintf(stderr
,"Enter path to file %s: ", sourcefile
);
194 fgets(tmppath
, sizeof(tmppath
), stdin
);
196 if( tmppath
[strlen(tmppath
)-1] == '\n' )
198 tmppath
[strlen(tmppath
)-1] = '\0';
201 if( tmppath
[strlen(tmppath
)-1] != '/' )
203 strcat(tmppath
, "/");
206 * Now append the base file name.
208 strcat(tmppath
, basename
);
210 status
= stat(tmppath
, &statbuf
);
214 * OK, I guess the user doesn't really want to see it
217 ol
= (struct open_filelist
*) DBG_alloc(sizeof(*ol
));
218 ol
->path
= DBG_strdup(sourcefile
);
219 ol
->real_path
= NULL
;
224 fprintf(stderr
,"Unable to open file %s\n", tmppath
);
230 * Create header for file.
232 ol
= (struct open_filelist
*) DBG_alloc(sizeof(*ol
));
233 ol
->path
= DBG_strdup(sourcefile
);
234 ol
->real_path
= DBG_strdup(tmppath
);
238 ol
->size
= statbuf
.st_size
;
242 * Now open and map the file.
244 fd
= open(tmppath
, O_RDONLY
);
250 addr
= mmap(0, statbuf
.st_size
, PROT_READ
, MAP_PRIVATE
, fd
, 0);
251 if( addr
== (char *) -1 )
257 * Now build up the line number mapping table.
261 while(pnt
< addr
+ ol
->size
)
270 ol
->linelist
= (unsigned int*) DBG_alloc( ol
->nlines
* sizeof(unsigned int) );
274 ol
->linelist
[nlines
++] = 0;
275 while(pnt
< addr
+ ol
->size
)
279 ol
->linelist
[nlines
++] = pnt
- addr
;
282 ol
->linelist
[nlines
++] = pnt
- addr
;
288 * We know what the file is, we just need to reopen it and remap it.
290 fd
= open(ol
->real_path
, O_RDONLY
);
296 addr
= mmap(0, ol
->size
, PROT_READ
, MAP_PRIVATE
, fd
, 0);
297 if( addr
== (char *) -1 )
304 * All we need to do is to display the source lines here.
307 for(i
=start
- 1; i
<= end
- 1; i
++)
309 if( i
< 0 || i
>= ol
->nlines
- 1)
315 memset(&buffer
, 0, sizeof(buffer
));
316 if( ol
->linelist
[i
+1] != ol
->linelist
[i
] )
318 memcpy(&buffer
, addr
+ ol
->linelist
[i
],
319 (ol
->linelist
[i
+1] - ol
->linelist
[i
]) - 1);
321 fprintf(stderr
,"%d\t%s\n", i
+ 1, buffer
);
324 munmap(addr
, ol
->size
);
332 DEBUG_List(struct list_id
* source1
, struct list_id
* source2
,
341 * We need to see what source file we need. Hopefully we only have
342 * one specified, otherwise we might as well punt.
346 && source1
->sourcefile
!= NULL
347 && source2
->sourcefile
!= NULL
348 && strcmp(source1
->sourcefile
, source2
->sourcefile
) != 0 )
350 fprintf(stderr
, "Ambiguous source file specification.\n");
355 if( source1
!= NULL
&& source1
->sourcefile
!= NULL
)
357 sourcefile
= source1
->sourcefile
;
360 if( sourcefile
== NULL
362 && source2
->sourcefile
!= NULL
)
364 sourcefile
= source2
->sourcefile
;
367 if( sourcefile
== NULL
)
369 sourcefile
= (char *) &DEBUG_current_sourcefile
;
372 if( sourcefile
== NULL
)
374 fprintf(stderr
, "No source file specified.\n");
379 * Now figure out the line number range to be listed.
384 if( source1
!= NULL
)
386 start
= source1
->line
;
389 if( source2
!= NULL
)
394 if( start
== -1 && end
== -1 )
398 end
= DEBUG_start_sourceline
;
403 start
= DEBUG_end_sourceline
;
407 else if( start
== -1 )
417 * Now call this function to do the dirty work.
419 rtn
= DEBUG_DisplaySource(sourcefile
, start
, end
);
421 if( sourcefile
!= (char *) &DEBUG_current_sourcefile
)
423 strcpy(DEBUG_current_sourcefile
, sourcefile
);
425 DEBUG_start_sourceline
= start
;
426 DEBUG_end_sourceline
= end
;
429 DBG_ADDR DEBUG_LastDisassemble
={NULL
,0,0};
431 void DEBUG_GetCurrentAddress( DBG_ADDR
*addr
)
434 TDB
*pTask
= (TDB
*)GlobalLock16( GetCurrentTask() );
437 addr
->seg
= CS_reg(&DEBUG_context
);
438 addr
->off
= EIP_reg(&DEBUG_context
);
440 if (ISV86(&DEBUG_context
)) addr
->seg
|= (DWORD
)(pTask
? pTask
->hModule
: 0) << 16;
441 else if (IS_SELECTOR_SYSTEM(addr
->seg
)) addr
->seg
= 0;
443 GlobalUnlock16( GetCurrentTask() );
447 addr
->off
= (DWORD
)GET_IP(&DEBUG_context
);
453 _disassemble(DBG_ADDR
*addr
)
455 DEBUG_PrintAddress( addr
, dbg_mode
, TRUE
);
456 fprintf(stderr
,": ");
457 if (!DBG_CHECK_READ_PTR( addr
, 1 )) return 0;
458 DEBUG_Disasm( addr
, TRUE
);
459 fprintf(stderr
,"\n");
464 _disassemble_fixaddr(DBG_ADDR
*addr
) {
466 struct datatype
*testtype
;
468 DBG_FIX_ADDR_SEG(addr
,CS_reg(&DEBUG_context
));
469 if( addr
->type
!= NULL
)
471 if( addr
->type
== DEBUG_TypeIntConst
)
474 * We know that we have the actual offset stored somewhere
475 * else in 32-bit space. Grab it, and we
480 addr
->off
= DEBUG_GetExprValue(addr
, NULL
);
485 if (!DBG_CHECK_READ_PTR( addr
, 1 )) return;
486 DEBUG_TypeDerefPointer(addr
, &testtype
);
487 if( testtype
!= NULL
|| addr
->type
== DEBUG_TypeIntConst
)
488 addr
->off
= DEBUG_GetExprValue(addr
, NULL
);
491 else if (!addr
->seg
&& !addr
->off
)
493 fprintf(stderr
,"Invalid expression\n");
499 DEBUG_Disassemble(const DBG_ADDR
*xstart
,const DBG_ADDR
*xend
,int offset
)
507 _disassemble_fixaddr(&start
);
511 _disassemble_fixaddr(&end
);
513 if (!xstart
&& !xend
) {
514 last
= DEBUG_LastDisassemble
;
515 if (!last
.seg
&& !last
.off
)
516 DEBUG_GetCurrentAddress( &last
);
518 for (i
=0;i
<offset
;i
++)
519 if (!_disassemble(&last
)) break;
520 memcpy(&DEBUG_LastDisassemble
,&last
,sizeof(last
));
525 for (i
=0;i
<offset
;i
++)
526 if (!_disassemble(&last
)) break;
527 memcpy(&DEBUG_LastDisassemble
,&last
,sizeof(last
));
530 while (last
.off
<= end
.off
)
531 if (!_disassemble(&last
)) break;
532 memcpy(&DEBUG_LastDisassemble
,&last
,sizeof(last
));
542 DEBUG_AddPath("../../de");
545 fscanf(stdin
,"%d %d", &i
, &j
);
546 DEBUG_DisplaySource("dumpexe.c", i
, j
);