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&a... ============================================================================== --- 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=4303... ============================================================================== --- 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&am... ============================================================================== --- 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@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);