*
* - Image directory caching
*/
+
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
return res;
}
+int
+cleanable(char *path)
+{
+ if (strcmp(basename(path),DEF_OPT_DIR) == 0)
+ return 1;
+ return 0;
+}
+
int
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;
return 0;
}
-
+/* EOF */
int check_directory(int force);
int read_cache(void);
int create_cache(int force, int skipImageBase);
+int cleanable(char *path);
/* EOF */
*
* - Cli for escape commands
*/
+
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/* 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)
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 <Image>:<offset>\n");
+ }
+ else
+ esclog(outFile, "':' expected\n");
+
+ return 1;
+}
+
char
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");
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 (*)");
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");
{
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");
return KDBG_ESC_CHAR; //handled escaped command
}
+
+/* EOF */
"%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
*
* - Help text and functions
*/
+
#include <stdio.h>
#include "version.h"
" -l <logFile>\n"
" <logFile>: Append copy to specified logFile.\n"
" Default: no logFile\n\n"
+" -L <logFile>\n"
+" <logFile>: (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: <IMAGENAME:ADDRESS> )\n\n"
" 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"
" 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 <module>:<reladdress>:\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"
" | 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"
+" <msi.dll:2e35d (dll/win32/msi/msiquery.c:189 (MSI_IterateRecords))>\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
else
fprintf(stderr, "Try log2lines -h\n");
}
+
+/* EOF */
*
* - Image functions for symbol info
*/
-#include <sys/stat.h>
+
#include <errno.h>
#include <string.h>
#include <rsym.h>
+#include "compat.h"
#include "util.h"
#include "options.h"
#include "log2lines.h"
fclose(fr);
return 0;
}
+
+/* EOF */
#include <string.h>
#include <stdlib.h>
+#include "config.h"
#include "compat.h"
#include "list.h"
#include "util.h"
l2l_dbg(1, "ImageBase field missing\n");
return entry_delete(pentry);
}
+ pentry->RelBase = INVALID_BASE;
+ pentry->Size = 0;
return pentry;
}
return pentry;
}
+
+/* EOF */
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);
#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;
{
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);
+ }
}
}
}
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));
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");
{
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;
}
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
{
}
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 */
$(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
$(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)
--- /dev/null
+/*
+ * ReactOS log2lines
+ * Written by Jan Roeloffzen
+ *
+ * - Custom match routines
+ */
+
+#include <string.h>
+
+#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 */
--- /dev/null
+#include "util.h"
+
+int match_line(FILE *outFile, char *Line);
+
+/* EOF */
*
* - Option init and parsing
*/
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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
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 <opt_dir>
-char opt_logFile[MAX_PATH]; // -l <opt_logFile>
+char opt_logFile[MAX_PATH]; // -l|L <opt_logFile>
+char *opt_mod = NULL; // -mod for opt_logFile
char opt_7z[MAX_PATH]; // -z <opt_7z>
char opt_scanned[LINESIZE]; // all scanned options
char opt_SourcesPath[LINESIZE]; //sources path
int i;
char *s;
+ opt_mod = "a";
strcpy(opt_dir, "");
strcpy(opt_logFile, "");
strcpy(opt_7z, CMD_7Z);
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;
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++;
/* need to retranslate for source info: */
opt_undo++;
opt_redo++;
+ opt_Revision_check ++;
}
break;
case 't':
return optCount;
}
+
+/* EOF */
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 <opt_dir>
extern char opt_logFile[]; // -l <opt_logFile>
+extern char *opt_mod; // mod for opt_logFile
extern char opt_7z[]; // -z <opt_7z>
extern char opt_scanned[]; // all scanned options
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)
{
void
reportRevision(FILE *outFile)
{
- if (!opt_Revision)
- return;
- if (strcmp(opt_Revision, "check") == 0)
+ if (opt_Revision_check)
{
if (lastLine.valid)
logRevCheck(outFile);
return res;
}
+
+/* EOF */
{
memset(psumm, 0, sizeof(SUMM));
}
+
+/* EOF */
#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);
}
return 0;
}
+
+/* EOF */
#include <stdio.h>
#include "cmd.h"
+#include "options.h"
#define log(outFile, fmt, ...) \
{ \
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 */
#pragma once
-#define LOG2LINES_VERSION "2.1"
+#define LOG2LINES_VERSION "2.2"
/* EOF */