Get method name from Image RVA

74 Views Asked by At

I want to export stack trace data from an ETL file (Event Tracing for Windows) into a more readable format.

CPU profiling data is only useful with method names, but when on the recording machine no symbol server access exists it would be useful to record just the amount of data to later load the method names into the tool as an extra post processing step.

The input would be e.g. dll with a RVA (Relative Virtual Address) like

kernel32.dll+0xdddd

After storing this data I want to get the full method name out of this. As far as I have read the symbol server lookup uses just the tuple

  • Pdb Guid
  • Pdb Age
  • Pdb Name

In theory I should be able to retrieve a method name with a helper method with this signature:

string GetMethod(string dll, long RVA, Guid pdbGuid, int pdbAge, string pdbName)

The normal approach to lookup methods is to use Dbghelp.dll. To be able to use I need to call SymInitialize but all of these APIs expect a process handle.

BOOL IMAGEAPI SymInitializeW(
  [in]           HANDLE hProcess,
  [in, optional] PCWSTR UserSearchPath,
  [in]           BOOL   fInvadeProcess
);

Has anyone experience with getting the method name from an Image RVA address when the input is not a live process or a memory dump file? Or would I need to use another library (e.g. msdia140.dll)?

1

There are 1 best solutions below

0
Alois Kraus On

PerfView has full support for this already. https://github.com/microsoft/perfview/blob/main/src/TraceEvent/Symbols/NativeSymbolModule.cs

/// <summary>
/// This overload of SourceLocationForRva like the one that takes only an RVA will return a source location
/// if it can.   However this version has additional support for NGEN images.   In the case of NGEN images 
/// for .NET V4.6.1 or later), the NGEN images can't convert all the way back to a source location, but they 
/// can convert the RVA back to IL artifacts (ilAssemblyName, methodMetadataToken, iloffset).  THese can then
/// be used to look up the source line using the IL PDB.  
/// 
/// Thus if the return value from this is null, check to see if the ilAssemblyName is non-null, and if not 
/// you can look up the source location using that information.  
/// </summary>
public SourceLocation SourceLocationForRva(uint rva, out string ilAssemblyName, out uint methodMetadataToken, out int ilOffset)
{

This is exactly what I need and it uses msdia140.dll. It looks like the "normal" dbghelp.dll is not the best fit for this task.