Index: tools/rsym/log2lines.c =================================================================== --- tools/rsym/log2lines.c (revision 44285) +++ tools/rsym/log2lines.c (working copy) @@ -18,7 +18,7 @@ #include "rsym.h" -#define LOG2LINES_VERSION "1.1" +#define LOG2LINES_VERSION "1.3" #define INVALID_BASE 0xFFFFFFFFL @@ -53,12 +53,21 @@ #define CP_FMT CP_CMD "%s %s > " DEV_NULL #define CMD_7Z "7z" +//#define UNZIP_FMT_7Z "%s e -y %s -o%s > " DEV_NULL +#define UNZIP_FMT_7Z "%s e -y %s -o%s" #define UNZIP_FMT "%s x -y -r %s -o%s > " DEV_NULL #define UNZIP_FMT_CAB \ "%s x -y -r %s" PATH_STR "reactos" PATH_STR "reactos.cab -o%s" PATH_STR "reactos" PATH_STR "reactos > " DEV_NULL #define LINESIZE 1024 +#define log(outFile, fmt, args...) \ + { \ + fprintf(outFile, fmt, args); \ + if (logFile) \ + fprintf(logFile, fmt, args); \ + } + struct entry_struct { char *buf; @@ -84,6 +93,7 @@ int redo; int skipped; int diff; + int majordiff; int offset_errors; int total; }; @@ -180,9 +190,11 @@ 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, toString); if (opt_twice) { @@ -190,51 +202,77 @@ if ( e == e2 ) e2 = NULL; + else + summ.diff ++; if ( opt_Twice && e2 ) { e = e2; e2 = NULL; - /* replaced (transparantly), but update stats: */ - summ.diff ++; + /* replaced (transparantly), but updated stats */ } } if ( e || e2 ) { - if (toString) - { // put in toString if provided - if ( e2 ) - { - snprintf(toString, LINESIZE, "%s:%u (%s) [%s:%u (%s)]", + if ( e2 ) + { + 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->FileOffset], - (unsigned int)e2->SourceLine, &Strings[e2->FunctionOffset]); - summ.diff ++; } else { - snprintf(toString, LINESIZE, "%s:%u (%s)", - &Strings[e->FileOffset], - (unsigned int)e->SourceLine, - &Strings[e->FunctionOffset]); - } - return 0; + 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 - { // to stdout - if ( e2 ) - { - printf("%s:%u (%s) [%s:%u (%s)]\n", - &Strings[e->FileOffset], + { + if (toString) + { // put in toString if provided + snprintf(toString, LINESIZE, "%s:%u (%s)", + &Strings[e->FileOffset], (unsigned int)e->SourceLine, - &Strings[e->FunctionOffset], - &Strings[e2->FileOffset], - (unsigned int)e2->SourceLine, - &Strings[e2->FunctionOffset]); - summ.diff ++; + &Strings[e->FunctionOffset]); } else { @@ -242,9 +280,9 @@ &Strings[e->FileOffset], (unsigned int)e->SourceLine, &Strings[e->FunctionOffset]); - } - return 0; + } } + return 0; } return 1; } @@ -309,10 +347,9 @@ return res; } -static long -my_atoi(const char *a) +static const char * +getFmt(const char *a) { - int i = 0; const char *fmt = "%x"; if (*a == '0') @@ -332,11 +369,25 @@ break; } } - sscanf(a, fmt, &i); + return fmt; +} + +static long +my_atoi(const char *a) +{ + int i = 0; + sscanf(a, getFmt(a), &i); return i; } static int +isOffset(const char *a) +{ + int i = 0; + return sscanf(a, getFmt(a), &i); +} + +static int file_exists(char *name) { FILE *f; @@ -408,7 +459,7 @@ fr = fopen(fname, "rb"); if (!fr) { - if (opt_verbose) + if (opt_verbose>2) fprintf(stderr, "get_ImageBase, cannot open '%s' (%s)\n", fname, strerror(errno)); return 1; } @@ -807,16 +858,12 @@ mark = opt_mark ? "* " : ""; if (opt_redo && !(res = translate_file(path, offset, LineOut))) { - fprintf(outFile, "%s<%s:%x (%s)>%s", mark, path, offset, LineOut, tail); - if (logFile) - fprintf(logFile, "%s<%s:%x (%s)>%s", mark, path, offset, LineOut, tail); + log(outFile, "%s<%s:%x (%s)>%s", mark, path, offset, LineOut, tail); summ.redo ++; } else { - fprintf(outFile, "%s<%s:%x>%s", mark, path, offset, tail); - if (logFile) - fprintf(logFile, "%s<%s:%x>%s", mark, path, offset, tail); + log(outFile, "%s<%s:%x>%s", mark, path, offset, tail); summ.undo ++; } } @@ -837,9 +884,7 @@ if (!(res = translate_file(path, offset, LineOut))) { mark = opt_mark ? "* " : ""; - fprintf(outFile, "%s<%s:%x (%s)>%s", mark, path, offset, LineOut, tail); - if (logFile) - fprintf(logFile, "%s<%s:%x (%s)>%s", mark, path, offset, LineOut, tail); + log(outFile, "%s<%s:%x (%s)>%s", mark, path, offset, LineOut, tail); summ.translated ++; } else @@ -855,9 +900,7 @@ { if (sep) *sep = ':'; // restore because not translated - fprintf(outFile, "%s%s", mark, s); // just copy - if (logFile) - fprintf(logFile, "%s%s", mark, s); // just copy + log(outFile, "%s%s", mark, s); } memset(Line, '\0', LINESIZE); // flushed } @@ -868,13 +911,14 @@ if (outFile) { fprintf(outFile, "\n*** LOG2LINES SUMMARY ***\n"); - fprintf(outFile, "Translated: %d\n", summ.translated); - fprintf(outFile, "Reverted: %d\n", summ.undo); - fprintf(outFile, "Retranslated: %d\n", summ.redo); - fprintf(outFile, "Skipped: %d\n", summ.skipped); - fprintf(outFile, "Differ: %d\n", summ.diff); - fprintf(outFile, "Offset error: %d\n", summ.offset_errors); - fprintf(outFile, "Total: %d\n", summ.total); + fprintf(outFile, "Translated: %d\n", summ.translated); + fprintf(outFile, "Reverted: %d\n", summ.undo); + fprintf(outFile, "Retranslated: %d\n", summ.redo); + fprintf(outFile, "Skipped: %d\n", summ.skipped); + fprintf(outFile, "Differ: %d\n", summ.diff); + fprintf(outFile, "Differ(function/source): %d\n", summ.majordiff); + fprintf(outFile, "Offset error: %d\n", summ.offset_errors); + fprintf(outFile, "Total: %d\n", summ.total); fprintf(outFile, "-------------------------------\n"); fprintf(outFile, "Log2lines version: " LOG2LINES_VERSION "\n"); fprintf(outFile, "Directory: %s\n",opt_dir); @@ -927,7 +971,6 @@ translate_line(outFile, Line, path, LineOut); translate_char(c, outFile); } - i = 0; } else { @@ -971,9 +1014,7 @@ } else { - fprintf(outFile, "%s", Line); // just copy - if (logFile) - fprintf(logFile, "%s", Line); // just copy + log(outFile, "%s", Line); } } } @@ -993,9 +1034,12 @@ static char *verboseUsage = "\n" "Description:\n" -" When are given, log2lines works just like raddr2line\n" +" When are given, log2lines works like raddr2line:\n" +" - The combination can be repeated\n" +" - Also, can be repeated for each \n" +" - NOTE: some of the options below will have no effect in this form.\n" " Otherwise it reads stdin and tries to translate lines of the form:\n" -" \n\n" +" \n\n" " The result is written to stdout.\n" " log2lines uses a cache in order to avoid a directory scan at each\n" " image lookup, greatly increasing performance. Only image path and its\n" @@ -1008,7 +1052,9 @@ " -d |\n" " Directory to scan for images. (Do not append a '" PATH_STR "')\n" " This option also takes an ISO image as argument:\n" -" - The image is recognized by the '.iso' extension.\n" +" - The image is recognized by the '.iso' or '.7z' extension.\n" +" - NOTE: The '.7z' and extracted '.iso' basenames must be identical,\n" +" which is normally true for Reactos trunk builds.\n" " - The image will be unpacked to a directory with the same name.\n" " - The embedded reactos.cab file will also be unpacked.\n" " - Combined with -f the file will be re-unpacked.\n" @@ -1026,17 +1072,20 @@ " -r Raw output without translation.\n\n" " -s Statistics. A summary with the following info is printed after EOF:\n" " *** LOG2LINES SUMMARY ***\n" -" - Translated: Translated lines.\n" -" - Reverted: Lines translated back. See -u option\n" -" - Retranslated: Lines retranslated. See -U option\n" -" - Skipped: Lines not translated.\n" -" - Differ: Lines where (addr-1) info differs. See -tT options\n" -" - Offset error: Image exists, but error retrieving offset info.\n" -" - Total: Total number of lines attempted to translate.\n" +" - Translated: Translated lines.\n" +" - Reverted: Lines translated back. See -u option\n" +" - Retranslated: Lines retranslated. See -U option\n" +" - Skipped: Lines not translated.\n" +" - Differ: Lines where (addr-1) info differs. See -tT options\n" +" - Differ(func/src):Lines where also function or source info differ.\n" +" - Offset error: Image exists, but error retrieving offset info.\n" +" - Total: Total number of lines attempted to translate.\n" " Also some version info is displayed.\n\n" " -t Translate twice. The address itself and for (address - 1)\n" -" Display extra filename and linenumber between [..] if they differ\n\n" -" -T As -t, but the original filename+linenumber gets replaced\n\n" +" Show extra filename, func and linenumber between [..] if they differ\n" +" So if only the linenumbers differ, then only show the extra\n" +" linenumber.\n\n" +" -T As -t, but the original filename+func+linenumber gets replaced\n\n" " -u Undo translations.\n" " Lines are translated back (reverted) to the form \n" " Overrides console mode -c.\n\n" @@ -1061,14 +1110,22 @@ " Use kdbg debugger to send output to logfile:\n" " log2lines < \\\\.\\pipe\\kdbg > dbg.log\n\n" " Re-translate a debug log:\n" -" log2lines -d bootcd-38701-dbg.iso < bugxxxx.log\n\n" +" log2lines -U -d bootcd-38701-dbg.iso < bugxxxx.log\n\n" +" Re-translate a debug log. Specify a 7z file, which wil be decompressed.\n" +" Also check for (address) - (address - 1) differences:\n" +" log2lines -U -t -d bootcd-38701-dbg.7z < bugxxxx.log\n" +" This would generate loglines like:\n" +" ''\n\n" +" The following command line invocations are equivalent:\n" +" log2lines msi.dll 2e35d msi.dll 2235 msiexec.exe 30a8 msiexec.exe 2e89\n" +" log2lines msi.dll 2e35d 2235 msiexec.exe 30a8 2e89\n\n" "\n"; static void usage(int verbose) { fprintf(stderr, "log2lines " LOG2LINES_VERSION "\n\n"); - fprintf(stderr, "Usage: log2lines [-%s] [ ]\n", optchars); + fprintf(stderr, "Usage: log2lines -%s { {}}\n", optchars); if (verbose) { fprintf(stderr, "%s", verboseUsage); @@ -1135,10 +1192,51 @@ static int check_directory(int force) { + char Line[LINESIZE]; char freeldr_path[MAX_PATH]; char iso_path[MAX_PATH]; + char compressed_7z_path[MAX_PATH]; + char *check_iso; + char *check_dir; - char *check_iso = strrchr(opt_dir, '.'); + check_iso = strrchr(opt_dir, '.'); + if (check_iso && PATHCMP(check_iso, ".7z") == 0) + { + if (opt_verbose) + fprintf(stderr, "Uncompressing 7z image: %s\n", opt_dir); + + //First attempt to decompress to a .iso image + strcpy(compressed_7z_path, opt_dir); + if ( (check_dir = strrchr(compressed_7z_path, PATH_CHAR)) ) + { + *check_dir = '\0'; + } + else + strcpy(compressed_7z_path, "."); //default to current dir + + sprintf(Line, UNZIP_FMT_7Z, opt_7z, opt_dir, compressed_7z_path); + + /* This of course only works if the .7z and .iso basenames are identical + * which is normally true for our trunk builds: + */ + strcpy(check_iso, ".iso"); + if (!file_exists(opt_dir) || force) + { + if (system(Line) < 0) + { + fprintf(stderr, "\nCannot decompress to iso image %s\n", opt_dir); + if (opt_verbose) + fprintf(stderr, "Failed to execute: '%s'\n", Line); + return 2; + } + } + else + { + if (opt_verbose > 1) + fprintf(stderr, "%s already decompressed\n", opt_dir); + } + } + if (check_iso && PATHCMP(check_iso, ".iso") == 0) { if (opt_verbose) @@ -1272,12 +1370,6 @@ opt_console = 0; argc -= optCount; - if (argc != 1 && argc != 3) - { - usage(0); - exit(1); - } - if (check_directory(opt_force)) exit(3); @@ -1312,16 +1404,42 @@ } } - if (argc == 3) - { // translate - translate_file(argv[optCount + 1], my_atoi(argv[optCount + 2]), NULL); + if (argc>1) + { // translate { } + int i=1; + const char *base = NULL; + const char *offset = NULL; + while ( i < argc ) + { + offset = argv[optCount + i++]; + if( isOffset(offset) ) + { + if (base) + { + if (opt_verbose > 1) + fprintf(stderr, "translating %s %s\n",base,offset); + translate_file(base, my_atoi(offset), NULL); + } + else + { + fprintf(stderr, " expected\n"); + res = 3; + break; + } + } + else + { + //Must be exefile + base = offset; + } + } } else - { // translate logging from stdin + { // translate logging from stdin translate_files(stdin, stdout); } if (logFile) fclose(logFile); - return res; + exit(res); }