Author: cfinck
Date: Sun Sep 13 04:19:14 2009
New Revision: 43036
URL: 
http://svn.reactos.org/svn/reactos?rev=43036&view=rev
Log:
Rewrite internal raddr2line caller and parser
- Use a better algorithm to ensure that our target line is a resolvable backtrace line.
- Mimic the output of Kdbg's own address resolver completely.
- Use a linked list of all EXE, DLL and SYS files inside "output-i386" instead
of looking them up in "reactos.dff".
  This also lets us resolve addresses in modules not present in "reactos.dff".
(e.g. drivers already available at setup)
- Use the correct path if ROS_OUTPUT is not set.
Modified:
    trunk/tools/sysreg2/console.c
    trunk/tools/sysreg2/raddr2line.c
    trunk/tools/sysreg2/sysreg.h
    trunk/tools/sysreg2/virt.c
Modified: trunk/tools/sysreg2/console.c
URL:
http://svn.reactos.org/svn/reactos/trunk/tools/sysreg2/console.c?rev=43036&…
==============================================================================
--- trunk/tools/sysreg2/console.c [iso-8859-1] (original)
+++ trunk/tools/sysreg2/console.c [iso-8859-1] Sun Sep 13 04:19:14 2009
@@ -160,7 +160,7 @@
             }
             /* Output the line, raddr2line the included addresses if necessary */
-                       if ((KdbgHit == 1) &&
(ResolveAddressFromFile(Raddr2LineBuffer, BUFFER_SIZE, Buffer)))
+            if (KdbgHit == 1 && ResolveAddressFromFile(Raddr2LineBuffer,
sizeof(Raddr2LineBuffer), Buffer))
                 printf("%s", Raddr2LineBuffer);
             else
                 printf("%s", Buffer);
Modified: trunk/tools/sysreg2/raddr2line.c
URL:
http://svn.reactos.org/svn/reactos/trunk/tools/sysreg2/raddr2line.c?rev=430…
==============================================================================
--- trunk/tools/sysreg2/raddr2line.c [iso-8859-1] (original)
+++ trunk/tools/sysreg2/raddr2line.c [iso-8859-1] Sun Sep 13 04:19:14 2009
@@ -8,112 +8,182 @@
 #include "sysreg.h"
-bool GetPackagePath(char* Buffer, int BuffSize, char* Module)
+static void RecurseModuleDirectory(const char* Directory, ModuleListEntry** LastElement)
 {
-    char* ptr;
-    FILE* fp;
-    int i;
+    char* EntryPath;
+    char* Period;
+    DIR* dir;
+    struct dirent* dp;
+    struct stat statbuf;
-    fp = fopen("boot/bootdata/packages/reactos.dff", "r");
-    if (fp)
+    dir = opendir(Directory);
+    if(!dir)
+        return;
+
+    while(dp = readdir(dir))
     {
-        while(fgets(Buffer, BuffSize,fp))
+        if(*dp->d_name == '.')
+            continue;
+
+        EntryPath = (char*)malloc(strlen(Directory) + strlen(dp->d_name) + 2);
+        strcpy(EntryPath, Directory);
+        strcat(EntryPath, "/");
+        strcat(EntryPath, dp->d_name);
+
+        if(stat(EntryPath, &statbuf) == -1)
         {
-            if (strstr(Buffer, Module))
+            free(EntryPath);
+            continue;
+        }
+
+        if(statbuf.st_mode & S_IFDIR)
+        {
+            RecurseModuleDirectory(EntryPath, LastElement);
+            free(EntryPath);
+        }
+        else
+        {
+            Period = strchr(dp->d_name, '.');
+
+            /* A file needs to have one of the following extensions to be a valid module
*/
+            if(!Period || (strcasecmp(Period, ".exe") &&
strcasecmp(Period, ".dll") && strcasecmp(Period, ".sys")))
             {
-                ptr = strchr(Buffer, ' ');
-                if (ptr)
-                    *ptr = '\0';
+                free(EntryPath);
+                continue;
+            }
-                for (i = 0; i < strlen(Buffer); i++)
-                {
-                    if (Buffer[i] == '\\')
-                        Buffer[i] = '/';
-                }
-                fclose(fp);
-                return true;
-            }
-        }
-        fclose(fp);
-    }
-    return false;
-}
+            (*LastElement)->Next = (ModuleListEntry*)malloc(sizeof(ModuleListEntry));
+            *LastElement = (*LastElement)->Next;
+            (*LastElement)->Next = NULL;
-bool ResolveAddressFromFile(char* Buffer, int BuffSize, char* Data)
-{
-    int Resolved = 0;
-    char* sep;
-    char* sep2;
-    char Module[32];
-    char Addr[20];
-    char Command[256];
-    char PkgData[80];
-    char emptystr[] = "";
-
-    if ((strstr(Data, ":>")) && (!strchr(Data, ')')))
-    {
-        sep = strchr(Data, ':');
-        if (sep)
-        {
-            strncpy(Module, Data + 1, (int) (sep - Data) - 1);
-            Module[(int)(sep-Data)-2] = '\0';
-            sep2 = strchr(Data, '>');
-            strncpy(Addr, Data + (sep - Data + 1), (int) (sep2 - sep) -1);
-            Addr[(int)(sep2-sep)-1] = '\0';
-            Resolved = 1;
+            (*LastElement)->Module = (char*)malloc(strlen(dp->d_name) + 1);
+            strcpy((*LastElement)->Module, dp->d_name);
+            (*LastElement)->Path = EntryPath;
         }
     }
-    sep = strchr(Data, '+');
-    if ((sep) && strstr(Data, ":\\"))
+    closedir(dir);
+}
+
+void InitializeModuleList()
+{
+    ModuleListEntry* LastElement;
+
+    ModuleList = (ModuleListEntry*)malloc(sizeof(ModuleListEntry));
+    ModuleList->Next = NULL;
+    LastElement = ModuleList;
+
+    RecurseModuleDirectory(OutputPath, &LastElement);
+}
+
+void CleanModuleList()
+{
+    ModuleListEntry* CurrentElement;
+    ModuleListEntry* PreviousElement;
+
+    CurrentElement = ModuleList->Next;
+
+    while(CurrentElement)
     {
-        sep2 = strchr(Data + (sep - Data), ' ');
-        strncpy(Addr, Data + (sep - Data + 1), (int) (sep2 - sep) - 1);
-        Addr[(int)(sep2-sep) - 1] = '\0';
-        sep = strrchr(Data, '\\');
-        strcpy(Module, sep + 1);
-        Module[strlen(Module) - 2] = '\0';
-        Resolved = 2;
+        free(CurrentElement->Module);
+        free(CurrentElement->Path);
+
+        PreviousElement = CurrentElement;
+        CurrentElement = CurrentElement->Next;
+        free(PreviousElement);
     }
-    if (Resolved > 0)
+    free(ModuleList);
+}
+
+static ModuleListEntry* FindModule(const char* Module)
+{
+    ModuleListEntry* CurrentElement;
+
+    CurrentElement = ModuleList->Next;
+
+    while(CurrentElement)
     {
-        if (GetPackagePath(PkgData, sizeof(PkgData), Module))
+        if(!strcmp(CurrentElement->Module, Module))
+            return CurrentElement;
+
+        CurrentElement = CurrentElement->Next;
+    }
+
+    return NULL;
+}
+
+bool ResolveAddressFromFile(char* Buffer, size_t BufferSize, const char* Data)
+{
+    bool ReturnValue = false;
+    char* Address = NULL;
+    char* AddressStart;
+    char Command[256];
+    char* Module = NULL;
+    char* pBuffer;
+    FILE* Process;
+    ModuleListEntry* ModuleEntry;
+    size_t AddressLength;
+
+    /* A resolvable backtrace line has to look like this:
+       <abcdefg.dll:123a>
+    */
+    if(*Data != '<')
+        return false;
+
+    AddressStart = strchr(Data, ':');
+
+    if(!AddressStart)
+        return false;
+
+    ++AddressStart;
+    AddressLength = strspn(AddressStart, "1234567890abcdefABCDEF");
+
+    if(!AddressLength || AddressStart[AddressLength] != '>')
+        return false;
+
+    /* Ok, this looks like a backtrace line we can resolve */
+    Module = (char*)malloc(AddressStart - Data - 1);
+    strncpy(Module, Data + 1, AddressStart - Data - 2);
+    Module[AddressStart - Data - 2] = 0;
+
+    Address = (char*)malloc(AddressLength + 1);
+    strncpy(Address, AddressStart, AddressLength);
+    Address[AddressLength] = 0;
+
+    /* Try to find the path to this module */
+    if(ModuleEntry = FindModule(Module))
+    {
+        /* Run raddr2line */
+        sprintf(Command, "%s/tools/rsym/raddr2line %s %s 2>/dev/null",
OutputPath, ModuleEntry->Path, Address);
+        Process = popen(Command, "r");
+
+        if(!feof(Process))
         {
-            const char* outdir = getenv("ROS_OUTPUT");
-            char* ptr;
-            if (!outdir)
-                outdir = emptystr;
-            sprintf(Command, "%s/tools/rsym/raddr2line %s/%s %s 2>&1",
-                    outdir, outdir, PkgData, Addr);
-            FILE* p = popen(Command, "r");
-            char buf[100] = {'\0'};
-            while(feof(p)==0)
+            pBuffer = &Buffer[AddressStart - Data + AddressLength];
+            strncpy(Buffer, Data, pBuffer - Buffer);
+
+            *pBuffer++ = ' ';
+            *pBuffer++ = '(';
+
+            if(fgets(pBuffer, BufferSize - (pBuffer - Buffer), Process))
             {
-                fgets(buf,100,p);
-                if (strstr(buf, "error"))
-                    strcpy(buf, "(no debug info)");
-                ptr = strchr(buf, '\n');
-                if (ptr)
-                    *ptr = '\0';
-                ptr = strchr(Data, '>');
-                if (ptr)
-                    *ptr = '\0';
-                if (Resolved == 2)
-                {
-                    ptr = strchr(Data, '\n');
-                    if (ptr)
-                        *ptr = '\0';
-                }
-                strcpy(Buffer, Data);
-                strcat(Buffer, " ");
-                if (Resolved == 2)
-                    strcat(Buffer, "<");
-                strcat(Buffer, buf);
-                strcat(Buffer, ">\n");
-                return true;
+                pBuffer += strlen(pBuffer) - 1;
+
+                *pBuffer++ = ')';
+                *pBuffer++ = '>';
+                *pBuffer++ = '\n';
+                *pBuffer = 0;
+
+                ReturnValue = true;
             }
         }
+
+        pclose(Process);
     }
-    return false;
+
+    free(Module);
+    free(Address);
+
+    return ReturnValue;
 }
Modified: trunk/tools/sysreg2/sysreg.h
URL:
http://svn.reactos.org/svn/reactos/trunk/tools/sysreg2/sysreg.h?rev=43036&a…
==============================================================================
--- trunk/tools/sysreg2/sysreg.h [iso-8859-1] (original)
+++ trunk/tools/sysreg2/sysreg.h [iso-8859-1] Sun Sep 13 04:19:14 2009
@@ -6,6 +6,7 @@
  *              Copyright 2009 Colin Finck <colin(a)reactos.org>
  */
+#include <dirent.h>
 #include <fcntl.h>
 #include <libvirt.h>
 #include <poll.h>
@@ -21,19 +22,24 @@
 #include <libxml/tree.h>
 #include <libxml/xpath.h>
 #include <libxml/xpathInternals.h>
+#include <sys/stat.h>
 #include <sys/sysinfo.h>
+#include <sys/types.h>
 #define EXIT_CHECKPOINT_REACHED     0
 #define EXIT_CONTINUE               1
 #define EXIT_DONT_CONTINUE          2
 #define NUM_STAGES                  3
-typedef struct {
+typedef struct _stage
+{
     char BootDevice[8];
     char Checkpoint[80];
-} stage;
+}
+stage;
-typedef struct {
+typedef struct _Settings
+{
     int Timeout;
     char Filename[255];
     char Name[80];
@@ -42,9 +48,16 @@
     stage Stage[3];
     unsigned int MaxCacheHits;
     unsigned int MaxRetries;
-} Settings;
+}
+Settings;
-Settings AppSettings;
+typedef struct _ModuleListEntry
+{
+    struct _ModuleListEntry* Next;
+    char* Module;
+    char* Path;
+}
+ModuleListEntry;
 /* utils.c */
 char* ReadFile (const char* filename);
@@ -58,5 +71,11 @@
 int ProcessDebugData(const char* tty, int timeout, int stage);
 /* raddr2line.c */
-bool GetPackagePath(char* Buffer, int BuffSize, char* Module);
-bool ResolveAddressFromFile(char* Buffer, int BuffSize, char* Data);
+void InitializeModuleList();
+void CleanModuleList();
+bool ResolveAddressFromFile(char* Buffer, size_t BufferSize, const char* Data);
+
+/* virt.c */
+extern const char* OutputPath;
+extern Settings AppSettings;
+extern ModuleListEntry* ModuleList;
Modified: trunk/tools/sysreg2/virt.c
URL:
http://svn.reactos.org/svn/reactos/trunk/tools/sysreg2/virt.c?rev=43036&…
==============================================================================
--- trunk/tools/sysreg2/virt.c [iso-8859-1] (original)
+++ trunk/tools/sysreg2/virt.c [iso-8859-1] Sun Sep 13 04:19:14 2009
@@ -7,6 +7,11 @@
  */
 #include "sysreg.h"
+
+const char DefaultOutputPath[] = "output-i386";
+const char* OutputPath;
+Settings AppSettings;
+ModuleListEntry* ModuleList;
 bool GetConsole(virDomainPtr vDomPtr, char* console)
 {
@@ -146,7 +151,6 @@
     }
     return vDomPtr;
 }
-
 int main(int argc, char **argv)
 {
@@ -161,6 +165,13 @@
     unsigned int Retries;
     unsigned int Stage;
+    /* Get the output path to the built ReactOS files */
+    OutputPath = getenv("ROS_OUTPUT");
+    if(!OutputPath)
+        OutputPath = DefaultOutputPath;
+
+    InitializeModuleList();
+
     if (argc == 2)
         strcpy(config, argv[1]);
     else
@@ -252,6 +263,8 @@
 cleanup:
+    CleanModuleList();
+
     if (vConn)
         virConnectClose(vConn);