2 * File source.c - source file handling for internal debugger.
4 * Copyright (C) 1997, Eric Youngdale.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include <sys/types.h>
26 #ifdef HAVE_SYS_MMAN_H
35 #define PATH_MAX MAX_PATH
43 struct searchlist
* next
;
51 struct open_filelist
* next
;
54 unsigned int * linelist
;
57 static struct open_filelist
* ofiles
;
59 static struct searchlist
* listhead
;
60 static char DEBUG_current_sourcefile
[PATH_MAX
];
61 static int DEBUG_start_sourceline
= -1;
62 static int DEBUG_end_sourceline
= -1;
67 struct searchlist
* sl
;
69 DEBUG_Printf(DBG_CHN_MESG
,"Search list :\n");
70 for(sl
= listhead
; sl
; sl
= sl
->next
)
72 DEBUG_Printf(DBG_CHN_MESG
, "\t%s\n", sl
->path
);
74 DEBUG_Printf(DBG_CHN_MESG
, "\n");
78 DEBUG_AddPath(const char * path
)
80 struct searchlist
* sl
;
82 sl
= (struct searchlist
*) DBG_alloc(sizeof(struct searchlist
));
89 sl
->path
= DBG_strdup(path
);
96 struct searchlist
* sl
;
97 struct searchlist
* nxt
;
99 for(sl
= listhead
; sl
; sl
= nxt
)
111 DEBUG_DisplaySource(char * sourcefile
, int start
, int end
)
117 struct open_filelist
* ol
;
119 char * basename
= NULL
;
122 struct searchlist
* sl
;
125 char tmppath
[PATH_MAX
];
128 * First see whether we have the file open already. If so, then
129 * use that, otherwise we have to try and open it.
131 for(ol
= ofiles
; ol
; ol
= ol
->next
)
133 if( strcmp(ol
->path
, sourcefile
) == 0 )
142 * Try again, stripping the path from the opened file.
144 basename
= strrchr(sourcefile
, '\\' );
146 basename
= strrchr(sourcefile
, '/' );
148 basename
= sourcefile
;
152 for(ol
= ofiles
; ol
; ol
= ol
->next
)
154 if( strcmp(ol
->path
, basename
) == 0 )
165 * Crapola. We need to try and open the file.
167 status
= stat(sourcefile
, &statbuf
);
170 strcpy(tmppath
, sourcefile
);
172 else if( (status
= stat(basename
, &statbuf
)) != -1 )
174 strcpy(tmppath
, basename
);
178 for(sl
= listhead
; sl
; sl
= sl
->next
)
180 strcpy(tmppath
, sl
->path
);
181 if( tmppath
[strlen(tmppath
)-1] != '/' )
183 strcat(tmppath
, "/");
186 * Now append the base file name.
188 strcat(tmppath
, basename
);
190 status
= stat(tmppath
, &statbuf
);
199 if (DEBUG_InteractiveP
)
203 * Still couldn't find it. Ask user for path to add.
205 sprintf(zbuf
, "Enter path to file '%s': ", sourcefile
);
206 DEBUG_ReadLine(zbuf
, tmppath
, sizeof(tmppath
));
208 if( tmppath
[strlen(tmppath
)-1] == '\n' )
210 tmppath
[strlen(tmppath
)-1] = '\0';
213 if( tmppath
[strlen(tmppath
)-1] != '/' )
215 strcat(tmppath
, "/");
218 * Now append the base file name.
220 strcat(tmppath
, basename
);
222 status
= stat(tmppath
, &statbuf
);
227 * OK, I guess the user doesn't really want to see it
230 ol
= (struct open_filelist
*) DBG_alloc(sizeof(*ol
));
231 ol
->path
= DBG_strdup(sourcefile
);
232 ol
->real_path
= NULL
;
237 DEBUG_Printf(DBG_CHN_MESG
,"Unable to open file %s\n", tmppath
);
243 * Create header for file.
245 ol
= (struct open_filelist
*) DBG_alloc(sizeof(*ol
));
246 ol
->path
= DBG_strdup(sourcefile
);
247 ol
->real_path
= DBG_strdup(tmppath
);
251 ol
->size
= statbuf
.st_size
;
255 * Now open and map the file.
257 fd
= open(tmppath
, O_RDONLY
);
263 addr
= mmap(0, statbuf
.st_size
, PROT_READ
, MAP_PRIVATE
, fd
, 0);
264 if( addr
== (char *) -1 )
270 * Now build up the line number mapping table.
274 while(pnt
< addr
+ ol
->size
)
283 ol
->linelist
= (unsigned int*) DBG_alloc( ol
->nlines
* sizeof(unsigned int) );
287 ol
->linelist
[nlines
++] = 0;
288 while(pnt
< addr
+ ol
->size
)
292 ol
->linelist
[nlines
++] = pnt
- addr
;
295 ol
->linelist
[nlines
++] = pnt
- addr
;
301 * We know what the file is, we just need to reopen it and remap it.
303 fd
= open(ol
->real_path
, O_RDONLY
);
309 addr
= mmap(0, ol
->size
, PROT_READ
, MAP_PRIVATE
, fd
, 0);
310 if( addr
== (char *) -1 )
317 * All we need to do is to display the source lines here.
320 for(i
=start
- 1; i
<= end
- 1; i
++)
322 if( i
< 0 || i
>= ol
->nlines
- 1)
328 memset(&buffer
, 0, sizeof(buffer
));
329 if( ol
->linelist
[i
+1] != ol
->linelist
[i
] )
331 memcpy(&buffer
, addr
+ ol
->linelist
[i
],
332 (ol
->linelist
[i
+1] - ol
->linelist
[i
]) - 1);
334 DEBUG_Printf(DBG_CHN_MESG
,"%d\t%s\n", i
+ 1, buffer
);
337 munmap(addr
, ol
->size
);
345 DEBUG_List(struct list_id
* source1
, struct list_id
* source2
,
354 * We need to see what source file we need. Hopefully we only have
355 * one specified, otherwise we might as well punt.
359 && source1
->sourcefile
!= NULL
360 && source2
->sourcefile
!= NULL
361 && strcmp(source1
->sourcefile
, source2
->sourcefile
) != 0 )
363 DEBUG_Printf(DBG_CHN_MESG
, "Ambiguous source file specification.\n");
368 if( source1
!= NULL
&& source1
->sourcefile
!= NULL
)
370 sourcefile
= source1
->sourcefile
;
373 if( sourcefile
== NULL
375 && source2
->sourcefile
!= NULL
)
377 sourcefile
= source2
->sourcefile
;
380 if( sourcefile
== NULL
)
382 sourcefile
= (char *) &DEBUG_current_sourcefile
;
385 if( sourcefile
== NULL
)
387 DEBUG_Printf(DBG_CHN_MESG
, "No source file specified.\n");
392 * Now figure out the line number range to be listed.
397 if( source1
!= NULL
)
399 start
= source1
->line
;
402 if( source2
!= NULL
)
407 if( start
== -1 && end
== -1 )
411 end
= DEBUG_start_sourceline
;
416 start
= DEBUG_end_sourceline
;
420 else if( start
== -1 )
430 * Now call this function to do the dirty work.
432 rtn
= DEBUG_DisplaySource(sourcefile
, start
, end
);
434 if( sourcefile
!= (char *) &DEBUG_current_sourcefile
)
436 strcpy(DEBUG_current_sourcefile
, sourcefile
);
438 DEBUG_start_sourceline
= start
;
439 DEBUG_end_sourceline
= end
;
442 DBG_ADDR DEBUG_LastDisassemble
={0,0};
444 BOOL
DEBUG_DisassembleInstruction(DBG_ADDR
*addr
)
449 DEBUG_PrintAddress(addr
, DEBUG_CurrThread
->dbg_mode
, TRUE
);
450 DEBUG_Printf(DBG_CHN_MESG
, ": ");
451 if (!DEBUG_READ_MEM_VERBOSE((void*)DEBUG_ToLinear(addr
), &ch
, sizeof(ch
))) {
452 DEBUG_Printf(DBG_CHN_MESG
, "-- no code --");
455 DEBUG_Disasm(addr
, TRUE
);
457 DEBUG_Printf(DBG_CHN_MESG
,"\n");
462 DEBUG_Disassemble(const DBG_VALUE
*xstart
,const DBG_VALUE
*xend
,int offset
)
470 DEBUG_GrabAddress(&start
, TRUE
);
474 DEBUG_GrabAddress(&end
, TRUE
);
476 if (!xstart
&& !xend
) {
477 last
= DEBUG_LastDisassemble
;
478 if (!last
.seg
&& !last
.off
)
479 DEBUG_GetCurrentAddress( &last
);
481 for (i
=0;i
<offset
;i
++)
482 if (!DEBUG_DisassembleInstruction(&last
)) break;
483 DEBUG_LastDisassemble
= last
;
488 for (i
=0;i
<offset
;i
++)
489 if (!DEBUG_DisassembleInstruction(&last
)) break;
490 DEBUG_LastDisassemble
= last
;
493 while (last
.off
<= end
.addr
.off
)
494 if (!DEBUG_DisassembleInstruction(&last
)) break;
495 DEBUG_LastDisassemble
= last
;