[PATCH 6/6] [DbGHelp]: while loading MSC debug info, don't handle public symbol at once, but delay their handling after all other symbols are loaded

Eric Pouech eric.pouech at orange.fr
Sat Sep 6 15:20:19 CDT 2008


- this allows to handle properly addresses between public and real symbols
- this should also increase drastically the performance of .dbg/.pdb loading

A+
---

 dlls/dbghelp/msc.c |  223 ++++++++++++++++++++++++++++++++++++----------------
 1 files changed, 155 insertions(+), 68 deletions(-)


diff --git a/dlls/dbghelp/msc.c b/dlls/dbghelp/msc.c
index 1a28091..9b73635 100644
--- a/dlls/dbghelp/msc.c
+++ b/dlls/dbghelp/msc.c
@@ -1300,9 +1300,28 @@ static void codeview_add_func_linenum(struct module* module,
     }
 }
 
+static inline void codeview_add_variable(const struct msc_debug_info* msc_dbg,
+                                         struct symt_compiland* compiland,
+                                         const char* name,
+                                         unsigned segment, unsigned offset,
+                                         unsigned symtype, BOOL is_local, BOOL force)
+{
+    if (name && *name)
+    {
+        unsigned        address = codeview_get_address(msc_dbg, segment, offset);
+
+        if (force || !symt_find_nearest(msc_dbg->module, address))
+        {
+            symt_new_global_variable(msc_dbg->module, compiland,
+                                     name, is_local, address, 0,
+                                     codeview_get_type(symtype, FALSE));
+        }
+    }
+}
+
 static int codeview_snarf(const struct msc_debug_info* msc_dbg, const BYTE* root, 
                           int offset, int size,
-                          struct codeview_linetab* linetab)
+                          struct codeview_linetab* linetab, BOOL do_globals)
 {
     struct symt_function*               curr_func = NULL;
     int                                 i, length;
@@ -1333,51 +1352,34 @@ static int codeview_snarf(const struct msc_debug_info* msc_dbg, const BYTE* root
          */
 	case S_GDATA_V1:
 	case S_LDATA_V1:
-            symt_new_global_variable(msc_dbg->module, compiland,
-                                     terminate_string(&sym->data_v1.p_name), sym->generic.id == S_LDATA_V1,
-                                     codeview_get_address(msc_dbg, sym->data_v1.segment, sym->data_v1.offset),
-                                     0,
-                                     codeview_get_type(sym->data_v1.symtype, FALSE));
+            if (do_globals)
+                codeview_add_variable(msc_dbg, compiland, terminate_string(&sym->data_v1.p_name),
+                                      sym->data_v1.segment, sym->data_v1.offset, sym->data_v1.symtype,
+                                      sym->generic.id == S_LDATA_V1, TRUE);
 	    break;
 	case S_GDATA_V2:
 	case S_LDATA_V2:
-            name = terminate_string(&sym->data_v2.p_name);
-            if (name)
-                symt_new_global_variable(msc_dbg->module, compiland,
-                                         name, sym->generic.id == S_LDATA_V2,
-                                         codeview_get_address(msc_dbg, sym->data_v2.segment, sym->data_v2.offset),
-                                         0,
-                                         codeview_get_type(sym->data_v2.symtype, FALSE));
+            if (do_globals)
+                codeview_add_variable(msc_dbg, compiland, terminate_string(&sym->data_v2.p_name),
+                                      sym->data_v2.segment, sym->data_v2.offset, sym->data_v2.symtype,
+                                      sym->generic.id == S_LDATA_V2, TRUE);
 	    break;
 	case S_GDATA_V3:
 	case S_LDATA_V3:
-            if (*sym->data_v3.name)
-                symt_new_global_variable(msc_dbg->module, compiland,
-                                         sym->data_v3.name,
-                                         sym->generic.id == S_LDATA_V3,
-                                         codeview_get_address(msc_dbg, sym->data_v3.segment, sym->data_v3.offset),
-                                         0,
-                                         codeview_get_type(sym->data_v3.symtype, FALSE));
+            if (do_globals)
+                codeview_add_variable(msc_dbg, compiland, sym->data_v3.name,
+                                      sym->data_v3.segment, sym->data_v3.offset, sym->data_v3.symtype,
+                                      sym->generic.id == S_LDATA_V3, TRUE);
 	    break;
 
-	case S_PUB_V1: /* FIXME is this really a 'data_v1' structure ?? */
-            if (!(dbghelp_options & SYMOPT_NO_PUBLICS))
-            {
-                symt_new_public(msc_dbg->module, compiland,
-                                terminate_string(&sym->data_v1.p_name), 
-                                codeview_get_address(msc_dbg, sym->data_v1.segment, sym->data_v1.offset),
-                                1, TRUE /* FIXME */, TRUE /* FIXME */);
-            }
+        /* Public symbols */
+	case S_PUB_V1:
+	case S_PUB_V2:
+        case S_PUB_V3:
+        case S_PUB_FUNC1_V3:
+        case S_PUB_FUNC2_V3:
+            /* will be handled later on in codeview_snarf_public */
             break;
-	case S_PUB_V2: /* FIXME is this really a 'data_v2' structure ?? */
-            if (!(dbghelp_options & SYMOPT_NO_PUBLICS))
-            {
-                symt_new_public(msc_dbg->module, compiland,
-                                terminate_string(&sym->data_v2.p_name), 
-                                codeview_get_address(msc_dbg, sym->data_v2.segment, sym->data_v2.offset),
-                                1, TRUE /* FIXME */, TRUE /* FIXME */);
-            }
-	    break;
 
         /*
          * Sort of like a global function, but it just points
@@ -1711,29 +1713,6 @@ static int codeview_snarf(const struct msc_debug_info* msc_dbg, const BYTE* root
             length += (*name + 1 + 3) & ~3;
             break;
 
-        case S_PUB_V3:
-            if (!(dbghelp_options & SYMOPT_NO_PUBLICS))
-            {
-                symt_new_public(msc_dbg->module, compiland,
-                                sym->data_v3.name, 
-                                codeview_get_address(msc_dbg, sym->data_v3.segment, sym->data_v3.offset),
-                                1, FALSE /* FIXME */, FALSE);
-            }
-            break;
-        case S_PUB_FUNC1_V3:
-        case S_PUB_FUNC2_V3: /* using a data_v3 isn't what we'd expect */
-#if 0
-            /* FIXME: this is plain wrong (from a simple test) */
-            if (!(dbghelp_options & SYMOPT_NO_PUBLICS))
-            {
-                symt_new_public(msc_dbg->module, compiland,
-                                sym->data_v3.name, 
-                                codeview_get_address(msc_dbg, sym->data_v3.segment, sym->data_v3.offset),
-                                1, TRUE /* FIXME */, TRUE);
-            }
-#endif
-            break;
-
         case S_MSTOOL_V3: /* just to silence a few warnings */
             break;
 
@@ -1763,6 +1742,107 @@ static int codeview_snarf(const struct msc_debug_info* msc_dbg, const BYTE* root
     return TRUE;
 }
 
+static int codeview_snarf_public(const struct msc_debug_info* msc_dbg, const BYTE* root,
+                                 int offset, int size)
+
+{
+    int                                 i, length;
+    struct symt_compiland*              compiland = NULL;
+
+    /*
+     * Loop over the different types of records and whenever we
+     * find something we are interested in, record it and move on.
+     */
+    for (i = offset; i < size; i += length)
+    {
+        const union codeview_symbol* sym = (const union codeview_symbol*)(root + i);
+        length = sym->generic.len + 2;
+        if (i + length > size) break;
+        if (!sym->generic.id || length < 4) break;
+        if (length & 3) FIXME("unpadded len %u\n", length);
+
+        switch (sym->generic.id)
+        {
+	case S_PUB_V1: /* FIXME is this really a 'data_v1' structure ?? */
+            if (!(dbghelp_options & SYMOPT_NO_PUBLICS))
+            {
+                symt_new_public(msc_dbg->module, compiland,
+                                terminate_string(&sym->data_v1.p_name),
+                                codeview_get_address(msc_dbg, sym->data_v1.segment, sym->data_v1.offset),
+                                1, TRUE /* FIXME */, TRUE /* FIXME */);
+            }
+            break;
+	case S_PUB_V2: /* FIXME is this really a 'data_v2' structure ?? */
+            if (!(dbghelp_options & SYMOPT_NO_PUBLICS))
+            {
+                symt_new_public(msc_dbg->module, compiland,
+                                terminate_string(&sym->data_v2.p_name),
+                                codeview_get_address(msc_dbg, sym->data_v2.segment, sym->data_v2.offset),
+                                1, TRUE /* FIXME */, TRUE /* FIXME */);
+            }
+	    break;
+
+        case S_PUB_V3:
+            if (!(dbghelp_options & SYMOPT_NO_PUBLICS))
+            {
+                symt_new_public(msc_dbg->module, compiland,
+                                sym->data_v3.name,
+                                codeview_get_address(msc_dbg, sym->data_v3.segment, sym->data_v3.offset),
+                                1, FALSE /* FIXME */, FALSE);
+            }
+            break;
+        case S_PUB_FUNC1_V3:
+        case S_PUB_FUNC2_V3: /* using a data_v3 isn't what we'd expect */
+#if 0
+            /* FIXME: this is plain wrong (from a simple test) */
+            if (!(dbghelp_options & SYMOPT_NO_PUBLICS))
+            {
+                symt_new_public(msc_dbg->module, compiland,
+                                sym->data_v3.name,
+                                codeview_get_address(msc_dbg, sym->data_v3.segment, sym->data_v3.offset),
+                                1, TRUE /* FIXME */, TRUE);
+            }
+#endif
+            break;
+        /*
+         * Global and local data symbols.  We don't associate these
+         * with any given source file.
+         */
+	case S_GDATA_V1:
+	case S_LDATA_V1:
+            codeview_add_variable(msc_dbg, compiland, terminate_string(&sym->data_v1.p_name),
+                                  sym->data_v1.segment, sym->data_v1.offset, sym->data_v1.symtype,
+                                  sym->generic.id == S_LDATA_V1, FALSE);
+	    break;
+	case S_GDATA_V2:
+	case S_LDATA_V2:
+            codeview_add_variable(msc_dbg, compiland, terminate_string(&sym->data_v2.p_name),
+                                  sym->data_v2.segment, sym->data_v2.offset, sym->data_v2.symtype,
+                                  sym->generic.id == S_LDATA_V2, FALSE);
+	    break;
+	case S_GDATA_V3:
+	case S_LDATA_V3:
+            codeview_add_variable(msc_dbg, compiland, sym->data_v3.name,
+                                  sym->data_v3.segment, sym->data_v3.offset, sym->data_v3.symtype,
+                                  sym->generic.id == S_LDATA_V3, FALSE);
+	    break;
+        /*
+         * These are special, in that they are always followed by an
+         * additional length-prefixed string which is *not* included
+         * into the symbol length count.  We need to skip it.
+         */
+	case S_PROCREF_V1:
+	case S_DATAREF_V1:
+	case S_LPROCREF_V1:
+            length += (((const char*)sym)[length] + 1 + 3) & ~3;
+            break;
+        }
+        msc_dbg->module->sortlist_valid = TRUE;
+    }
+    msc_dbg->module->sortlist_valid = FALSE;
+    return TRUE;
+}
+
 /*========================================================================
  * Process PDB file.
  */
@@ -2237,6 +2317,7 @@ static BOOL pdb_process_internal(const struct process* pcs,
     if (symbols_image)
     {
         PDB_SYMBOLS symbols;
+        BYTE*       globalimage;
         BYTE*       modimage;
         BYTE*       file;
         int         header_size = 0;
@@ -2257,13 +2338,11 @@ static BOOL pdb_process_internal(const struct process* pcs,
         pdb_process_symbol_imports(pcs, msc_dbg, &symbols, symbols_image, image, pdb_lookup, module_index);
 
         /* Read global symbol table */
-        modimage = pdb_read_file(image, pdb_lookup, symbols.gsym_file);
-        if (modimage)
+        globalimage = pdb_read_file(image, pdb_lookup, symbols.gsym_file);
+        if (globalimage)
         {
-            codeview_snarf(msc_dbg, modimage, 0, 
-                           pdb_get_file_size(pdb_lookup, symbols.gsym_file), NULL);
-
-            pdb_free(modimage);
+            codeview_snarf(msc_dbg, globalimage, 0,
+                           pdb_get_file_size(pdb_lookup, symbols.gsym_file), NULL, FALSE);
         }
 
         /* Read per-module symbol / linenumber tables */
@@ -2290,7 +2369,7 @@ static BOOL pdb_process_internal(const struct process* pcs,
 
                 if (sfile.symbol_size)
                     codeview_snarf(msc_dbg, modimage, sizeof(DWORD),
-                                   sfile.symbol_size, linetab);
+                                   sfile.symbol_size, linetab, TRUE);
 
                 pdb_free(modimage);
             }
@@ -2298,6 +2377,14 @@ static BOOL pdb_process_internal(const struct process* pcs,
             file_name += strlen(file_name) + 1;
             file = (BYTE*)((DWORD)(file_name + strlen(file_name) + 1 + 3) & ~3);
         }
+        /* finish the remaining public and global information */
+        if (globalimage)
+        {
+            codeview_snarf_public(msc_dbg, globalimage, 0,
+                                  pdb_get_file_size(pdb_lookup, symbols.gsym_file));
+
+            pdb_free(globalimage);
+        }
     }
     else
         pdb_process_symbol_imports(pcs, msc_dbg, NULL, NULL, image, pdb_lookup, 
@@ -2462,7 +2549,7 @@ static BOOL codeview_process_info(const struct process* pcs,
                                                      TRUE);
 
                 codeview_snarf(msc_dbg, msc_dbg->root + ent->lfo, sizeof(DWORD),
-                               ent->cb, linetab);
+                               ent->cb, linetab, TRUE);
             }
         }
 





More information about the wine-patches mailing list