Cheat Engine Forum Index Cheat Engine
The Official Site of Cheat Engine
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 


How does Cheat Engine load debug symbols from a PDB?

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine
View previous topic :: View next topic  
Author Message
Just_Ero
How do I cheat?
Reputation: 0

Joined: 09 Feb 2020
Posts: 7

PostPosted: Sat Dec 04, 2021 3:58 pm    Post subject: How does Cheat Engine load debug symbols from a PDB? Reply with quote

Hi,

I'm trying to create some helper functions in C# that allow me to load and enumerate a module's symbols via a provided PDB file. Particularly, I want to get some specific symbols of a Unity game's UnityPlayer.dll, the PDB of which I download from Unity's symbol server.

Looking through the source (which is incredibly difficult, because Pascal feels like complete gibberish) I found that CE makes use of the normal symbol funcitons from WinAPI's `dbghelp.dll` in the `symbolhandler.pas` file:

I believe the PDB loading is handled in `procedure TSymbolloaderthread.processThreadEvents` (though I may be wrong. This leads me to believe that the function used to retrieve the symbol info from a PDB is SymSearch (line 2226).

I have attempted to implement this in C# (.NET 6.0) in the following way:

Code:

[DbgHelp.cs]

public delegate bool PSYM_ENUMERATESYMBOLS_CALLBACK([In] ref SYMBOL_INFO pSymInfo, [In] uint SymbolSize, [In, Optional] IntPtr UserContext);

[DllImport("dbghelp.dll", CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SymInitialize([In] IntPtr hProcess, [In, Optional] string UserSearchPath, [In] bool fInvadeProcess);

[DllImport("dbghelp.dll", CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.U8)]
public static extern ulong SymLoadModuleEx([In] IntPtr hProcess, [In] IntPtr hFile, [In] string ImageName, [In] string ModuleName, [In, MarshalAs(UnmanagedType.U8)] ulong BaseOfDll, [In] uint DllSize, [In] IntPtr Data, [In] uint Flags);

[DllImport("dbghelp.dll", CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SymSearch([In] IntPtr hProcess, [In] ulong BaseOfDll, [In, Optional] uint Index, [In, Optional, MarshalAs(UnmanagedType.U4)] SymTag SymTag, [In, Optional] string Mask, [In, Optional] ulong Address, [In] PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback, [In, Optional] IntPtr UserContext, [In, MarshalAs(UnmanagedType.U4)] SymSearchOptions Options);

[DllImport("dbghelp.dll", CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SymCleanup([In] IntPtr hProcess);


Code:

[ProcessUtils.cs]

public static SYMBOL_INFO[] AllSymbols(this Process process, ProcessModule module, string symbol = "*")
{
   var procHandle = process.Handle;

   if (!DbgHelp.SymInitialize(procHandle, null, false))
      throw new Exception("Failed to initialize symbols.");

   var symbols = new List<SYMBOL_INFO>();

   try
   {
      if (DbgHelp.SymLoadModuleEx(procHandle, IntPtr.Zero, module.ModuleName, null, (ulong)(module.BaseAddress), (uint)(module.ModuleMemorySize), IntPtr.Zero, 0) == 0)
         throw new Exception("Failed to load module's symbols.");

      DbgHelp.PSYM_ENUMERATESYMBOLS_CALLBACK callback = new(enumSyms);

      if (!DbgHelp.SymSearch(procHandle, (ulong)(module.BaseAddress), 0, SymTag.Function, symbol, 0, callback, IntPtr.Zero, SymSearchOptions.SYMSEARCH_ALLITEMS))
         throw new Exception("Failed to enumerate over PDB symbols.");
   }
   finally
   {
      DbgHelp.SymCleanup(procHandle);
   }

   return symbols.ToArray();

   bool enumSyms(ref SYMBOL_INFO pSymInfo, uint SymbolSizem, IntPtr UserContext)
   {
      symbols.Add(pSymInfo);
      return true;
   }
}


SymTag.Function translates to the same dword(SymTagFunction) used in L2226 and SymSearchOptions.SYMSEARCH_ALLITEMS also translates to 8 at the end of L2226.

Am I missing something?
Back to top
View user's profile Send private message
Csimbi
I post too much
Reputation: 92

Joined: 14 Jul 2007
Posts: 3102

PostPosted: Sat Dec 04, 2021 6:23 pm    Post subject: Reply with quote

You know that CE is open source, right?
You can just read the code and adapt it.
Back to top
View user's profile Send private message
Just_Ero
How do I cheat?
Reputation: 0

Joined: 09 Feb 2020
Posts: 7

PostPosted: Sun Dec 05, 2021 6:15 am    Post subject: Reply with quote

Uh, yes? Why do you think I said I looked through the code and that Pascal is unreadable to me? There's no such thing as "just read the code and adapt it" when the code is 22 years old.
Back to top
View user's profile Send private message
Csimbi
I post too much
Reputation: 92

Joined: 14 Jul 2007
Posts: 3102

PostPosted: Sun Dec 05, 2021 6:53 am    Post subject: Reply with quote

Just_Ero wrote:
Uh, yes? Why do you think I said I looked through the code and that Pascal is unreadable to me? There's no such thing as "just read the code and adapt it" when the code is 22 years old.

It might be 22 years old, but it still runs today.
That means it's very good code.
I'd suggest you learn Pascal a bit so you can actually understand what's going on.
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 457

Joined: 09 May 2003
Posts: 25262
Location: The netherlands

PostPosted: Sun Dec 05, 2021 11:23 am    Post subject: Reply with quote

what part doesn't work ?

Have you tried with invasive on ?

_________________
Do not ask me about online cheats. I don't know any and wont help finding them.

Like my help? Join me on Patreon so i can keep helping
Back to top
View user's profile Send private message MSN Messenger
Just_Ero
How do I cheat?
Reputation: 0

Joined: 09 Feb 2020
Posts: 7

PostPosted: Sun Dec 05, 2021 1:28 pm    Post subject: Reply with quote

Well, I'm only finding embedded symbols with the method I'm using. Is Cheat Engine parsing the PDB file somehow? I'm not finding any code that's doing that.
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 457

Joined: 09 May 2003
Posts: 25262
Location: The netherlands

PostPosted: Sun Dec 05, 2021 1:35 pm    Post subject: Reply with quote

just the windows symbol api

also, there's another part where symbols are enumerated

_________________
Do not ask me about online cheats. I don't know any and wont help finding them.

Like my help? Join me on Patreon so i can keep helping
Back to top
View user's profile Send private message MSN Messenger
Just_Ero
How do I cheat?
Reputation: 0

Joined: 09 Feb 2020
Posts: 7

PostPosted: Sun Dec 05, 2021 1:39 pm    Post subject: Reply with quote

Hm, do you know or recall which parts are doing what?

It's difficult finding the correct methods, since I don't know all that much about CE's internal workings. In C#, I have access to all of the windows symbol API, which sounds like great news, but I seem to be missing something.

It's only the PDB-specific symbols I'm missing. I can see them fine in CE, just not in my code...
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 457

Joined: 09 May 2003
Posts: 25262
Location: The netherlands

PostPosted: Sun Dec 05, 2021 2:18 pm    Post subject: Reply with quote

look at symEnumSymbols
_________________
Do not ask me about online cheats. I don't know any and wont help finding them.

Like my help? Join me on Patreon so i can keep helping
Back to top
View user's profile Send private message MSN Messenger
Just_Ero
How do I cheat?
Reputation: 0

Joined: 09 Feb 2020
Posts: 7

PostPosted: Sun Dec 05, 2021 2:59 pm    Post subject: Reply with quote

I've done that using the following code:

Code:

WinAPI.SymEnumSymbols(procHandle, (ulong)(module.BaseAddress), symbol, callback, IntPtr.Zero);


Code:

bool enumSyms(ref SYMBOL_INFO pSymInfo, uint SymbolSizem, IntPtr UserContext)
{
   symbols.Add(pSymInfo);
   return true;
}


"procHandle" is a HANDLE to the current process,
"(ulong)(module.BaseAddress)" is the BaseOfDll value of the module to check the symbols from as a ULONG64,
"symbol" is a PCSTR with the symbol name/mask,
"callback" is "enumSyms", which is a PSYM_ENUMERATESYMBOLS_CALLBACK (symbols is just a list of SYMBOL_INFO structs),
"IntPtr.Zero" is a null PVOID object for the UserContext variable.

Is the issue that my UserContext is NULL?
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 457

Joined: 09 May 2003
Posts: 25262
Location: The netherlands

PostPosted: Sun Dec 05, 2021 3:11 pm    Post subject: Reply with quote

perhaps you havn't set the path to where to find the pdb in syminitialize or SymSetSearchPath
_________________
Do not ask me about online cheats. I don't know any and wont help finding them.

Like my help? Join me on Patreon so i can keep helping
Back to top
View user's profile Send private message MSN Messenger
Just_Ero
How do I cheat?
Reputation: 0

Joined: 09 Feb 2020
Posts: 7

PostPosted: Sun Dec 05, 2021 3:56 pm    Post subject: Reply with quote

Cool, thank you! Using

Code:

WinAPI.SymInitialize(procHandle, Path.GetDirectoryName(module.FileName), false);


I can now get all symbols (of course, as long as the PDB is in the same directory as the DLL).

Thank you!
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Powered by phpBB © 2001, 2005 phpBB Group

CE Wiki   IRC (#CEF)   Twitter
Third party websites