3 * Written by Jan Roeloffzen
5 * - Initialization, translation and main loop
19 #include "log2lines.h"
25 static FILE *dbgIn
= NULL
;
26 static FILE *dbgOut
= NULL
;
27 static FILE *conIn
= NULL
;
28 static FILE *conOut
= NULL
;
29 static const char *kdbg_prompt
= KDBG_PROMPT
;
30 static const char *kdbg_cont
= KDBG_CONT
;
42 memset(&lastLine
, 0, sizeof(LINEINFO
));
46 log_file(FILE *outFile
, char *fileName
, int line
)
48 int i
= 0, min
= 0, max
= 0;
52 strcpy(s
, opt_SourcesPath
);
55 max
= line
+ opt_SrcPlus
;
56 if ((src
= fopen(s
, "r")))
58 min
= line
- opt_Source
;
59 min
= (min
< 0) ? 0 : min
;
60 while (i
< max
&& fgets(s
, LINESIZE
, src
))
65 log(outFile
, "| ----\n");
66 log(outFile
, "| %4.4d %s", i
+ 1, s
);
72 log(outFile
, "| S--- source has only %d lines! (check source/revision)\n", i
);
75 l2l_dbg(1, "Can't open: %s (check " SOURCES_ENV
")\n", s
);
79 logSource(FILE *outFile
)
81 log_file(outFile
, lastLine
.file1
, lastLine
.nr1
);
84 log(outFile
, "| ---- [%u] ----\n", lastLine
.nr2
);
85 log_file(outFile
, lastLine
.file2
, lastLine
.nr2
);
90 reportSource(FILE *outFile
)
101 reportSource(outFile
);
107 print_offset(void *data
, size_t offset
, char *toString
)
109 PSYMBOLFILE_HEADER RosSymHeader
= (PSYMBOLFILE_HEADER
)data
;
110 PROSSYM_ENTRY e
= NULL
;
111 PROSSYM_ENTRY e2
= NULL
;
112 int bFileOffsetChanged
= 0;
114 char *Strings
= (char *)data
+ RosSymHeader
->StringsOffset
;
117 e
= find_offset(data
, offset
);
120 e2
= find_offset(data
, offset
- 1);
131 /* replaced (transparantly), but updated stats */
136 strcpy(lastLine
.file1
, &Strings
[e
->FileOffset
]);
137 strcpy(lastLine
.func1
, &Strings
[e
->FunctionOffset
]);
138 lastLine
.nr1
= e
->SourceLine
;
139 sources_entry_create(&sources
, lastLine
.file1
, SVN_PREFIX
);
143 strcpy(lastLine
.file2
, &Strings
[e2
->FileOffset
]);
144 strcpy(lastLine
.func2
, &Strings
[e2
->FunctionOffset
]);
145 lastLine
.nr2
= e2
->SourceLine
;
146 sources_entry_create(&sources
, lastLine
.file2
, SVN_PREFIX
);
147 bFileOffsetChanged
= e
->FileOffset
!= e2
->FileOffset
;
148 if (e
->FileOffset
!= e2
->FileOffset
|| e
->FunctionOffset
!= e2
->FunctionOffset
)
152 * - "%.0s" displays nothing, but processes argument
153 * - bFileOffsetChanged implies always display 2nd SourceLine even if the same
154 * - also for FunctionOffset
157 if (bFileOffsetChanged
)
163 if (e
->SourceLine
!= e2
->SourceLine
|| bFileOffsetChanged
)
169 if (e
->FunctionOffset
!= e2
->FunctionOffset
|| bFileOffsetChanged
)
170 strcat(fmt
, "[%s])");
172 strcat(fmt
, "%.0s)");
175 { // put in toString if provided
176 snprintf(toString
, LINESIZE
, fmt
,
177 &Strings
[e
->FileOffset
],
178 &Strings
[e2
->FileOffset
],
179 (unsigned int)e
->SourceLine
,
180 (unsigned int)e2
->SourceLine
,
181 &Strings
[e
->FunctionOffset
],
182 &Strings
[e2
->FunctionOffset
]);
188 &Strings
[e
->FileOffset
],
189 &Strings
[e2
->FileOffset
],
190 (unsigned int)e
->SourceLine
,
191 (unsigned int)e2
->SourceLine
,
192 &Strings
[e
->FunctionOffset
],
193 &Strings
[e2
->FunctionOffset
]);
199 { // put in toString if provided
200 snprintf(toString
, LINESIZE
, "%s:%u (%s)",
201 &Strings
[e
->FileOffset
],
202 (unsigned int)e
->SourceLine
,
203 &Strings
[e
->FunctionOffset
]);
207 printf("%s:%u (%s)\n",
208 &Strings
[e
->FileOffset
],
209 (unsigned int)e
->SourceLine
,
210 &Strings
[e
->FunctionOffset
]);
219 process_data(const void *FileData
, size_t offset
, char *toString
)
223 PIMAGE_SECTION_HEADER PERosSymSectionHeader
= get_sectionheader((char *)FileData
);
224 if (!PERosSymSectionHeader
)
227 res
= print_offset((char *)FileData
+ PERosSymSectionHeader
->PointerToRawData
, offset
, toString
);
231 sprintf(toString
, "??:0");
234 l2l_dbg(1, "Offset not found: %x\n", (unsigned int)offset
);
235 summ
.offset_errors
++;
242 process_file(const char *file_name
, size_t offset
, char *toString
)
248 FileData
= load_file(file_name
, &FileSize
);
251 l2l_dbg(0, "An error occured loading '%s'\n", file_name
);
255 res
= process_data(FileData
, offset
, toString
);
262 translate_file(const char *cpath
, size_t offset
, char *toString
)
265 LIST_MEMBER
*pentry
= NULL
;
269 dpath
= path
= convert_path(cpath
);
273 // The path could be absolute:
274 if (get_ImageBase(path
, &base
))
276 pentry
= entry_lookup(&cache
, path
);
280 base
= pentry
->ImageBase
;
281 if (base
== INVALID_BASE
)
283 l2l_dbg(1, "No, or invalid base address: %s\n", path
);
289 l2l_dbg(1, "Not found in cache: %s\n", path
);
296 res
= process_file(path
, offset
, toString
);
304 translate_char(int c
, FILE *outFile
)
312 remove_mark(char *Line
)
314 if (Line
[1] == ' ' && Line
[2] == '<')
315 if (Line
[0] == '*' || Line
[0] == '?')
321 translate_line(FILE *outFile
, char *Line
, char *path
, char *LineOut
)
325 char *sep
, *tail
, *mark
, *s
;
333 s
= remove_mark(Line
);
336 /* Strip all lines added by this tool: */
338 if (sscanf(s
, "| %s", buf
) == 1)
339 if (buf
[0] == '0' || strcmp(buf
, "----") == 0 || strcmp(buf
, "L2L-") == 0 || strcmp(buf
, "S---") == 0 || strcmp(buf
, "R---") == 0 || atoi(buf
))
343 sep
= strchr(s
, ':');
347 cnt
= sscanf(s
, "<%s %x%c", path
, &offset
, &ch
);
350 if (cnt
== 3 && ch
== ' ')
352 tail
= strchr(s
, '>');
353 tail
= tail
? tail
- 1 : tail
;
354 if (tail
&& tail
[0] == ')' && tail
[1] == '>')
358 mark
= opt_mark
? "* " : "";
359 if (opt_redo
&& !(res
= translate_file(path
, offset
, LineOut
)))
361 log(outFile
, "%s<%s:%x (%s)>%s", mark
, path
, offset
, LineOut
, tail
);
366 log(outFile
, "%s<%s:%x>%s", mark
, path
, offset
, tail
);
372 mark
= opt_Mark
? "? " : "";
379 if (!opt_undo
|| opt_redo
)
381 if (cnt
== 3 && ch
== '>')
383 tail
= strchr(s
, '>') + 1;
384 if (!(res
= translate_file(path
, offset
, LineOut
)))
386 mark
= opt_mark
? "* " : "";
387 log(outFile
, "%s<%s:%x (%s)>%s", mark
, path
, offset
, LineOut
, tail
);
392 mark
= opt_Mark
? "? " : "";
402 *sep
= ':'; // restore because not translated
403 log(outFile
, "%s%s", mark
, s
);
405 memset(Line
, '\0', LINESIZE
); // flushed
409 translate_files(FILE *inFile
, FILE *outFile
)
411 char Line
[LINESIZE
+ 1];
412 char path
[LINESIZE
+ 1];
413 char LineOut
[LINESIZE
+ 1];
417 const char *pc
= kdbg_cont
;
418 const char *p
= kdbg_prompt
;
419 const char *p_eos
= p
+ sizeof(KDBG_PROMPT
) - 1; //end of string pos
421 memset(Line
, '\0', LINESIZE
+ 1);
424 while ((c
= fgetc(inFile
)) != EOF
)
428 ch
= (unsigned char)c
;
434 if ( strncmp(Line
, KDBG_DISCARD
, sizeof(KDBG_DISCARD
)-1) == 0 )
436 memset(Line
, '\0', LINESIZE
); // flushed
440 Line
[1] = handle_escape_cmd(outFile
, Line
);
441 if (Line
[1] != KDBG_ESC_CHAR
)
445 // kdbg prompt, so already echoed char by char
446 memset(Line
, '\0', LINESIZE
);
447 translate_char(c
, outFile
);
451 if (match_line(outFile
, Line
))
453 translate_line(outFile
, Line
, path
, LineOut
);
454 translate_char(c
, outFile
);
472 translate_line(outFile
, Line
, path
, LineOut
);
480 translate_line(outFile
, Line
, path
, LineOut
);
484 translate_line(outFile
, Line
, path
, LineOut
);
485 translate_char(c
, outFile
);
489 translate_char(c
, outFile
);
500 translate_char(c
, outFile
);
504 translate_line(outFile
, Line
, path
, LineOut
);
510 translate_line(outFile
, Line
, path
, LineOut
);
511 translate_char(c
, outFile
);
517 translate_char(c
, outFile
);
521 { // Line by line, slightly faster but less interactive
522 while (fgets(Line
, LINESIZE
, inFile
) != NULL
)
528 translate_line(outFile
, Line
, path
, LineOut
);
532 log(outFile
, "%s", Line
);
538 stat_print(outFile
, &summ
);
540 stat_print(logFile
, &summ
);
547 main(int argc
, const char **argv
)
558 memset(&cache
, 0, sizeof(LIST
));
559 memset(&sources
, 0, sizeof(LIST
));
563 optInit
= optionInit(argc
, argv
);
564 optCount
= optionParse(argc
, argv
);
566 if (optCount
< 0 || optInit
< 0)
574 if (check_directory(opt_force
))
580 create_cache(opt_force
, 0);
588 l2l_dbg(4, "Cache read complete\n");
590 if (set_LogFile(&logFile
))
595 l2l_dbg(4, "opt_logFile processed\n");
599 l2l_dbg(3, "Command line: \"%s\"\n",opt_Pipe
);
601 if (!(dbgIn
= POPEN(opt_Pipe
, "r")))
603 dbgIn
= stdin
; //restore
604 l2l_dbg(0, "Could not popen '%s' (%s)\n", opt_Pipe
, strerror(errno
));
609 l2l_dbg(4, "opt_Pipe processed\n");
612 { // translate {<exefile> <offset>}
614 const char *exefile
= NULL
;
615 const char *offset
= NULL
;
616 char Line
[LINESIZE
+ 1];
617 char PathBuffer
[LINESIZE
+ 1];
618 char LineOutBuffer
[LINESIZE
+ 1];
620 // TODO: Re-use one translate_files(), instead of repeated translate_line().
623 offset
= argv
[optCount
+ i
++];
624 if (isOffset(offset
))
628 l2l_dbg(2, "translating %s %s\n", exefile
, offset
);
630 snprintf(Line
, LINESIZE
, "<%s:%s>\n", exefile
, offset
);
631 translate_line(conOut
, Line
, PathBuffer
, LineOutBuffer
);
636 l2l_dbg(0, "<exefile> expected\n");
643 // Not an offset so must be an exefile:
649 { // translate logging from stdin
650 translate_files(dbgIn
, conOut
);
667 list_clear(&sources
);