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);