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
37 #define PATH_MAX MAX_PATH
45 struct searchlist
* next
;
53 struct open_filelist
* next
;
56 unsigned int * linelist
;
59 static struct open_filelist
* ofiles
;
61 static struct searchlist
* listhead
;
62 static char DEBUG_current_sourcefile
[PATH_MAX
];
63 static int DEBUG_start_sourceline
= -1;
64 static int DEBUG_end_sourceline
= -1;
69 struct searchlist
* sl
;
71 DEBUG_Printf("Search list :\n");
72 for(sl
= listhead
; sl
; sl
= sl
->next
)
74 DEBUG_Printf("\t%s\n", sl
->path
);
80 DEBUG_AddPath(const char * path
)
82 struct searchlist
* sl
;
84 sl
= (struct searchlist
*) DBG_alloc(sizeof(struct searchlist
));
91 sl
->path
= DBG_strdup(path
);
98 struct searchlist
* sl
;
99 struct searchlist
* nxt
;
101 for(sl
= listhead
; sl
; sl
= nxt
)
111 static void* DEBUG_MapFile(const char* name
, HANDLE
* hMap
, unsigned* size
)
115 hFile
= CreateFile(name
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
116 OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
117 if (hFile
== INVALID_HANDLE_VALUE
) return (void*)-1;
118 if (size
!= NULL
&& (*size
= GetFileSize(hFile
, NULL
)) == -1) return (void*)-1;
119 *hMap
= CreateFileMapping(hFile
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
121 if (!*hMap
) return (void*)-1;
122 return MapViewOfFile(*hMap
, FILE_MAP_READ
, 0, 0, 0);
125 static void DEBUG_UnmapFile(void* addr
, HANDLE hMap
)
127 UnmapViewOfFile(addr
);
131 static struct open_filelist
* DEBUG_SearchOpenFile(const char* name
)
133 struct open_filelist
* ol
;
135 for (ol
= ofiles
; ol
; ol
= ol
->next
)
137 if (strcmp(ol
->path
, name
) == 0) break;
144 DEBUG_DisplaySource(char * sourcefile
, int start
, int end
)
148 struct open_filelist
* ol
;
150 char* basename
= NULL
;
153 struct searchlist
* sl
;
156 char tmppath
[PATH_MAX
];
159 * First see whether we have the file open already. If so, then
160 * use that, otherwise we have to try and open it.
162 ol
= DEBUG_SearchOpenFile(sourcefile
);
167 * Try again, stripping the path from the opened file.
169 basename
= strrchr(sourcefile
, '\\' );
171 basename
= strrchr(sourcefile
, '/' );
173 basename
= sourcefile
;
177 ol
= DEBUG_SearchOpenFile(basename
);
183 * Crapola. We need to try and open the file.
185 status
= GetFileAttributes(sourcefile
);
186 if ( status
!= INVALID_FILE_ATTRIBUTES
)
188 strcpy(tmppath
, sourcefile
);
190 else if ( (status
= GetFileAttributes(basename
)) != INVALID_FILE_ATTRIBUTES
)
192 strcpy(tmppath
, basename
);
196 for (sl
= listhead
; sl
; sl
= sl
->next
)
198 strcpy(tmppath
, sl
->path
);
199 if ( tmppath
[strlen(tmppath
)-1] != '/' && tmppath
[strlen(tmppath
)-1] != '\\' )
201 strcat(tmppath
, "/");
204 * Now append the base file name.
206 strcat(tmppath
, basename
);
208 status
= GetFileAttributes(tmppath
);
209 if ( status
!= INVALID_FILE_ATTRIBUTES
) break;
214 if (DEBUG_InteractiveP
)
218 * Still couldn't find it. Ask user for path to add.
220 snprintf(zbuf
, sizeof(zbuf
), "Enter path to file '%s': ", sourcefile
);
221 DEBUG_ReadLine(zbuf
, tmppath
, sizeof(tmppath
));
223 if ( tmppath
[strlen(tmppath
)-1] != '/' )
225 strcat(tmppath
, "/");
228 * Now append the base file name.
230 strcat(tmppath
, basename
);
232 status
= GetFileAttributes(tmppath
);
236 status
= INVALID_FILE_ATTRIBUTES
;
237 strcpy(tmppath
, sourcefile
);
240 if ( status
== INVALID_FILE_ATTRIBUTES
)
243 * OK, I guess the user doesn't really want to see it
246 ol
= (struct open_filelist
*) DBG_alloc(sizeof(*ol
));
247 ol
->path
= DBG_strdup(sourcefile
);
248 ol
->real_path
= NULL
;
253 DEBUG_Printf("Unable to open file %s\n", tmppath
);
259 * Create header for file.
261 ol
= (struct open_filelist
*) DBG_alloc(sizeof(*ol
));
262 ol
->path
= DBG_strdup(sourcefile
);
263 ol
->real_path
= DBG_strdup(tmppath
);
270 addr
= DEBUG_MapFile(tmppath
, &hMap
, &ol
->size
);
271 if ( addr
== (char *) -1 )
276 * Now build up the line number mapping table.
280 while (pnt
< addr
+ ol
->size
)
282 if ( *pnt
++ == '\n' )
289 ol
->linelist
= (unsigned int*) DBG_alloc( ol
->nlines
* sizeof(unsigned int) );
293 ol
->linelist
[nlines
++] = 0;
294 while(pnt
< addr
+ ol
->size
)
298 ol
->linelist
[nlines
++] = pnt
- addr
;
301 ol
->linelist
[nlines
++] = pnt
- addr
;
306 addr
= DEBUG_MapFile(ol
->real_path
, &hMap
, NULL
);
307 if ( addr
== (char *) -1 )
313 * All we need to do is to display the source lines here.
316 for (i
= start
- 1; i
<= end
- 1; i
++)
320 if (i
< 0 || i
>= ol
->nlines
- 1)
326 memset(&buffer
, 0, sizeof(buffer
));
327 if ( ol
->linelist
[i
+1] != ol
->linelist
[i
] )
329 memcpy(&buffer
, addr
+ ol
->linelist
[i
],
330 (ol
->linelist
[i
+1] - ol
->linelist
[i
]) - 1);
332 DEBUG_Printf("%d\t%s\n", i
+ 1, buffer
);
335 DEBUG_UnmapFile(addr
, hMap
);
340 DEBUG_List(struct list_id
* source1
, struct list_id
* source2
,
349 * We need to see what source file we need. Hopefully we only have
350 * one specified, otherwise we might as well punt.
354 && source1
->sourcefile
!= NULL
355 && source2
->sourcefile
!= NULL
356 && strcmp(source1
->sourcefile
, source2
->sourcefile
) != 0 )
358 DEBUG_Printf("Ambiguous source file specification.\n");
363 if( source1
!= NULL
&& source1
->sourcefile
!= NULL
)
365 sourcefile
= source1
->sourcefile
;
368 if( sourcefile
== NULL
370 && source2
->sourcefile
!= NULL
)
372 sourcefile
= source2
->sourcefile
;
375 if( sourcefile
== NULL
)
377 sourcefile
= (char *) &DEBUG_current_sourcefile
;
380 if( sourcefile
== NULL
)
382 DEBUG_Printf("No source file specified.\n");
387 * Now figure out the line number range to be listed.
392 if( source1
!= NULL
)
394 start
= source1
->line
;
397 if( source2
!= NULL
)
402 if( start
== -1 && end
== -1 )
406 end
= DEBUG_start_sourceline
;
411 start
= DEBUG_end_sourceline
;
415 else if( start
== -1 )
425 * Now call this function to do the dirty work.
427 rtn
= DEBUG_DisplaySource(sourcefile
, start
, end
);
429 if( sourcefile
!= (char *) &DEBUG_current_sourcefile
)
431 strcpy(DEBUG_current_sourcefile
, sourcefile
);
433 DEBUG_start_sourceline
= start
;
434 DEBUG_end_sourceline
= end
;
437 DBG_ADDR DEBUG_LastDisassemble
={0,0};
439 BOOL
DEBUG_DisassembleInstruction(DBG_ADDR
*addr
)
444 DEBUG_PrintAddress(addr
, DEBUG_CurrThread
->dbg_mode
, TRUE
);
446 if (!DEBUG_READ_MEM_VERBOSE((void*)DEBUG_ToLinear(addr
), &ch
, sizeof(ch
))) {
447 DEBUG_Printf("-- no code --");
450 DEBUG_Disasm(addr
, TRUE
);
457 DEBUG_Disassemble(const DBG_VALUE
*xstart
,const DBG_VALUE
*xend
,int offset
)
465 DEBUG_GrabAddress(&start
, TRUE
);
469 DEBUG_GrabAddress(&end
, TRUE
);
471 if (!xstart
&& !xend
) {
472 last
= DEBUG_LastDisassemble
;
473 if (!last
.seg
&& !last
.off
)
474 DEBUG_GetCurrentAddress( &last
);
476 for (i
=0;i
<offset
;i
++)
477 if (!DEBUG_DisassembleInstruction(&last
)) break;
478 DEBUG_LastDisassemble
= last
;
483 for (i
=0;i
<offset
;i
++)
484 if (!DEBUG_DisassembleInstruction(&last
)) break;
485 DEBUG_LastDisassemble
= last
;
488 while (last
.off
<= end
.addr
.off
)
489 if (!DEBUG_DisassembleInstruction(&last
)) break;
490 DEBUG_LastDisassemble
= last
;