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
;
43 memset(&lastLine
, 0, sizeof(LINEINFO
));
47 log_file(FILE *outFile
, char *fileName
, int line
)
49 int i
= 0, min
= 0, max
= 0;
53 strcpy(s
, opt_SourcesPath
);
56 max
= line
+ opt_SrcPlus
;
57 if ((src
= fopen(s
, "r")))
59 min
= line
- opt_Source
;
60 min
= (min
< 0) ? 0 : min
;
61 while (i
< max
&& fgets(s
, LINESIZE
, src
))
66 log(outFile
, "| ----\n");
67 log(outFile
, "| %4.4d %s", i
+ 1, s
);
73 log(outFile
, "| S--- source has only %d lines! (check source/revision)\n", i
);
76 l2l_dbg(1, "Can't open: %s (check " SOURCES_ENV
")\n", s
);
80 logSource(FILE *outFile
)
82 log_file(outFile
, lastLine
.file1
, lastLine
.nr1
);
85 log(outFile
, "| ---- [%u] ----\n", lastLine
.nr2
);
86 log_file(outFile
, lastLine
.file2
, lastLine
.nr2
);
91 reportSource(FILE *outFile
)
100 report(FILE *outFile
)
102 reportRevision(outFile
);
103 reportSource(outFile
);
109 print_offset(void *data
, size_t offset
, char *toString
)
111 PSYMBOLFILE_HEADER RosSymHeader
= (PSYMBOLFILE_HEADER
)data
;
112 PROSSYM_ENTRY e
= NULL
;
113 PROSSYM_ENTRY e2
= NULL
;
114 int bFileOffsetChanged
= 0;
116 char *Strings
= (char *)data
+ RosSymHeader
->StringsOffset
;
119 e
= find_offset(data
, offset
);
122 e2
= find_offset(data
, offset
- 1);
133 /* replaced (transparantly), but updated stats */
138 strcpy(lastLine
.file1
, &Strings
[e
->FileOffset
]);
139 strcpy(lastLine
.func1
, &Strings
[e
->FunctionOffset
]);
140 lastLine
.nr1
= e
->SourceLine
;
141 sources_entry_create(&sources
, lastLine
.file1
, SVN_PREFIX
);
145 strcpy(lastLine
.file2
, &Strings
[e2
->FileOffset
]);
146 strcpy(lastLine
.func2
, &Strings
[e2
->FunctionOffset
]);
147 lastLine
.nr2
= e2
->SourceLine
;
148 sources_entry_create(&sources
, lastLine
.file2
, SVN_PREFIX
);
149 bFileOffsetChanged
= e
->FileOffset
!= e2
->FileOffset
;
150 if (e
->FileOffset
!= e2
->FileOffset
|| e
->FunctionOffset
!= e2
->FunctionOffset
)
154 * - "%.0s" displays nothing, but processes argument
155 * - bFileOffsetChanged implies always display 2nd SourceLine even if the same
156 * - also for FunctionOffset
159 if (bFileOffsetChanged
)
165 if (e
->SourceLine
!= e2
->SourceLine
|| bFileOffsetChanged
)
171 if (e
->FunctionOffset
!= e2
->FunctionOffset
|| bFileOffsetChanged
)
172 strcat(fmt
, "[%s])");
174 strcat(fmt
, "%.0s)");
177 { // put in toString if provided
178 snprintf(toString
, LINESIZE
, fmt
,
179 &Strings
[e
->FileOffset
],
180 &Strings
[e2
->FileOffset
],
181 (unsigned int)e
->SourceLine
,
182 (unsigned int)e2
->SourceLine
,
183 &Strings
[e
->FunctionOffset
],
184 &Strings
[e2
->FunctionOffset
]);
190 &Strings
[e
->FileOffset
],
191 &Strings
[e2
->FileOffset
],
192 (unsigned int)e
->SourceLine
,
193 (unsigned int)e2
->SourceLine
,
194 &Strings
[e
->FunctionOffset
],
195 &Strings
[e2
->FunctionOffset
]);
201 { // put in toString if provided
202 snprintf(toString
, LINESIZE
, "%s:%u (%s)",
203 &Strings
[e
->FileOffset
],
204 (unsigned int)e
->SourceLine
,
205 &Strings
[e
->FunctionOffset
]);
209 printf("%s:%u (%s)\n",
210 &Strings
[e
->FileOffset
],
211 (unsigned int)e
->SourceLine
,
212 &Strings
[e
->FunctionOffset
]);
221 process_data(const void *FileData
, size_t offset
, char *toString
)
225 PIMAGE_SECTION_HEADER PERosSymSectionHeader
= get_sectionheader((char *)FileData
);
226 if (!PERosSymSectionHeader
)
229 res
= print_offset((char *)FileData
+ PERosSymSectionHeader
->PointerToRawData
, offset
, toString
);
233 sprintf(toString
, "??:0");
236 l2l_dbg(1, "Offset not found: %x\n", (unsigned int)offset
);
237 summ
.offset_errors
++;
244 process_file(const char *file_name
, size_t offset
, char *toString
)
250 FileData
= load_file(file_name
, &FileSize
);
253 l2l_dbg(0, "An error occured loading '%s'\n", file_name
);
257 res
= process_data(FileData
, offset
, toString
);
264 translate_file(const char *cpath
, size_t offset
, char *toString
)
267 LIST_MEMBER
*pentry
= NULL
;
271 dpath
= path
= convert_path(cpath
);
275 // The path could be absolute:
276 if (get_ImageBase(path
, &base
))
278 pentry
= entry_lookup(&cache
, path
);
282 base
= pentry
->ImageBase
;
283 if (base
== INVALID_BASE
)
285 l2l_dbg(1, "No, or invalid base address: %s\n", path
);
291 l2l_dbg(1, "Not found in cache: %s\n", path
);
298 res
= process_file(path
, offset
, toString
);
306 translate_char(int c
, FILE *outFile
)
314 remove_mark(char *Line
)
316 if (Line
[1] == ' ' && Line
[2] == '<')
317 if (Line
[0] == '*' || Line
[0] == '?')
323 translate_line(FILE *outFile
, char *Line
, char *path
, char *LineOut
)
327 char *sep
, *tail
, *mark
, *s
;
335 s
= remove_mark(Line
);
338 /* Strip all lines added by this tool: */
340 if (sscanf(s
, "| %s", buf
) == 1)
341 if (buf
[0] == '0' || strcmp(buf
, "----") == 0 || strcmp(buf
, "L2L-") == 0 || strcmp(buf
, "S---") == 0 || strcmp(buf
, "R---") == 0 || atoi(buf
))
345 sep
= strchr(s
, ':');
349 cnt
= sscanf(s
, "<%s %x%c", path
, &offset
, &ch
);
352 if (cnt
== 3 && ch
== ' ')
354 tail
= strchr(s
, '>');
355 tail
= tail
? tail
- 1 : tail
;
356 if (tail
&& tail
[0] == ')' && tail
[1] == '>')
360 mark
= opt_mark
? "* " : "";
361 if (opt_redo
&& !(res
= translate_file(path
, offset
, LineOut
)))
363 log(outFile
, "%s<%s:%x (%s)>%s", mark
, path
, offset
, LineOut
, tail
);
368 log(outFile
, "%s<%s:%x>%s", mark
, path
, offset
, tail
);
374 mark
= opt_Mark
? "? " : "";
381 if (!opt_undo
|| opt_redo
)
383 if (cnt
== 3 && ch
== '>')
385 tail
= strchr(s
, '>') + 1;
386 if (!(res
= translate_file(path
, offset
, LineOut
)))
388 mark
= opt_mark
? "* " : "";
389 log(outFile
, "%s<%s:%x (%s)>%s", mark
, path
, offset
, LineOut
, tail
);
394 mark
= opt_Mark
? "? " : "";
404 *sep
= ':'; // restore because not translated
405 log(outFile
, "%s%s", mark
, s
);
407 memset(Line
, '\0', LINESIZE
); // flushed
411 translate_files(FILE *inFile
, FILE *outFile
)
413 char *Line
= malloc(LINESIZE
+ 1);
414 char *path
= malloc(LINESIZE
+ 1);
415 char *LineOut
= malloc(LINESIZE
+ 1);
419 const char *pc
= kdbg_cont
;
420 const char *p
= kdbg_prompt
;
421 const char *p_eos
= p
+ sizeof(KDBG_PROMPT
) - 1; //end of string pos
423 if (Line
&& path
&& LineOut
)
425 memset(Line
, '\0', LINESIZE
+ 1);
428 while ((c
= fgetc(inFile
)) != EOF
)
432 ch
= (unsigned char)c
;
438 if ( strncmp(Line
, KDBG_DISCARD
, sizeof(KDBG_DISCARD
)-1) == 0 )
440 memset(Line
, '\0', LINESIZE
); // flushed
444 Line
[1] = handle_escape_cmd(outFile
, Line
, path
, LineOut
);
445 if (Line
[1] != KDBG_ESC_CHAR
)
449 // kdbg prompt, so already echoed char by char
450 memset(Line
, '\0', LINESIZE
);
451 translate_char(c
, outFile
);
455 if (match_line(outFile
, Line
))
457 translate_line(outFile
, Line
, path
, LineOut
);
458 translate_char(c
, outFile
);
476 translate_line(outFile
, Line
, path
, LineOut
);
484 translate_line(outFile
, Line
, path
, LineOut
);
488 translate_line(outFile
, Line
, path
, LineOut
);
489 translate_char(c
, outFile
);
493 translate_char(c
, outFile
);
504 translate_char(c
, outFile
);
508 translate_line(outFile
, Line
, path
, LineOut
);
514 translate_line(outFile
, Line
, path
, LineOut
);
515 translate_char(c
, outFile
);
521 translate_char(c
, outFile
);
525 { // Line by line, slightly faster but less interactive
526 while (fgets(Line
, LINESIZE
, inFile
) != NULL
)
532 translate_line(outFile
, Line
, path
, LineOut
);
536 log(outFile
, "%s", Line
);
541 if (opt_Revision
&& (strstr(opt_Revision
, "regscan") == opt_Revision
))
543 char *s
= strchr(opt_Revision
, ',');
547 revinfo
.range
= atoi(s
);
554 stat_print(outFile
, &summ
);
556 stat_print(logFile
, &summ
);
566 main(int argc
, const char **argv
)
577 memset(&cache
, 0, sizeof(LIST
));
578 memset(&sources
, 0, sizeof(LIST
));
580 memset(&revinfo
, 0, sizeof(REVINFO
));
583 optInit
= optionInit(argc
, argv
);
584 optCount
= optionParse(argc
, argv
);
586 if (optCount
< 0 || optInit
< 0)
593 if (opt_Revision
&& (strcmp(opt_Revision
, "update") == 0))
595 res
= updateSvnlog();
599 if (check_directory(opt_force
))
602 create_cache(opt_force
, 0);
607 l2l_dbg(4, "Cache read complete\n");
609 if (set_LogFile(&logFile
))
611 l2l_dbg(4, "opt_logFile processed\n");
615 l2l_dbg(3, "Command line: \"%s\"\n",opt_Pipe
);
617 if (!(dbgIn
= POPEN(opt_Pipe
, "r")))
619 dbgIn
= stdin
; //restore
620 l2l_dbg(0, "Could not popen '%s' (%s)\n", opt_Pipe
, strerror(errno
));
621 free(opt_Pipe
); opt_Pipe
= NULL
;
624 l2l_dbg(4, "opt_Pipe processed\n");
627 { // translate {<exefile> <offset>}
629 const char *exefile
= NULL
;
630 const char *offset
= NULL
;
631 char Line
[LINESIZE
+ 1];
636 offset
= argv
[optCount
+ i
++];
637 if (isOffset(offset
))
641 l2l_dbg(2, "translating %s %s\n", exefile
, offset
);
642 translate_file(exefile
, my_atoi(offset
), Line
);
643 printf("%s\n", Line
);
648 l2l_dbg(0, "<exefile> expected\n");
655 // Not an offset so must be an exefile:
661 { // translate logging from stdin
662 translate_files(dbgIn
, conOut
);