Search code examples
visual-studiowindbgdebug-symbols

Symbol server using symstore.exe with pointers and compress.exe does not work


I want to create a symbol server using symstore from Microsoft with symbol storage separated from actual symbol server, but I am unable to get pointers and compression work together. For testing purposes I have created a server like that on my local drive.

I have added a symbol path in my environment (_NT_SYMBOL_PATH=srv*symbol_server_path but I have tried with _NT_SYMBOL_PATH=srv*my_symbol_cache*symbol_server_path). Basically what I do right now is:

  1. Add symbol to symbol server using command:

    symstore /p /r /f symbol_file_path /s symbol_server_path /t product
    

    Where symbol_file_path is an UNC path.

  2. Compress that symbol with compress.exe

    compress.exe -R -S symbol_file_path
    

    Where symbol_file_path is an UNC path.

  3. Check if compressed file exists - if yes, delete uncompressed symbol

As far as I can tell this is correct with the statement from symstore docs where you can read:

  1. Use SymStore with the /p option to store pointers to the symbol files. After SymStore finishes, compress the files that the pointers refer to.

So what I do should basically work, right? Well - it's not...

I have tried to debug some dump that should work with symbols I have stored but what I see in Visual Studio is an "System cannot read from the specified device" error. I have tried to use elevated privileges or change symbol server path to local path (basically tried both UNC and local path) and it didnt't really work.

I thought that maybe compression really doesn't work with pointers in SymStore as it is stated in /compress parameter description on SymStore Command-Line Options

/compress - Causes SymStore to create a compressed version of each file copied to the symbol store instead of using an uncompressed copy of the file. This option is only valid when storing files and not pointers, and cannot be used with the /p option.

But... I can see that debugger is trying to load that symbol even when path differs from the one in pointer file and it does create a 0 byte file with the correct name of symbol in my symbol cache.

Any idea what is happening or what am I doing wrong?


Update:

I have clarified above that symbol_file_path is an UNC path in my case, and also that I do include '/t ' in my symstore calls.

Considering blabb response - After successfuly compressing and deleting step - my windbg and visual studio when it tries to load *.pd_ file output welcomes me with an error:

System cannot read from the specified device

After trying to reload symbol in windbg for my .exe with

 .reload /f <exe_file_name>.exe

With sympath

srv*<symbol_cache>*<symbol_server>*http://msdl.microsoft.com/download/symbols

I have received following output:

SYMSRV:  BYINDEX: 0x3C
         <symbol_cache>*<symbol_server>*http://msdl.microsoft.com/download/symbols
         <exe_file_name>.pdb
         <pdb_hash>
SYMSRV:  <symbol_cache>\<exe_file_name>.pdb\<pdb_hash>\<exe_file_name>.pdb - file not found
SYMSRV:  <symbol_server>\<exe_file_name>.pdb\<pdb_hash>\<exe_file_name>.pdb - file not found
SYMSRV:  The file.ptr file message is: <symbol_storage_path>\<exe_file_name>.pdb
SYMSRV:  <symbol_server>\<exe_file_name>.pdb\<pdb_hash>\file.ptr
SYMSRV:  <symbol_storage_path>\<exe_file_name>.pdb - file not found
SYMSRV:  <symbol_cache>\<exe_file_name>.pdb\<pdb_hash>\<exe_file_name>.pdb - file not found
SYMSRV:  <symbol_storage_path>\<exe_file_name>.pd_
         System nie może czytać z określonego urządzenia. <-- which is equivalent to "System cannot read from the specified device"
SYMSRV:  PATH: C:\ProgramData\dbg\sym\<exe_file_name>.pdb\<pdb_hash>\<exe_file_name>.pdb
DBGHELP: ........ DIA E_PDB_FILE_SYSTEM error from 971
DBGHELP: ........ DIA E_PDB_FILE_SYSTEM error from 971
DBGHELP: C:\ProgramData\dbg\sym\<exe_file_name>.pdb\<pdb_hash>\<exe_file_name>.pdb - drive not ready
DBGHELP: <path_not_included_in_symbol_path>\<exe_file_name>.pdb - file not found
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for <exe_file_name>.exe - 
DBGHELP: <exe_file_name> - export symbols

************* Symbol Loading Error Summary **************
Module name            Error
<exe_file_name>      Drive not ready : srv*<symbol_cache>*<symbol_server>*http://msdl.microsoft.com/download/symbols
                This error indicates a .pdb file related failure.
                The error is likely caused by a network glitch or out of disk error.
                Using a local cache (CACHE*) can work around networking issues.

When I have changed my sympath to

cache*<symbol_cache>*<symbol_server>*http://msdl.microsoft.com/download/symbols 

I have received following output:

SYMSRV:  BYINDEX: 0x2F
         <symbol_cache>*<symbol_server>*http://msdl.microsoft.com/download/symbols
         <exe_file_name>.pdb
         <pdb_hash>
SYMSRV:  PATH: <symbol_cache>\<exe_file_name>.pdb\<pdb_hash>\<exe_file_name>.pdb
DBGHELP: ........ DIA E_PDB_FILE_SYSTEM error from 971
DBGHELP: ........ DIA E_PDB_FILE_SYSTEM error from 971
**DBGHELP: <symbol_cache>\<exe_file_name>.pdb\<pdb_hash>\<exe_file_name>.pdb - drive not ready** <- this is where my problem is
DBGHELP: Failed copying the file '<path_not_included_in_symbol_path>\<exe_file_name>.pdb' to the cache
DBGHELP: Failed copying the file '<path_not_included_in_symbol_path>\<exe_file_name>.pdb' to the cache
DBGHELP: <path_not_included_in_symbol_path>\<exe_file_name>.pdb - file not found
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for <exe_file_name>.exe - 
DBGHELP: <exe_file_name> - export symbols

************* Symbol Loading Error Summary **************
Module name            Error
<exe_file_name>      Drive not ready : <symbol_cache>\<exe_file_name>.pdb\<pdb_hash>\<exe_file_name>.pdb
                This error indicates a .pdb file related failure.
                The error is likely caused by a network glitch or out of disk error.
                Using a local cache (CACHE*) can work around networking issues.

With all this - I am unable to load that symbol. I had no issues when it was not compressed.

Every time I try to load the symbol 0 byte file is created in my symbol cache. I hope this clarifies what is happening.


Update 2

Changing _NT_SYMBOL_PATH to

cache*<symbol_cache>;srv*<symbol_cache>*<symbol_server>

Did not help. Visual Studio copied *.pd_ file, windbg didn't. Both have the same problem - .pd_ is not uncompressed to .pdb, but they try to read from .pdb file which doesn't exist or it has 0 byte size.


Solution

  • symstore /p /r /f symbol_file_path /s symbol_server_path

    i just tried this and symstore complains the file path must be a network path or /l switch must be used for local directory

    D:\>md symstotest
    
    D:\>cd symstotest
    
    D:\symstotest>symstore add /r /p /f e:\test\zwopenproc\*.*  /s .
    SYMSTORE ERROR: Class: Syntax. Desc: /f must be followed by a network path when storing po
    inters unless /l is used.
    
    SYMSTORE: Number of pointers stored = 0
    SYMSTORE: Number of errors = 0
    SYMSTORE: Number of pointers ignored = 0
    
    D:\symstotest>
    

    what is your case ??

    if i use a local Directory switch /l with say a dir called e:\test\somedir\*.* symstore insists i have to provide /t

    D:\symstotest>symstore add /r /p /l /f e:\test\zwopenproc\*.*  /s .
    SYMSTORE ERROR: Class: Syntax. Desc: '/t <product>' is required with this add type.
    
    SYMSTORE: Number of pointers stored = 0
    SYMSTORE: Number of errors = 0
    SYMSTORE: Number of pointers ignored = 0
    
    D:\symstotest>
    

    again did you comply ??

    on complying symstore seems to be happy and seems to create this directory structure

    D:\symstotest>symstore add /r /p /l /t win7 /f e:\test\zwopenproc\*.*  /s .
    Finding ID...  0000000001
    
    SYMSTORE: Number of pointers stored = 3
    SYMSTORE: Number of errors = 0
    SYMSTORE: Number of pointers ignored = 3
    
    D:\symstotest>tree /a /f
    
    D:.
    |   pingme.txt
    |
    +---000Admin
    |       0000000001
    |       history.txt
    |       lastid.txt
    |       server.txt
    |
    +---vc140.pdb
    |   \---76CA8C231EF1443195D38A95A8A86958
    |           file.ptr
    |           refs.ptr
    |
    +---zwopenproc.exe
    |   \---57B75BB84a000
    |           file.ptr
    |           refs.ptr
    |
    \---zwopenproc.pdb
        \---E3CA63D5CD7544E9BC90709CA8D04042a
                file.ptr
                refs.ptr
    

    the respective *.ptr files seems to contain data as documented in manual

    D:\symstotest>for /F %I in ('dir /s /b *.ptr') do cat %I
    
    D:\symstotest>cat D:\symstotest\vc140.pdb\76CA8C231EF1443195D38A95A8A86958\file.ptr
    e:\test\zwopenproc\vc140.pdb
    D:\symstotest>cat D:\symstotest\vc140.pdb\76CA8C231EF1443195D38A95A8A86958\refs.ptr
    0000000001,ptr,"e:\test\zwopenproc\vc140.pdb",typ,"",,,
    D:\symstotest>cat D:\symstotest\zwopenproc.exe\57B75BB84a000\file.ptr
    e:\test\zwopenproc\zwopenproc.exe
    D:\symstotest>cat D:\symstotest\zwopenproc.exe\57B75BB84a000\refs.ptr
    0000000001,ptr,"e:\test\zwopenproc\zwopenproc.exe",bin,"",,,
    D:\symstotest>cat D:\symstotest\zwopenproc.pdb\E3CA63D5CD7544E9BC90709CA8D04042a\file.ptr
    
    e:\test\zwopenproc\zwopenproc.pdb
    D:\symstotest>cat D:\symstotest\zwopenproc.pdb\E3CA63D5CD7544E9BC90709CA8D04042a\refs.ptr
    
    0000000001,ptr,"e:\test\zwopenproc\zwopenproc.pdb",pri,"",,,
    D:\symstotest>
    

    i dont have the resource kit tool compress.exe handy so i cannot test the compression at the moment but i will update answer when i can

    but it appears that you can compress the files in actual directory in the sample case above compress <switces> "e:\test\zwopenproc\zwopenproc.pdb" to "e:\test\zwopenproc\zwopenproc.pd_"

    and symsrv.dll will be capable of retrieving the compressed file

    once retrieved it seems it would be your responsibility to uncompress
    or use a downstream cache to let symsrv.dll so it for you
    for using in a windbg session as quoted in manual

    Compressed Files
    SymSrv is compatible with symbol stores that contain compressed files, as long as this compression has been done with the compress.exe tool, which is available here. Compressed files should have an underscore as the last character in their file extensions (for example, module1.pd_ or module2.db_). For details, see SymStore.
    
    If the files on the store are compressed, you must use a downstream store. SymSrv will uncompress all files before caching them on the downstream store.
    

       

    ===============================UPDATE============================

    It Seems to work here

    contents of folder pre test

    E:\test\zwopenproc>dir /b
    zwopenproc.cpp
    zwopenproc.exe
    zwopenproc.pdb
    

    creating a folder and adding symstore transactions to that folder

    E:\test\zwopenproc>d:
    
    D:\>md symsto
    
    D:\>cd symsto
    
    D:\symsto>symstore add /p /r /l /t win7 /f e:\test\zwopenproc\*.* /s .
    Finding ID...  0000000001
    
    SYMSTORE: Number of pointers stored = 2
    SYMSTORE: Number of errors = 0
    SYMSTORE: Number of pointers ignored = 1
    
    D:\symsto>dir /s /b
    D:\symsto\000Admin
    D:\symsto\pingme.txt
    D:\symsto\zwopenproc.exe
    D:\symsto\zwopenproc.pdb
    D:\symsto\000Admin\0000000001
    D:\symsto\000Admin\history.txt
    D:\symsto\000Admin\lastid.txt
    D:\symsto\000Admin\server.txt
    D:\symsto\zwopenproc.exe\57E9886E4a000
    D:\symsto\zwopenproc.exe\57E9886E4a000\file.ptr
    D:\symsto\zwopenproc.exe\57E9886E4a000\refs.ptr
    D:\symsto\zwopenproc.pdb\A734669CFEA74EFB8437FE1086F559B61
    D:\symsto\zwopenproc.pdb\A734669CFEA74EFB8437FE1086F559B61\file.ptr
    D:\symsto\zwopenproc.pdb\A734669CFEA74EFB8437FE1086F559B61\refs.ptr
    

    compressing and deleting

    D:\symsto>e:
    
    E:\test\zwopenproc>e:\rktools\compress.exe -R -S zwopenproc.pdb
    
    Compressing zwopenproc.pdb to zwopenproc.pd_.
    zwopenproc.pdb: 4960256 bytes compressed to 1903179 bytes, 62% savings.
    
    Total savings: 1 files, 4960256 bytes compressed to 1903179 bytes, 61% savings.
    
    E:\test\zwopenproc>del zwopenproc.pdb
    
    E:\test\zwopenproc>dir /b
    zwopenproc.cpp
    zwopenproc.exe
    zwopenproc.pd_
    

    running windbg and an instance of procmon

    E:\test\zwopenproc>windbg zwopenproc.exe
    
    E:\test\zwopenproc>procmon
    

    **when windbg stopped in initial breakpoint adding the new store to sympath and reloading the modules **

    Microsoft (R) Windows Debugger Version 10.0.10586.567 X86
    CommandLine: zwopenproc.exe
    
    
    0:000> .sympath
    Symbol search path is: srv*E:\symbols*http://msdl.microsoft.com/download/symbols
    
    0:000> .sympath srv*E:\symbols*D:\symsto*http://msdl.microsoft.com/download/symbols
    Symbol search path is: srv*E:\symbols*D:\symsto*http://msdl.microsoft.com/download/symbols
    
    0:000> .reload /f
    
    the first time .reload doesn't seem to find the symbol file though i can see in procmon    
    that the files were fethced from new symstore and written to 
    downstream cache e:\symbols and     
    default cache sym dir in !homedir  (windbg installation directory)
    
    zwopenproc PDB notfound:srv*e:\symbols*d:\symsto*http://msdl.microsoft.com/download/symbols
    
    0:000> lm
    start    end        module name
    00b70000 00bba000   zwopenproc   (no symbols)  
    
    **issuing .reload /f a second time the symbol files are loaded successfully**      
    
    0:000> .reload /f
    Reloading current modules
    ........
    0:000> lm
    start    end        module name
    00b70000 00bba000   zwopenproc   (private pdb symbols)   
    e:\symbols\zwopenproc.pdb\A734669CFEA74EFB8437FE1086F559B61\zwopenproc.pdb