diff --git a/reactos/tools/log2lines/cache.c b/reactos/tools/log2lines/cache.c index fd5bcc2c303..d8faa8d9537 100644 --- a/reactos/tools/log2lines/cache.c +++ b/reactos/tools/log2lines/cache.c @@ -4,6 +4,7 @@ * * - Image directory caching */ + #include #include #include @@ -65,6 +66,14 @@ unpack_iso(char *dir, char *iso) return res; } +int +cleanable(char *path) +{ + if (strcmp(basename(path),DEF_OPT_DIR) == 0) + return 1; + return 0; +} + int check_directory(int force) { @@ -135,7 +144,10 @@ check_directory(int force) cache_name = malloc(MAX_PATH); tmp_name = malloc(MAX_PATH); strcpy(cache_name, opt_dir); - strcat(cache_name, PATH_STR CACHEFILE); + if (cleanable(opt_dir)) + strcat(cache_name, ALT_PATH_STR CACHEFILE); + else + strcat(cache_name, PATH_STR CACHEFILE); strcpy(tmp_name, cache_name); strcat(tmp_name, "~"); return 0; @@ -271,4 +283,4 @@ create_cache(int force, int skipImageBase) return 0; } - +/* EOF */ diff --git a/reactos/tools/log2lines/cache.h b/reactos/tools/log2lines/cache.h index e34290fabae..0acdd4c0f68 100644 --- a/reactos/tools/log2lines/cache.h +++ b/reactos/tools/log2lines/cache.h @@ -10,5 +10,6 @@ int check_directory(int force); int read_cache(void); int create_cache(int force, int skipImageBase); +int cleanable(char *path); /* EOF */ diff --git a/reactos/tools/log2lines/cmd.c b/reactos/tools/log2lines/cmd.c index 72877dcb822..ca7afaa8749 100644 --- a/reactos/tools/log2lines/cmd.c +++ b/reactos/tools/log2lines/cmd.c @@ -4,6 +4,7 @@ * * - Cli for escape commands */ + #include #include #include @@ -17,7 +18,7 @@ /* When you edit the cmd line and/or use the history instead of just typing, * a bunch of editing BS and space characters * is inserted, so the string looks right on the console but still - * starts with the original string: + * contains the original string, plus other garbage: */ static char *backSpaceEdit(char *s) @@ -142,6 +143,39 @@ handle_switch_pstr(FILE *outFile, char **psw, char *arg, char *desc) return changed; } +static int +handle_address_cmd(FILE *outFile, char *arg) +{ + PLIST_MEMBER plm; + char Image[NAMESIZE]; + DWORD Offset; + int cnt; + char *s; + + if(( s = strchr(arg, ':') )) + { + *s = ' '; + if ( (cnt = sscanf(arg,"%20s %lx", Image, &Offset)) == 2) + { + if (( plm = entry_lookup(&cache, Image) )) + { + if (plm->RelBase != INVALID_BASE) + esclog(outFile, "Address: 0x%lx\n", plm->RelBase + Offset) + else + esclog(outFile, "Relocated base missing for '%s' ('mod' will update)\n", Image); + } + else + esclog(outFile, "Image '%s' not found\n", Image); + } + else + esclog(outFile, "usage: `a :\n"); + } + else + esclog(outFile, "':' expected\n"); + + return 1; +} + char handle_escape_cmd(FILE *outFile, char *Line, char *path, char *LineOut) { @@ -177,12 +211,15 @@ handle_escape_cmd(FILE *outFile, char *Line, char *path, char *LineOut) opt_cli = 1; switch (cmd) { + case 'a': + handle_address_cmd(outFile, arg); + break; case 'h': usage(1); break; case 'b': if (handle_switch(outFile, &opt_buffered, arg, "-b Logfile buffering")) - set_LogFile(logFile); //re-open same logfile + set_LogFile(&logFile); //re-open same logfile break; case 'c': handle_switch(outFile, &opt_console, NULL, "-c Console option"); @@ -191,8 +228,18 @@ handle_escape_cmd(FILE *outFile, char *Line, char *path, char *LineOut) handle_switch_str(outFile, opt_dir, NULL, "-d Directory option"); break; case 'l': - if (handle_switch_str(outFile, opt_logFile, arg, "-l logfile")) - set_LogFile(logFile); //open new logfile + if (handle_switch_str(outFile, opt_logFile, arg, "-l logfile") || (strcmp(opt_mod,"a")!=0)) + { + opt_mod = "a"; + set_LogFile(&logFile); //open new logfile + } + break; + case 'L': + if (handle_switch_str(outFile, opt_logFile, arg, "-L logfile") || (strcmp(opt_mod,"w")!=0)) + { + opt_mod = "w"; + set_LogFile(&logFile); //open new logfile + } break; case 'm': handle_switch(outFile, &opt_Mark, arg, "-m mark (*)"); @@ -212,8 +259,10 @@ handle_escape_cmd(FILE *outFile, char *Line, char *path, char *LineOut) break; case 'R': changed = handle_switch_pstr(outFile, &opt_Revision, arg, NULL); + opt_Revision_check = 0; if (opt_Revision) { + opt_Revision_check = 1; if (strstr(opt_Revision, "check") == opt_Revision) { esclog(outFile, "-R is \"%s\" (%s)\n", opt_Revision, changed ? "changed":"unchanged"); @@ -253,6 +302,7 @@ handle_escape_cmd(FILE *outFile, char *Line, char *path, char *LineOut) { handle_switch(outFile, &opt_undo, "1", "-u Undo"); handle_switch(outFile, &opt_redo, "1", "-U Undo and reprocess"); + opt_Revision_check = 1; } esclog(outFile, "-S Sources option is %d+%d,\"%s\"\n", opt_Source, opt_SrcPlus, opt_SourcesPath); esclog(outFile, "(Setting source tree not implemented)\n"); @@ -289,3 +339,5 @@ handle_escape_cmd(FILE *outFile, char *Line, char *path, char *LineOut) return KDBG_ESC_CHAR; //handled escaped command } + +/* EOF */ diff --git a/reactos/tools/log2lines/config.h b/reactos/tools/log2lines/config.h index d39c646a3d9..d1c73898e94 100644 --- a/reactos/tools/log2lines/config.h +++ b/reactos/tools/log2lines/config.h @@ -26,6 +26,11 @@ "%s x -y -r %s" PATH_STR "reactos" PATH_STR "reactos.cab -o%s" \ PATH_STR "reactos" PATH_STR "reactos > " DEV_NULL +/* When we can't use a normal path, because it gets cleaned, + * fallback to name mangling: + */ +#define ALT_PATH_STR "#" + #define LINESIZE 1024 #define NAMESIZE 80 diff --git a/reactos/tools/log2lines/help.c b/reactos/tools/log2lines/help.c index 37e6bf400f8..c036d4857c7 100644 --- a/reactos/tools/log2lines/help.c +++ b/reactos/tools/log2lines/help.c @@ -4,6 +4,7 @@ * * - Help text and functions */ + #include #include "version.h" @@ -51,6 +52,9 @@ char *verboseUsage = " -l \n" " : Append copy to specified logFile.\n" " Default: no logFile\n\n" +" -L \n" +" : (Over)write copy to specified logFile.\n" +" Default: no logFile\n\n" " -m Prefix (mark) each translated line with '* '.\n\n" " -M Prefix (mark) each NOT translated line with '? '.\n" " ( Only for lines of the form: )\n\n" @@ -112,7 +116,7 @@ char *verboseUsage = " For a reliable result, these sources should be up to date with\n" " the tested revision (or try '-R check').\n" " Can be combined with -tTR.\n" -" Implies -U (For retrieving source info).\n\n" +" Implies -U (For retrieving source info) and -R check.\n\n" " -t Translate twice. The address itself and for (address-1).\n" " Show extra filename, func and linenumber between [..] if they differ\n" " So if only the linenumbers differ, then only show the extra\n" @@ -139,7 +143,10 @@ char *verboseUsage = " Options accepting a string as argument can be cleared by the value '" KDBG_ESC_OFF "'.\n" " Some ClI commands are read only or not (entirely) implemented.\n" " If no value is provided, the current one is printed.\n" -" There are only a few extra ClI commands or with different behaviour:\n" +" There are a few extra ClI commands or with different behaviour:\n" +" - `a ::\n" +" - Outputs absolute address e.g. for setting breakpoints.\n" +" - Do a 'mod' first to retrieve relocation info.\n" " - `h : shows this helptext (without exiting)\n" " - `q : quits log2lines\n" " - `R regscan : the output is printed immediately (do a 'bt' first)\n" @@ -233,7 +240,14 @@ char *verboseUsage = " | L2L- -l logfile is \"new.log\" (changed)\n" " kdb:> `l off\n" " | L2L- -l logfile is "" (changed)\n" -" kdb:>\n" +" kdb:>\n\n" +" Set a breakpoint with help of 'mod' and '`a':\n" +" \n" +" kdb:> mod (for kernel tracing usually only needed once)\n" +" -- mod output with reloc info\n" +" kdb:> `a msi.dll:2e35d\n" +" | L2L- Address: 0x00096ca0\n" +" kdb:> bpx 0x00096ca0\n\n" "\n"; void @@ -246,3 +260,5 @@ usage(int verbose) else fprintf(stderr, "Try log2lines -h\n"); } + +/* EOF */ diff --git a/reactos/tools/log2lines/image.c b/reactos/tools/log2lines/image.c index f94abcb59c8..bae302b8d51 100644 --- a/reactos/tools/log2lines/image.c +++ b/reactos/tools/log2lines/image.c @@ -4,11 +4,12 @@ * * - Image functions for symbol info */ -#include + #include #include #include +#include "compat.h" #include "util.h" #include "options.h" #include "log2lines.h" @@ -163,3 +164,5 @@ get_ImageBase(char *fname, size_t *ImageBase) fclose(fr); return 0; } + +/* EOF */ diff --git a/reactos/tools/log2lines/list.c b/reactos/tools/log2lines/list.c index 4491d079252..3fdd22b564d 100644 --- a/reactos/tools/log2lines/list.c +++ b/reactos/tools/log2lines/list.c @@ -9,6 +9,7 @@ #include #include +#include "config.h" #include "compat.h" #include "list.h" #include "util.h" @@ -162,6 +163,8 @@ cache_entry_create(char *Line) l2l_dbg(1, "ImageBase field missing\n"); return entry_delete(pentry); } + pentry->RelBase = INVALID_BASE; + pentry->Size = 0; return pentry; } @@ -212,3 +215,5 @@ sources_entry_create(PLIST list, char *path, char *prefix) return pentry; } + +/* EOF */ diff --git a/reactos/tools/log2lines/list.h b/reactos/tools/log2lines/list.h index 4406a41be8f..fa426d4c0c0 100644 --- a/reactos/tools/log2lines/list.h +++ b/reactos/tools/log2lines/list.h @@ -6,14 +6,16 @@ typedef struct entry_struct char *name; char *path; size_t ImageBase; + size_t RelBase; + size_t Size; struct entry_struct *pnext; -} LIST_MEMBER,*PLIST_MEMBER; +} LIST_MEMBER, *PLIST_MEMBER; typedef struct list_struct { PLIST_MEMBER phead; PLIST_MEMBER ptail; -} LIST,*PLIST; +} LIST, *PLIST; PLIST_MEMBER entry_lookup(PLIST list, char *name); PLIST_MEMBER entry_delete(PLIST_MEMBER pentry); diff --git a/reactos/tools/log2lines/log2lines.c b/reactos/tools/log2lines/log2lines.c index 1ad94f2fb0e..c00cfd378b5 100644 --- a/reactos/tools/log2lines/log2lines.c +++ b/reactos/tools/log2lines/log2lines.c @@ -19,10 +19,13 @@ #include "log2lines.h" #include "help.h" #include "cmd.h" +#include "match.h" -static FILE *stdIn = NULL; -static FILE *stdOut = NULL; +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; @@ -443,15 +446,18 @@ translate_files(FILE *inFile, FILE *outFile) { if (p == p_eos) { - //kdbg prompt, so already echoed char by char + // kdbg prompt, so already echoed char by char memset(Line, '\0', LINESIZE); translate_char(c, outFile); } else { - translate_line(outFile, Line, path, LineOut); - translate_char(c, outFile); - report(outFile); + if (match_line(outFile, Line)) + { + translate_line(outFile, Line, path, LineOut); + translate_char(c, outFile); + report(outFile); + } } } } @@ -562,8 +568,10 @@ main(int argc, const char **argv) int res = 0; int optCount = 0; - stdIn = stdin; - stdOut = stdout; + dbgIn = stdin; + conOut = stdout; + (void)conIn; + (void)dbgOut; memset(&cache, 0, sizeof(LIST)); memset(&sources, 0, sizeof(LIST)); @@ -596,7 +604,7 @@ main(int argc, const char **argv) read_cache(); l2l_dbg(4, "Cache read complete\n"); - if (set_LogFile(logFile)) + if (set_LogFile(&logFile)) return 2; l2l_dbg(4, "opt_logFile processed\n"); @@ -604,9 +612,9 @@ main(int argc, const char **argv) { l2l_dbg(3, "Command line: \"%s\"\n",opt_Pipe); - if (!(stdIn = POPEN(opt_Pipe, "r"))) + if (!(dbgIn = POPEN(opt_Pipe, "r"))) { - stdIn = stdin; //restore + dbgIn = stdin; //restore l2l_dbg(0, "Could not popen '%s' (%s)\n", opt_Pipe, strerror(errno)); free(opt_Pipe); opt_Pipe = NULL; } @@ -631,7 +639,7 @@ main(int argc, const char **argv) l2l_dbg(2, "translating %s %s\n", exefile, offset); translate_file(exefile, my_atoi(offset), Line); printf("%s\n", Line); - report(stdOut); + report(conOut); } else { @@ -649,14 +657,16 @@ main(int argc, const char **argv) } else { // translate logging from stdin - translate_files(stdIn, stdOut); + translate_files(dbgIn, conOut); } if (logFile) fclose(logFile); if (opt_Pipe) - PCLOSE(stdIn); + PCLOSE(dbgIn); return res; } + +/* EOF */ diff --git a/reactos/tools/log2lines/log2lines.mak b/reactos/tools/log2lines/log2lines.mak index 358fd83d4e8..d19d6c09a9a 100644 --- a/reactos/tools/log2lines/log2lines.mak +++ b/reactos/tools/log2lines/log2lines.mak @@ -31,6 +31,7 @@ LOG2LINES_SOURCES = \ $(LOG2LINES_BASE_)stat.c \ $(LOG2LINES_BASE_)revision.c \ $(LOG2LINES_BASE_)cmd.c \ + $(LOG2LINES_BASE_)match.c \ $(LOG2LINES_BASE_)log2lines.c \ $(RSYM_BASE_)rsym_common.c @@ -88,6 +89,10 @@ $(LOG2LINES_INT_)cmd.o: $(LOG2LINES_BASE_)cmd.c | $(LOG2LINES_INT) $(ECHO_HOSTCC) ${host_gcc} $(LOG2LINES_HOST_CFLAGS) -c $< -o $@ +$(LOG2LINES_INT_)match.o: $(LOG2LINES_BASE_)match.c | $(LOG2LINES_INT) + $(ECHO_HOSTCC) + ${host_gcc} $(LOG2LINES_HOST_CFLAGS) -c $< -o $@ + .PHONY: log2lines_clean log2lines_clean: -@$(rm) $(LOG2LINES_TARGET) $(LOG2LINES_OBJECTS) 2>$(NUL) diff --git a/reactos/tools/log2lines/match.c b/reactos/tools/log2lines/match.c new file mode 100644 index 00000000000..256a8b71902 --- /dev/null +++ b/reactos/tools/log2lines/match.c @@ -0,0 +1,91 @@ +/* + * ReactOS log2lines + * Written by Jan Roeloffzen + * + * - Custom match routines + */ + +#include + +#include "config.h" +#include "log2lines.h" +#include "match.h" + +// break pattern: show source+line +static int match_break(FILE *outFile, char *Line, int processed) +{ + static int state = 0; + + if ( processed ) return processed; + switch (state) + { + case 1: + state = 0; + break; + default: + state = 0; + } + return 1; +} +// "mod" command: update relocated addresses +static int match_mod(FILE *outFile, char *Line, int processed) +{ + static int state = 0; + char Image[NAMESIZE]; + DWORD Base; + DWORD Size; + PLIST_MEMBER plm; + + int cnt; + + if ( processed ) return processed; + if ( (cnt = sscanf(Line," Base Size %5s", Image)) == 1 ) + { + l2l_dbg(1, "Module relocate list:\n"); + state = 1; + return 0; + } + switch (state) + { + case 1: + if ( (cnt = sscanf(Line,"%lx %lx %20s", &Base, &Size, Image)) == 3 ) + { + if (( plm = entry_lookup(&cache, Image) )) + { + plm->RelBase = Base; + plm->Size = Size; + l2l_dbg(1, "Relocated: %s %08x -> %08x\n", Image, plm->ImageBase, plm->RelBase); + } + return 0; + } + else + { + state = 0; + } + break; + default: + state = 0; + } + return 1; +} + +int match_line(FILE *outFile, char *Line) +{ + int processed = 1; + + if ( *Line == '\n' || *Line == '\0' ) + return 1; + if ( strncmp(Line, KDBG_CONT, sizeof(KDBG_CONT)-1 ) == 0 ) + return 1; + + processed = match_mod(outFile, Line, processed); + processed = match_break(outFile, Line, processed); + /* more to be appended here: + * processed = match_xxx(outFile, Line, processed ); + * ... + */ + + return (int)(Line[0]); +} + +/* EOF */ diff --git a/reactos/tools/log2lines/match.h b/reactos/tools/log2lines/match.h new file mode 100644 index 00000000000..436c0134fc5 --- /dev/null +++ b/reactos/tools/log2lines/match.h @@ -0,0 +1,5 @@ +#include "util.h" + +int match_line(FILE *outFile, char *Line); + +/* EOF */ diff --git a/reactos/tools/log2lines/options.c b/reactos/tools/log2lines/options.c index 88d7f4b9e37..efa77e44d18 100644 --- a/reactos/tools/log2lines/options.c +++ b/reactos/tools/log2lines/options.c @@ -4,6 +4,7 @@ * * - Option init and parsing */ + #include #include #include @@ -16,7 +17,7 @@ #include "log2lines.h" #include "options.h" -char *optchars = "bcd:fFhl:mMP:rR:sS:tTuUvz:"; +char *optchars = "bcd:fFhl:L:mMP:rR:sS:tTuUvz:"; int opt_buffered = 0; // -b int opt_help = 0; // -h int opt_force = 0; // -f @@ -37,8 +38,10 @@ int opt_Twice = 0; // -T int opt_undo = 0; // -u int opt_redo = 0; // -U char *opt_Revision = NULL; // -R +int opt_Revision_check = 0; // -R check char opt_dir[MAX_PATH]; // -d -char opt_logFile[MAX_PATH]; // -l +char opt_logFile[MAX_PATH]; // -l|L +char *opt_mod = NULL; // -mod for opt_logFile char opt_7z[MAX_PATH]; // -z char opt_scanned[LINESIZE]; // all scanned options char opt_SourcesPath[LINESIZE]; //sources path @@ -48,6 +51,7 @@ int optionInit(int argc, const char **argv) int i; char *s; + opt_mod = "a"; strcpy(opt_dir, ""); strcpy(opt_logFile, ""); strcpy(opt_7z, CMD_7Z); @@ -70,6 +74,9 @@ int optionInit(int argc, const char **argv) case 'd': strcpy(opt_dir, argv[i+1]); break; + case 'L': + opt_mod = "w"; + //fall through case 'l': strcpy(opt_logFile, argv[i+1]); break; @@ -146,6 +153,8 @@ int optionParse(int argc, const char **argv) free(opt_Revision); opt_Revision = malloc(LINESIZE); sscanf(optarg, "%s", opt_Revision); + if (strcmp(opt_Revision, "check") == 0) + opt_Revision_check ++; break; case 's': opt_stats++; @@ -161,6 +170,7 @@ int optionParse(int argc, const char **argv) /* need to retranslate for source info: */ opt_undo++; opt_redo++; + opt_Revision_check ++; } break; case 't': @@ -208,3 +218,5 @@ int optionParse(int argc, const char **argv) return optCount; } + +/* EOF */ diff --git a/reactos/tools/log2lines/options.h b/reactos/tools/log2lines/options.h index 87b6cd0f321..a3f2d75ba83 100644 --- a/reactos/tools/log2lines/options.h +++ b/reactos/tools/log2lines/options.h @@ -28,8 +28,10 @@ extern int opt_Twice ; // -T extern int opt_undo ; // -u extern int opt_redo ; // -U extern char *opt_Revision; // -R +extern int opt_Revision_check; // -R check extern char opt_dir[]; // -d extern char opt_logFile[]; // -l +extern char *opt_mod; // mod for opt_logFile extern char opt_7z[]; // -z extern char opt_scanned[]; // all scanned options diff --git a/reactos/tools/log2lines/revision.c b/reactos/tools/log2lines/revision.c index 5a05bc66ef3..ae5fa17da37 100644 --- a/reactos/tools/log2lines/revision.c +++ b/reactos/tools/log2lines/revision.c @@ -29,7 +29,7 @@ log_rev_check(FILE *outFile, char *fileName, int showfile) if (revinfo.opt_verbose) log(outFile, "| R--- %s Last Changed Rev: %d\n", s, rev); - if (rev && opt_Revision) + if (rev && opt_Revision_check) { if (revinfo.rev < revinfo.buildrev) { @@ -128,9 +128,7 @@ getTBRevision(char *fileName) void reportRevision(FILE *outFile) { - if (!opt_Revision) - return; - if (strcmp(opt_Revision, "check") == 0) + if (opt_Revision_check) { if (lastLine.valid) logRevCheck(outFile); @@ -297,3 +295,5 @@ updateSvnlog(void) return res; } + +/* EOF */ diff --git a/reactos/tools/log2lines/stat.c b/reactos/tools/log2lines/stat.c index 6f8e5fe83c2..801f693bde2 100644 --- a/reactos/tools/log2lines/stat.c +++ b/reactos/tools/log2lines/stat.c @@ -42,3 +42,5 @@ stat_clear(PSUMM psumm) { memset(psumm, 0, sizeof(SUMM)); } + +/* EOF */ diff --git a/reactos/tools/log2lines/util.c b/reactos/tools/log2lines/util.c index 50887e3c456..19e6342934a 100644 --- a/reactos/tools/log2lines/util.c +++ b/reactos/tools/log2lines/util.c @@ -16,25 +16,25 @@ #include "options.h" int -set_LogFile(FILE *logFile) +set_LogFile(FILE **plogFile) { if (*opt_logFile) { - if (logFile) - fclose(logFile); - logFile = NULL; + if (*plogFile) + fclose(*plogFile); + *plogFile = NULL; if (strcmp(opt_logFile,"none") == 0) return 0; //just close - logFile = fopen(opt_logFile, "a"); - if (logFile) + *plogFile = fopen(opt_logFile, opt_mod ? opt_mod : "a"); + if (*plogFile) { // disable buffering so fflush is not needed if (!opt_buffered) { l2l_dbg(1, "Disabling log buffering on %s\n", opt_logFile); - setbuf(logFile, NULL); + setbuf(*plogFile, NULL); } else l2l_dbg(1, "Enabling log buffering on %s\n", opt_logFile); @@ -186,3 +186,5 @@ copy_file(char *src, char *dst) } return 0; } + +/* EOF */ diff --git a/reactos/tools/log2lines/util.h b/reactos/tools/log2lines/util.h index afb5dcfb116..8df1181b4f7 100644 --- a/reactos/tools/log2lines/util.h +++ b/reactos/tools/log2lines/util.h @@ -10,6 +10,7 @@ #include #include "cmd.h" +#include "options.h" #define log(outFile, fmt, ...) \ { \ @@ -44,6 +45,6 @@ const char *getFmt(const char *a); long my_atoi(const char *a); int isOffset(const char *a); int copy_file(char *src, char *dst); -int set_LogFile(FILE *logFile); +int set_LogFile(FILE **plogFile); /* EOF */ diff --git a/reactos/tools/log2lines/version.h b/reactos/tools/log2lines/version.h index 1222b4f56da..ad1e9299af0 100644 --- a/reactos/tools/log2lines/version.h +++ b/reactos/tools/log2lines/version.h @@ -7,6 +7,6 @@ #pragma once -#define LOG2LINES_VERSION "2.1" +#define LOG2LINES_VERSION "2.2" /* EOF */