Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674/* * ReactOS log2lines * Written by Jan Roeloffzen * * - Initialization, translation and main loop */
#include <errno.h>#include <stdio.h>#include <string.h>#include <stdlib.h>
#include "util.h"#include "version.h"#include "compat.h"#include "options.h"#include "image.h"#include "cache.h"#include "log2lines.h"#include "help.h"#include "cmd.h"#include "match.h"
static FILE *dbgIn = NULL;static FILE *dbgOut = NULL;static FILE *conIn = NULL;static FILE *conOut = NULL;static const char *kdbg_prompt = KDBG_PROMPT;static const char *kdbg_cont = KDBG_CONT;
LIST sources;LINEINFO lastLine;FILE *logFile = NULL;LIST cache;SUMM summ;
static voidclearLastLine(void){ memset(&lastLine, 0, sizeof(LINEINFO));}
static voidlog_file(FILE *outFile, char *fileName, int line){ int i = 0, min = 0, max = 0; char s[LINESIZE]; FILE *src;
strcpy(s, opt_SourcesPath); strcat(s, fileName);
max = line + opt_SrcPlus; if ((src = fopen(s, "r"))) { min = line - opt_Source; min = (min < 0) ? 0 : min; while (i < max && fgets(s, LINESIZE, src)) { if (i >= min) { if (i == line) log(outFile, "| ----\n"); log(outFile, "| %4.4d %s", i + 1, s); } i++; } fclose(src); if ( i < min ) log(outFile, "| S--- source has only %d lines! (check source/revision)\n", i); } else l2l_dbg(1, "Can't open: %s (check " SOURCES_ENV ")\n", s);}
static voidlogSource(FILE *outFile){ log_file(outFile, lastLine.file1, lastLine.nr1); if (lastLine.nr2) { log(outFile, "| ---- [%u] ----\n", lastLine.nr2); log_file(outFile, lastLine.file2, lastLine.nr2); }}
static voidreportSource(FILE *outFile){ if (!opt_Source) return; if (lastLine.valid) logSource(outFile);}
static voidreport(FILE *outFile){ reportSource(outFile); clearLastLine();}
static intprint_offset(void *data, size_t offset, char *toString){ PSYMBOLFILE_HEADER RosSymHeader = (PSYMBOLFILE_HEADER)data; PROSSYM_ENTRY e = NULL; PROSSYM_ENTRY e2 = NULL; int bFileOffsetChanged = 0; char fmt[LINESIZE]; char *Strings = (char *)data + RosSymHeader->StringsOffset;
fmt[0] = '\0'; e = find_offset(data, offset); if (opt_twice) { e2 = find_offset(data, offset - 1);
if (e == e2) e2 = NULL; else summ.diff++;
if (opt_Twice && e2) { e = e2; e2 = NULL; /* replaced (transparantly), but updated stats */ } } if (e || e2) { strcpy(lastLine.file1, &Strings[e->FileOffset]); strcpy(lastLine.func1, &Strings[e->FunctionOffset]); lastLine.nr1 = e->SourceLine; sources_entry_create(&sources, lastLine.file1, SVN_PREFIX); lastLine.valid = 1; if (e2) { strcpy(lastLine.file2, &Strings[e2->FileOffset]); strcpy(lastLine.func2, &Strings[e2->FunctionOffset]); lastLine.nr2 = e2->SourceLine; sources_entry_create(&sources, lastLine.file2, SVN_PREFIX); bFileOffsetChanged = e->FileOffset != e2->FileOffset; if (e->FileOffset != e2->FileOffset || e->FunctionOffset != e2->FunctionOffset) summ.majordiff++;
/* * - "%.0s" displays nothing, but processes argument * - bFileOffsetChanged implies always display 2nd SourceLine even if the same * - also for FunctionOffset */ strcat(fmt, "%s"); if (bFileOffsetChanged) strcat(fmt, "[%s]"); else strcat(fmt, "%.0s");
strcat(fmt, ":%u"); if (e->SourceLine != e2->SourceLine || bFileOffsetChanged) strcat(fmt, "[%u]"); else strcat(fmt, "%.0u");
strcat(fmt, " (%s"); if (e->FunctionOffset != e2->FunctionOffset || bFileOffsetChanged) strcat(fmt, "[%s])"); else strcat(fmt, "%.0s)");
if (toString) { // put in toString if provided snprintf(toString, LINESIZE, fmt, &Strings[e->FileOffset], &Strings[e2->FileOffset], (unsigned int)e->SourceLine, (unsigned int)e2->SourceLine, &Strings[e->FunctionOffset], &Strings[e2->FunctionOffset]); } else { strcat(fmt, "\n"); printf(fmt, &Strings[e->FileOffset], &Strings[e2->FileOffset], (unsigned int)e->SourceLine, (unsigned int)e2->SourceLine, &Strings[e->FunctionOffset], &Strings[e2->FunctionOffset]); } } else { if (toString) { // put in toString if provided snprintf(toString, LINESIZE, "%s:%u (%s)", &Strings[e->FileOffset], (unsigned int)e->SourceLine, &Strings[e->FunctionOffset]); } else { printf("%s:%u (%s)\n", &Strings[e->FileOffset], (unsigned int)e->SourceLine, &Strings[e->FunctionOffset]); } } return 0; } return 1;}
static intprocess_data(const void *FileData, size_t offset, char *toString){ int res;
PIMAGE_SECTION_HEADER PERosSymSectionHeader = get_sectionheader((char *)FileData); if (!PERosSymSectionHeader) return 2;
res = print_offset((char *)FileData + PERosSymSectionHeader->PointerToRawData, offset, toString); if (res) { if (toString) sprintf(toString, "??:0"); else printf("??:0"); l2l_dbg(1, "Offset not found: %x\n", (unsigned int)offset); summ.offset_errors++; }
return res;}
static intprocess_file(const char *file_name, size_t offset, char *toString){ void *FileData; size_t FileSize; int res = 1;
FileData = load_file(file_name, &FileSize); if (!FileData) { l2l_dbg(0, "An error occured loading '%s'\n", file_name); } else { res = process_data(FileData, offset, toString); free(FileData); } return res;}
static inttranslate_file(const char *cpath, size_t offset, char *toString){ size_t base = 0; LIST_MEMBER *pentry = NULL; int res = 0; char *path, *dpath;
dpath = path = convert_path(cpath); if (!path) return 1;
// The path could be absolute: if (get_ImageBase(path, &base)) { pentry = entry_lookup(&cache, path); if (pentry) { path = pentry->path; base = pentry->ImageBase; if (base == INVALID_BASE) { l2l_dbg(1, "No, or invalid base address: %s\n", path); res = 2; } } else { l2l_dbg(1, "Not found in cache: %s\n", path); res = 3; } }
if (!res) { res = process_file(path, offset, toString); }
free(dpath); return res;}
static voidtranslate_char(int c, FILE *outFile){ fputc(c, outFile); if (logFile) fputc(c, logFile);}
static char *remove_mark(char *Line){ if (Line[1] == ' ' && Line[2] == '<') if (Line[0] == '*' || Line[0] == '?') return Line + 2; return Line;}
static voidtranslate_line(FILE *outFile, char *Line, char *path, char *LineOut){ unsigned int offset; int cnt, res; char *sep, *tail, *mark, *s; unsigned char ch;
if (!*Line) return;
res = 1; mark = ""; s = remove_mark(Line); if (opt_undo) { /* Strip all lines added by this tool: */ char buf[NAMESIZE]; if (sscanf(s, "| %s", buf) == 1) if (buf[0] == '0' || strcmp(buf, "----") == 0 || strcmp(buf, "L2L-") == 0 || strcmp(buf, "S---") == 0 || strcmp(buf, "R---") == 0 || atoi(buf)) res = 0; }
sep = strchr(s, ':'); if (sep) { *sep = ' '; cnt = sscanf(s, "<%s %x%c", path, &offset, &ch); if (opt_undo) { if (cnt == 3 && ch == ' ') { tail = strchr(s, '>'); tail = tail ? tail - 1 : tail; if (tail && tail[0] == ')' && tail[1] == '>') { res = 0; tail += 2; mark = opt_mark ? "* " : ""; if (opt_redo && !(res = translate_file(path, offset, LineOut))) { log(outFile, "%s<%s:%x (%s)>%s", mark, path, offset, LineOut, tail); summ.redo++; } else { log(outFile, "%s<%s:%x>%s", mark, path, offset, tail); summ.undo++; } } else { mark = opt_Mark ? "? " : ""; summ.skipped++; } summ.total++; } }
if (!opt_undo || opt_redo) { if (cnt == 3 && ch == '>') { tail = strchr(s, '>') + 1; if (!(res = translate_file(path, offset, LineOut))) { mark = opt_mark ? "* " : ""; log(outFile, "%s<%s:%x (%s)>%s", mark, path, offset, LineOut, tail); summ.translated++; } else { mark = opt_Mark ? "? " : ""; summ.skipped++; } summ.total++; } } } if (res) { if (sep) *sep = ':'; // restore because not translated log(outFile, "%s%s", mark, s); } memset(Line, '\0', LINESIZE); // flushed}
static inttranslate_files(FILE *inFile, FILE *outFile){ char Line[LINESIZE + 1]; char path[LINESIZE + 1]; char LineOut[LINESIZE + 1]; int c; unsigned char ch; int i = 0; const char *pc = kdbg_cont; const char *p = kdbg_prompt; const char *p_eos = p + sizeof(KDBG_PROMPT) - 1; //end of string pos
memset(Line, '\0', LINESIZE + 1); if (opt_console) { while ((c = fgetc(inFile)) != EOF) { if (opt_quit)break;
ch = (unsigned char)c; if (!opt_raw) { switch (ch) { case '\n': if ( strncmp(Line, KDBG_DISCARD, sizeof(KDBG_DISCARD)-1) == 0 ) { memset(Line, '\0', LINESIZE); // flushed } else { Line[1] = handle_escape_cmd(outFile, Line); if (Line[1] != KDBG_ESC_CHAR) { if (p == p_eos) { // kdbg prompt, so already echoed char by char memset(Line, '\0', LINESIZE); translate_char(c, outFile); } else { if (match_line(outFile, Line)) { translate_line(outFile, Line, path, LineOut); translate_char(c, outFile); report(outFile); } } } } i = 0; p = kdbg_prompt; pc = kdbg_cont; break; case '<': i = 0; Line[i++] = ch; break; case '>': if (ch == *p) { p = p_eos; translate_line(outFile, Line, path, LineOut); }
if (p != p_eos) { if (i < LINESIZE) { Line[i++] = ch; translate_line(outFile, Line, path, LineOut); } else { translate_line(outFile, Line, path, LineOut); translate_char(c, outFile); } } else translate_char(c, outFile); i = 0; break; default: if (ch == *p)p++; if (ch == *pc)pc++; if (i < LINESIZE) { Line[i++] = ch; if (p == p_eos) { translate_char(c, outFile); } else if (!*pc) { translate_line(outFile, Line, path, LineOut); i = 0; } } else { translate_line(outFile, Line, path, LineOut); translate_char(c, outFile); i = 0; } } } else translate_char(c, outFile); } } else { // Line by line, slightly faster but less interactive while (fgets(Line, LINESIZE, inFile) != NULL) { if (opt_quit)break;
if (!opt_raw) { translate_line(outFile, Line, path, LineOut); report(outFile); } else log(outFile, "%s", Line); } }
if (opt_stats) { stat_print(outFile, &summ); if (logFile) stat_print(logFile, &summ); } return 0;}
intmain(int argc, const char **argv){ int res = 0; int optInit = 0; int optCount = 0;
dbgIn = stdin; conOut = stdout; (void)conIn; (void)dbgOut;
memset(&cache, 0, sizeof(LIST)); memset(&sources, 0, sizeof(LIST)); stat_clear(&summ); clearLastLine();
optInit = optionInit(argc, argv); optCount = optionParse(argc, argv);
if (optCount < 0 || optInit < 0) { res = optCount; goto cleanup; }
argc -= optCount;
if (check_directory(opt_force)) { res = 3; goto cleanup; }
create_cache(opt_force, 0); if (opt_exit) { res = 0; goto cleanup; }
read_cache(); l2l_dbg(4, "Cache read complete\n");
if (set_LogFile(&logFile)) { res = 2; goto cleanup; } l2l_dbg(4, "opt_logFile processed\n");
if (opt_Pipe) { l2l_dbg(3, "Command line: \"%s\"\n",opt_Pipe);
if (!(dbgIn = POPEN(opt_Pipe, "r"))) { dbgIn = stdin; //restore l2l_dbg(0, "Could not popen '%s' (%s)\n", opt_Pipe, strerror(errno)); free(opt_Pipe); opt_Pipe = NULL; } } l2l_dbg(4, "opt_Pipe processed\n");
if (argc > 1) { // translate {<exefile> <offset>} int i = 1; const char *exefile = NULL; const char *offset = NULL; char Line[LINESIZE + 1]; char PathBuffer[LINESIZE + 1]; char LineOutBuffer[LINESIZE + 1];
// TODO: Re-use one translate_files(), instead of repeated translate_line(). while (i < argc) { offset = argv[optCount + i++]; if (isOffset(offset)) { if (exefile) { l2l_dbg(2, "translating %s %s\n", exefile, offset);
snprintf(Line, LINESIZE, "<%s:%s>\n", exefile, offset); translate_line(conOut, Line, PathBuffer, LineOutBuffer); report(conOut); } else { l2l_dbg(0, "<exefile> expected\n"); res = 3; break; } } else { // Not an offset so must be an exefile: exefile = offset; } } } else { // translate logging from stdin translate_files(dbgIn, conOut); }
if (logFile) fclose(logFile);
if (opt_Pipe) PCLOSE(dbgIn);
cleanup: // See optionInit(). if (opt_Pipe) { free(opt_Pipe); opt_Pipe = NULL; }
list_clear(&sources); list_clear(&cache);
return res;}
/* EOF */