[DBGHELP] Add experimental rsym support. CORE-12773
authormjansen <mjansen@97493ccd-5924-5043-b1f5-66cb403b36ce>
Fri, 17 Feb 2017 16:18:15 +0000 (16:18 +0000)
committermjansen <mjansen@97493ccd-5924-5043-b1f5-66cb403b36ce>
Fri, 17 Feb 2017 16:18:15 +0000 (16:18 +0000)
git-svn-id: file:///srv/svn/reactos/trunk@73817 97493ccd-5924-5043-b1f5-66cb403b36ce

reactos/dll/win32/dbghelp/CMakeLists.txt
reactos/dll/win32/dbghelp/dbghelp_private.h
reactos/dll/win32/dbghelp/pe_module.c
reactos/dll/win32/dbghelp/rsym.c [new file with mode: 0644]

index ad93da4..7b0c384 100644 (file)
@@ -63,6 +63,7 @@ else()
         path.c
         pe_module.c
         rosstubs.c
+        rsym.c
         source.c
         stabs.c
         stack.c
index 41be44e..d6b2bbe 100644 (file)
@@ -714,6 +714,12 @@ extern BOOL         dwarf2_parse(struct module* module, unsigned long load_offse
 extern BOOL         dwarf2_virtual_unwind(struct cpu_stack_walk* csw, DWORD_PTR ip,
                                           CONTEXT* context, ULONG_PTR* cfa) DECLSPEC_HIDDEN;
 
+/* rsym.c */
+extern BOOL         rsym_parse(struct module* module, unsigned long load_offset,
+                                const void* rsym, int rsymlen) DECLSPEC_HIDDEN;
+
+
+
 /* stack.c */
 #ifndef DBGHELP_STATIC_LIB
 extern BOOL         sw_read_mem(struct cpu_stack_walk* csw, DWORD64 addr, void* ptr, DWORD sz) DECLSPEC_HIDDEN;
index a8469b5..dac94bb 100644 (file)
@@ -507,6 +507,32 @@ static BOOL pe_load_dwarf(struct module* module)
 
 #ifndef DBGHELP_STATIC_LIB
 /******************************************************************
+ *             pe_load_rsym
+ *
+ * look for ReactOS's own rsym format
+ */
+static BOOL pe_load_rsym(struct module* module)
+{
+    struct image_file_map*      fmap = &module->format_info[DFI_PE]->u.pe_info->fmap;
+    struct image_section_map    sect_rsym;
+    BOOL                        ret = FALSE;
+
+    if (pe_find_section(fmap, ".rossym", &sect_rsym))
+    {
+        const char* rsym = image_map_section(&sect_rsym);
+        if (rsym != IMAGE_NO_MAP)
+        {
+            ret = rsym_parse(module, module->module.BaseOfImage,
+                             rsym, image_get_map_size(&sect_rsym));
+        }
+        image_unmap_section(&sect_rsym);
+    }
+    TRACE("%s the RSYM debug info\n", ret ? "successfully loaded" : "failed to load");
+
+    return ret;
+}
+
+/******************************************************************
  *             pe_load_dbg_file
  *
  * loads a .dbg file
@@ -704,7 +730,9 @@ BOOL pe_load_debug_info(const struct process* pcs, struct module* module)
         ret = pe_load_dwarf(module) || ret;
         #ifndef DBGHELP_STATIC_LIB
         ret = pe_load_msc_debug_info(pcs, module) || ret;
+        ret = pe_load_rsym(module) || ret;
         #endif
+
         ret = ret || pe_load_coff_symbol_table(module); /* FIXME */
         /* if we still have no debug info (we could only get SymExport at this
          * point), then do the SymExport except if we have an ELF container,
diff --git a/reactos/dll/win32/dbghelp/rsym.c b/reactos/dll/win32/dbghelp/rsym.c
new file mode 100644 (file)
index 0000000..05c2725
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * PROJECT:         ReactOS dbghelp extension
+ * LICENSE:         GPLv2+ - See COPYING in the top level directory
+ * PURPOSE:         Parse rsym information for use with dbghelp
+ * PROGRAMMER:      Mark Jansen
+ */
+
+#include "dbghelp_private.h"
+#include <reactos/rossym.h>
+
+WINE_DEFAULT_DEBUG_CHANNEL(dbghelp_rsym);
+
+
+typedef struct rsym_file_entry_s
+{
+    const char* File;
+    unsigned Source;
+} rsym_file_entry_t;
+
+typedef struct rsym_func_entry_s
+{
+    ULONG_PTR Address;
+    struct symt_function* func;
+    struct rsym_func_entry_s* next;
+} rsym_func_entry_t;
+
+
+
+/******************************************************************
+ *             rsym_finalize_function (copied from stabs_finalize_function)
+ *
+ * Ends function creation: mainly:
+ * - cleans up line number information
+ * - tries to set up a debug-start tag (FIXME: heuristic to be enhanced)
+ */
+static void rsym_finalize_function(struct module* module, struct symt_function* func)
+{
+    IMAGEHLP_LINE64     il;
+    struct location     loc;
+
+    if (!func) return;
+    symt_normalize_function(module, func);
+    /* To define the debug-start of the function, we use the second line number.
+     * Not 100% bullet proof, but better than nothing
+     */
+    if (symt_fill_func_line_info(module, func, func->address, &il) &&
+        symt_get_func_line_next(module, &il))
+    {
+        loc.kind = loc_absolute;
+        loc.offset = il.Address - func->address;
+        symt_add_function_point(module, func, SymTagFuncDebugStart, 
+                                &loc, NULL);
+    }
+}
+
+
+static int is_metadata_sym(const char* name)
+{
+    ULONG len = name ? strlen(name) : 0;
+    return len > 3 && name[0] == '_' && name[1] != '_' && name[len-1] == '_' && name[len-2] == '_';
+};
+
+static int use_raw_address(const char* name)
+{
+    if (!name)
+        return 0;
+
+    if (!strcmp(name, "__ImageBase"))
+        return 1;
+
+    if (!strcmp(name, "__RUNTIME_PSEUDO_RELOC_LIST__"))
+        return 1;
+
+    return 0;
+}
+
+
+BOOL rsym_parse(struct module* module, unsigned long load_offset,
+                 const void* rsym_ptr, int rsymlen)
+{
+    const ROSSYM_HEADER* RosSymHeader;
+    const ROSSYM_ENTRY* First, *Last, *Entry;
+    const CHAR* Strings;
+
+    struct pool pool;
+    struct sparse_array file_table, func_table;
+    rsym_func_entry_t* first_func = NULL;
+
+
+    RosSymHeader = rsym_ptr;
+
+    if (RosSymHeader->SymbolsOffset < sizeof(ROSSYM_HEADER)
+        || RosSymHeader->StringsOffset < RosSymHeader->SymbolsOffset + RosSymHeader->SymbolsLength
+        || rsymlen < RosSymHeader->StringsOffset + RosSymHeader->StringsLength
+        || 0 != (RosSymHeader->SymbolsLength % sizeof(ROSSYM_ENTRY)))
+    {
+        WARN("Invalid ROSSYM_HEADER\n");
+        return FALSE;
+    }
+
+    First = (const ROSSYM_ENTRY *)((const char*)rsym_ptr + RosSymHeader->SymbolsOffset);
+    Last = First + RosSymHeader->SymbolsLength / sizeof(ROSSYM_ENTRY);
+    Strings = (const CHAR*)rsym_ptr + RosSymHeader->StringsOffset;
+
+    pool_init(&pool, 65536);
+    sparse_array_init(&file_table, sizeof(rsym_file_entry_t), 64);
+    sparse_array_init(&func_table, sizeof(rsym_func_entry_t), 128);
+
+    for (Entry = First; Entry != Last; Entry++)
+    {
+        ULONG Address = load_offset + Entry->Address;
+        if (!Entry->FileOffset)
+        {
+            rsym_func_entry_t* func = sparse_array_find(&func_table, Entry->FunctionOffset);
+
+            /* We do not want to define a data point where there is already a function! */
+            if (!func || func->Address != Address)
+            {
+                const char* SymbolName = Strings + Entry->FunctionOffset;
+                if (!is_metadata_sym(SymbolName))
+                {
+                    /* TODO: How should we determine the size? */
+                    ULONG Size = sizeof(ULONG);
+                    if (use_raw_address(SymbolName))
+                        Address = Entry->Address;
+
+                    symt_new_public(module, NULL, SymbolName, Address, Size);
+                }
+                else
+                {
+                    /* Maybe use it to fill some metadata? */
+                }
+            }
+        }
+        else
+        {
+            rsym_file_entry_t* file = sparse_array_find(&file_table, Entry->FileOffset);
+            rsym_func_entry_t* func = sparse_array_find(&func_table, Entry->FunctionOffset);
+
+            if (!file)
+            {
+                file = sparse_array_add(&file_table, Entry->FileOffset, &pool);
+                file->File = Strings + Entry->FileOffset;
+                file->Source = source_new(module, NULL, Strings + Entry->FileOffset);
+            }
+
+            if (!func)
+            {
+                func = sparse_array_add(&func_table, Entry->FunctionOffset, &pool);
+                func->func = symt_new_function(module, NULL, Strings + Entry->FunctionOffset,
+                    Address, 0, NULL);
+                func->Address = Address;
+                func->next = first_func;
+                first_func = func;
+            }
+
+            /* TODO: What if we have multiple chunks scattered around? */
+            symt_add_func_line(module, func->func, file->Source, Entry->SourceLine, Address - func->Address);
+        }
+    }
+
+    while (first_func)
+    {
+        /* TODO: Size of function? */
+        rsym_finalize_function(module, first_func->func);
+        first_func = first_func->next;
+    }
+
+    module->module.SymType = SymDia;
+    module->module.CVSig = 'R' | ('S' << 8) | ('Y' << 16) | ('M' << 24);
+    module->module.LineNumbers = TRUE;
+    module->module.GlobalSymbols = TRUE;
+    module->module.TypeInfo = FALSE;
+    module->module.SourceIndexed = TRUE;
+    module->module.Publics = TRUE;
+
+    pool_destroy(&pool);
+
+    return TRUE;
+}
+