Update log2lines to version 1.4. Jan Roeloffzen, bug #4342.

svn path=/trunk/; revision=44335
This commit is contained in:
Dmitry Gorbachev 2009-11-30 21:49:18 +00:00
parent 4b9396cef9
commit 378568a6d9

View file

@ -1,14 +1,6 @@
/*
* Usage: log2lines [-cd:fFhmrv] [<exefile> <offset>]
* Try log2lines -h
*
* This is a tool and is compiled using the host compiler,
* i.e. on Linux gcc and not mingw-gcc (cross-compiler).
* Therefore we can't include SDK headers and we have to
* duplicate some definitions here.
* Also note that the internal functions are "old C-style",
* returning an int, where a return of 0 means success and
* non-zero is failure.
* ReactOS log2lines
* Written by Jan Roeloffzen
*/
#include <stdio.h>
@ -18,7 +10,7 @@
#include "rsym.h"
#define LOG2LINES_VERSION "1.1"
#define LOG2LINES_VERSION "1.4"
#define INVALID_BASE 0xFFFFFFFFL
@ -34,7 +26,7 @@
#define CP_CMD "copy /Y "
#define DIR_FMT "dir /a:-d /s /b %s > %s"
#else /* not defined (__DJGPP__) || defined (__WIN32__) */
#else /* not defined (__DJGPP__) || defined (__WIN32__) */
#include <errno.h>
#include <limits.h>
@ -48,17 +40,26 @@
#define CP_CMD "cp -f "
#define DIR_FMT "find %s -type f > %s"
#endif /* not defined (__DJGPP__) || defined (__WIN32__) */
#endif /* not defined (__DJGPP__) || defined (__WIN32__) */
#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, ...) \
{ \
fprintf(outFile, fmt, ##__VA_ARGS__); \
if (logFile) \
fprintf(logFile, fmt, ##__VA_ARGS__); \
}
struct entry_struct
{
char *buf;
@ -79,20 +80,21 @@ struct cache_struct
struct summ_struct
{
int translated;
int undo;
int redo;
int skipped;
int diff;
int offset_errors;
int total;
int translated;
int undo;
int redo;
int skipped;
int diff;
int majordiff;
int offset_errors;
int total;
};
typedef struct cache_struct CACHE;
typedef struct summ_struct SUMM;
typedef struct summ_struct SUMM;
static CACHE cache;
static SUMM summ;
static CACHE cache;
static SUMM summ;
static char *optchars = "bcd:fFhl:mMrstTuUvz:";
static int opt_buffered= 0; // -b
@ -112,7 +114,7 @@ static int opt_redo = 0; // -U
static char opt_dir[MAX_PATH]; // -d
static char opt_logFile[MAX_PATH]; // -l
static char opt_7z[MAX_PATH]; // -z
static char opt_scanned[LINESIZE]; // all scanned options
static char opt_scanned[LINESIZE]; // all scanned options
static FILE *logFile = NULL;
static char *cache_name;
@ -152,11 +154,11 @@ find_rossym_section(PIMAGE_FILE_HEADER PEFileHeader, PIMAGE_SECTION_HEADER PESec
}
static PROSSYM_ENTRY
find_offset(void *data, size_t offset, char *toString)
find_offset(void *data, size_t offset)
{
PSYMBOLFILE_HEADER RosSymHeader = (PSYMBOLFILE_HEADER) data;
PROSSYM_ENTRY Entries = (PROSSYM_ENTRY) ((char *)data + RosSymHeader->SymbolsOffset);
size_t symbols = RosSymHeader->SymbolsLength / sizeof (ROSSYM_ENTRY);
PSYMBOLFILE_HEADER RosSymHeader = (PSYMBOLFILE_HEADER)data;
PROSSYM_ENTRY Entries = (PROSSYM_ENTRY)((char *)data + RosSymHeader->SymbolsOffset);
size_t symbols = RosSymHeader->SymbolsLength / sizeof(ROSSYM_ENTRY);
size_t i;
for (i = 0; i < symbols; i++)
@ -177,80 +179,108 @@ find_offset(void *data, size_t offset, char *toString)
static int
print_offset(void *data, size_t offset, char *toString)
{
PSYMBOLFILE_HEADER RosSymHeader = (PSYMBOLFILE_HEADER) data;
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;
e = find_offset(data, offset, toString);
fmt[0] = '\0';
e = find_offset(data, offset);
if (opt_twice)
{
e2 = find_offset(data, offset-1, toString);
if ( e == e2 )
e2 = NULL;
e2 = find_offset(data, offset - 1);
if ( opt_Twice && e2 )
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 (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],
(unsigned int)e->SourceLine,
&Strings[e->FunctionOffset],
&Strings[e2->FileOffset],
(unsigned int)e->SourceLine,
(unsigned int)e2->SourceLine,
&Strings[e->FunctionOffset],
&Strings[e2->FunctionOffset]);
summ.diff ++;
}
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]);
}
return 0;
}
else
{ // to stdout
if ( e2 )
{
printf("%s:%u (%s) [%s:%u (%s)]\n",
&Strings[e->FileOffset],
(unsigned int)e->SourceLine,
&Strings[e->FunctionOffset],
&Strings[e2->FileOffset],
(unsigned int)e2->SourceLine,
&Strings[e2->FunctionOffset]);
summ.diff ++;
}
else
{
printf("%s:%u (%s)\n",
&Strings[e->FileOffset],
&Strings[e->FileOffset],
(unsigned int)e->SourceLine,
&Strings[e->FunctionOffset]);
}
return 0;
}
return 0;
}
return 1;
}
static int
process_data(const void *FileData, size_t FileSize, size_t offset, char *toString)
process_data(const void *FileData, size_t offset, char *toString)
{
PIMAGE_DOS_HEADER PEDosHeader;
PIMAGE_FILE_HEADER PEFileHeader;
@ -261,24 +291,24 @@ process_data(const void *FileData, size_t FileSize, size_t offset, char *toStrin
int res;
/* Check if MZ header exists */
PEDosHeader = (PIMAGE_DOS_HEADER) FileData;
PEDosHeader = (PIMAGE_DOS_HEADER)FileData;
if (PEDosHeader->e_magic != IMAGE_DOS_MAGIC || PEDosHeader->e_lfanew == 0L)
{
fprintf(stderr, "Input file is not a PE image.\n");
summ.offset_errors ++;
summ.offset_errors++;
return 1;
}
/* Locate PE file header */
/* sizeof(ULONG) = sizeof(MAGIC) */
PEFileHeader = (PIMAGE_FILE_HEADER) ((char *)FileData + PEDosHeader->e_lfanew + sizeof (ULONG));
PEFileHeader = (PIMAGE_FILE_HEADER)((char *)FileData + PEDosHeader->e_lfanew + sizeof(ULONG));
/* Locate optional header */
PEOptHeader = (PIMAGE_OPTIONAL_HEADER) (PEFileHeader + 1);
PEOptHeader = (PIMAGE_OPTIONAL_HEADER)(PEFileHeader + 1);
ImageBase = PEOptHeader->ImageBase;
/* Locate PE section headers */
PESectionHeaders = (PIMAGE_SECTION_HEADER) ((char *)PEOptHeader + PEFileHeader->SizeOfOptionalHeader);
PESectionHeaders = (PIMAGE_SECTION_HEADER)((char *)PEOptHeader + PEFileHeader->SizeOfOptionalHeader);
/* make sure offset is what we want */
offset = fixup_offset(ImageBase, offset);
@ -288,7 +318,7 @@ process_data(const void *FileData, size_t FileSize, size_t offset, char *toStrin
if (!PERosSymSectionHeader)
{
fprintf(stderr, "Couldn't find rossym section in executable\n");
summ.offset_errors ++;
summ.offset_errors++;
return 1;
}
res = print_offset((char *)FileData + PERosSymSectionHeader->PointerToRawData, offset, toString);
@ -303,16 +333,15 @@ process_data(const void *FileData, size_t FileSize, size_t offset, char *toStrin
printf("??:0\n");
}
fprintf(stderr, "Offset not found.\n");
summ.offset_errors ++;
summ.offset_errors++;
}
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,10 +361,26 @@ my_atoi(const char *a)
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;
if (strchr(a, '.'))
return 0;
return sscanf(a, getFmt(a), &i);
}
static int
file_exists(char *name)
{
@ -387,7 +432,7 @@ process_file(const char *file_name, size_t offset, char *toString)
}
else
{
res = process_data(FileData, FileSize, offset, toString);
res = process_data(FileData, offset, toString);
free(FileData);
}
return res;
@ -408,12 +453,12 @@ get_ImageBase(char *fname, size_t *ImageBase)
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;
}
readLen = fread(&PEDosHeader, sizeof (IMAGE_DOS_HEADER), 1, fr);
readLen = fread(&PEDosHeader, sizeof(IMAGE_DOS_HEADER), 1, fr);
if (1 != readLen)
{
if (opt_verbose)
@ -432,8 +477,8 @@ get_ImageBase(char *fname, size_t *ImageBase)
}
/* Locate PE file header */
res = fseek(fr, PEDosHeader.e_lfanew + sizeof (ULONG), SEEK_SET);
readLen = fread(&PEFileHeader, sizeof (IMAGE_FILE_HEADER), 1, fr);
res = fseek(fr, PEDosHeader.e_lfanew + sizeof(ULONG), SEEK_SET);
readLen = fread(&PEFileHeader, sizeof(IMAGE_FILE_HEADER), 1, fr);
if (1 != readLen)
{
if (opt_verbose)
@ -443,7 +488,7 @@ get_ImageBase(char *fname, size_t *ImageBase)
}
/* Locate optional header */
readLen = fread(&PEOptHeader, sizeof (IMAGE_OPTIONAL_HEADER), 1, fr);
readLen = fread(&PEOptHeader, sizeof(IMAGE_OPTIONAL_HEADER), 1, fr);
if (1 != readLen)
{
if (opt_verbose)
@ -453,8 +498,8 @@ get_ImageBase(char *fname, size_t *ImageBase)
}
/* Check if it's really an IMAGE_OPTIONAL_HEADER we are interested in */
if ((PEOptHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC) &&
(PEOptHeader.Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC))
if (PEOptHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC &&
PEOptHeader.Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC)
{
if (opt_verbose > 1)
fprintf(stderr, "get_ImageBase %s, not an IMAGE_NT_OPTIONAL_HDR<32|64>\n", fname);
@ -500,7 +545,7 @@ entry_create(char *Line)
if (!Line)
return NULL;
pentry = malloc(sizeof (CACHE_ENTRY));
pentry = malloc(sizeof(CACHE_ENTRY));
if (!pentry)
return NULL;
@ -557,7 +602,7 @@ entry_lookup(char *name)
if (PATHCMP(name, pnext->name) == 0)
{
if (pprev)
{ // move to head for faster lookup next time
{ // move to head for faster lookup next time
pprev->pnext = pnext->pnext;
pnext->pnext = cache.phead;
cache.phead = pnext;
@ -680,7 +725,7 @@ create_cache(int force, int skipImageBase)
if (*Fname == '\n')
*Fname = '\0';
while ((Fname > Line) && (*Fname != PATH_CHAR))
while (Fname > Line && *Fname != PATH_CHAR)
Fname--;
if (*Fname == PATH_CHAR)
Fname++;
@ -770,9 +815,9 @@ translate_char(int c, FILE *outFile)
static char *
remove_mark(char *Line)
{
if( Line[1] == ' ' && Line[2] == '<' )
if ( Line[0] == '*' || Line[0] == '?' )
return Line+2;
if (Line[1] == ' ' && Line[2] == '<')
if (Line[0] == '*' || Line[0] == '?')
return Line + 2;
return Line;
}
@ -799,33 +844,29 @@ translate_line(FILE *outFile, char *Line, char *path, char *LineOut)
if (cnt == 3 && ch == ' ')
{
tail = strchr(s, '>');
tail = tail ? tail-1 : tail;
if (tail && (tail[0] == ')') && (tail[1] == '>') )
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)))
{
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);
summ.redo ++;
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);
summ.undo ++;
log(outFile, "%s<%s:%x>%s", mark, path, offset, tail);
summ.undo++;
}
}
else
{
mark = opt_Mark ? "? " : "";
summ.skipped ++;
summ.skipped++;
}
summ.total ++;
summ.total++;
}
}
@ -837,17 +878,15 @@ translate_line(FILE *outFile, char *Line, char *path, char *LineOut)
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);
summ.translated ++;
log(outFile, "%s<%s:%x (%s)>%s", mark, path, offset, LineOut, tail);
summ.translated++;
}
else
{
mark = opt_Mark ? "? " : "";
summ.skipped ++;
summ.skipped++;
}
summ.total ++;
summ.total++;
}
}
}
@ -855,36 +894,35 @@ translate_line(FILE *outFile, char *Line, char *path, char *LineOut)
{
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
}
static void
print_summary(FILE * outFile)
print_summary(FILE *outFile)
{
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);
fprintf(outFile, "Passed options: %s\n",opt_scanned);
fprintf(outFile, "Directory: %s\n", opt_dir);
fprintf(outFile, "Passed options: %s\n", opt_scanned);
fprintf(outFile, "-------------------------------\n");
}
}
static int
translate_files(FILE * inFile, FILE * outFile)
translate_files(FILE *inFile, FILE *outFile)
{
char *Line = malloc(LINESIZE + 1);
char *path = malloc(LINESIZE + 1);
@ -927,7 +965,6 @@ translate_files(FILE * inFile, FILE * outFile)
translate_line(outFile, Line, path, LineOut);
translate_char(c, outFile);
}
i = 0;
}
else
{
@ -962,7 +999,7 @@ translate_files(FILE * inFile, FILE * outFile)
}
}
else
{ // Line by line, slightly faster but less interactive
{ // Line by line, slightly faster but less interactive
while (fgets(Line, LINESIZE, inFile) != NULL)
{
if (!opt_raw)
@ -971,9 +1008,7 @@ translate_files(FILE * inFile, FILE * outFile)
}
else
{
fprintf(outFile, "%s", Line); // just copy
if (logFile)
fprintf(logFile, "%s", Line); // just copy
log(outFile, "%s", Line);
}
}
}
@ -993,9 +1028,12 @@ translate_files(FILE * inFile, FILE * outFile)
static char *verboseUsage =
"\n"
"Description:\n"
" When <exefile> <offset> are given, log2lines works just like raddr2line\n"
" When <exefile> <offset> are given, log2lines works like raddr2line:\n"
" - The <exefile> <offset> combination can be repeated\n"
" - Also, <offset> can be repeated for each <exefile>\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"
" <IMAGENAME:ADDRESS>\n\n"
" <IMAGENAME:ADDRESS>\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 +1046,9 @@ static char *verboseUsage =
" -d <directory>|<ISO image>\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 +1066,20 @@ static char *verboseUsage =
" -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 <IMAGENAME:ADDRESS>\n"
" Overrides console mode -c.\n\n"
@ -1053,7 +1096,7 @@ static char *verboseUsage =
"Examples:\n"
" Setup is a VMware machine with its serial port set to: '\\\\.\\pipe\\kdbg'.\n\n"
" Just recreate cache after a svn update or a new module has been added:\n"
" log2lines -F\n\n"
" log2lines -F\n\n"
" Use kdbg debugger via console (interactive):\n"
" log2lines -c < \\\\.\\pipe\\kdbg\n\n"
" Use kdbg debugger via console, and append copy to logFile:\n"
@ -1061,14 +1104,22 @@ static char *verboseUsage =
" 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"
" '<ntdll.dll:60f1 (dll/ntdll/ldr/utils.c:337[331] (LdrPEStartup))>'\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] [<exefile> <offset>]\n", optchars);
fprintf(stderr, "Usage: log2lines -%s {<exefile> <offset> {<offset>}}\n", optchars);
if (verbose)
{
fprintf(stderr, "%s", verboseUsage);
@ -1085,7 +1136,7 @@ unpack_iso(char *dir, char *iso)
char Line[LINESIZE];
int res = 0;
char iso_tmp[MAX_PATH];
int iso_copied = 0;
int iso_copied = 0;
FILE *fiso;
strcpy(iso_tmp, iso);
@ -1094,8 +1145,8 @@ unpack_iso(char *dir, char *iso)
if (opt_verbose)
fprintf(stderr, "Open of %s failed (locked for writing?), trying to copy first\n", iso);
strcat(iso_tmp,"~");
if (copy_file(iso,iso_tmp))
strcat(iso_tmp, "~");
if (copy_file(iso, iso_tmp))
return 3;
iso_copied = 1;
}
@ -1135,10 +1186,51 @@ unpack_iso(char *dir, char *iso)
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;
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);
}
}
char *check_iso = strrchr(opt_dir, '.');
if (check_iso && PATHCMP(check_iso, ".iso") == 0)
{
if (opt_verbose)
@ -1187,7 +1279,7 @@ main(int argc, const char **argv)
int i;
strcpy(opt_scanned, "");
for (i=1; i<argc; i++)
for (i = 1; i < argc; i++)
{
strcat(opt_scanned, argv[i]);
strcat(opt_scanned, " ");
@ -1218,7 +1310,7 @@ main(int argc, const char **argv)
case 'h':
opt_help++;
usage(1);
exit(0);
return 0;
break;
case 'F':
opt_exit++;
@ -1263,7 +1355,7 @@ main(int argc, const char **argv)
break;
default:
usage(0);
exit(2);
return 2;
break;
}
optCount++;
@ -1272,18 +1364,12 @@ main(int argc, const char **argv)
opt_console = 0;
argc -= optCount;
if (argc != 1 && argc != 3)
{
usage(0);
exit(1);
}
if (check_directory(opt_force))
exit(3);
return 3;
create_cache(opt_force, 0);
if (opt_exit)
exit(0);
return 0;
read_cache();
@ -1297,7 +1383,7 @@ main(int argc, const char **argv)
{
if (opt_verbose)
fprintf(stderr, "Disabling log buffering on %s\n", opt_logFile);
setbuf(logFile,NULL);
setbuf(logFile, NULL);
}
else
{
@ -1308,20 +1394,47 @@ main(int argc, const char **argv)
else
{
fprintf(stderr, "Could not open logfile %s (%s)\n", opt_logFile, strerror(errno));
exit(2);
return 2;
}
}
if (argc == 3)
{ // translate <exefile> <offset>
translate_file(argv[optCount + 1], my_atoi(argv[optCount + 2]), NULL);
if (argc > 1)
{ // translate {<exefile> <offset>}
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, "<exefile> 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;
}