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 


Import symbols from linker address map

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine
View previous topic :: View next topic  
Author Message
CodeReaver
Newbie cheater
Reputation: 0

Joined: 19 Apr 2005
Posts: 24

PostPosted: Sat Jan 09, 2016 1:47 pm    Post subject: Import symbols from linker address map Reply with quote

I'd like to import the (ideally demangled) symbols from a linker address map such as this:

Code:
 kain2

 Timestamp is 381a30c7 (Fri Oct 29 16:41:59 1999)

 Preferred load address is 00400000

 Start         Length     Name                   Class
 0001:00000000 000eab1eH .text                   CODE
 0002:00000000 000002b8H .idata$5                DATA
 0002:000002b8 00002603H .rdata                  DATA
 0002:000028bc 000000b4H .idata$2                DATA
 0002:00002970 00000014H .idata$3                DATA
 0002:00002984 000002b8H .idata$4                DATA
 0002:00002c3c 00000c3aH .idata$6                DATA
 0002:00003876 00000000H .edata                  DATA
 0003:00000000 00000004H .CRT$XCA                DATA
 0003:00000004 00000004H .CRT$XCZ                DATA
 0003:00000008 00000004H .CRT$XIA                DATA
 0003:0000000c 00000004H .CRT$XIC                DATA
 0003:00000010 00000004H .CRT$XIZ                DATA
 0003:00000014 00000004H .CRT$XPA                DATA
 0003:00000018 00000004H .CRT$XPX                DATA
 0003:0000001c 00000004H .CRT$XPZ                DATA
 0003:00000020 00000004H .CRT$XTA                DATA
 0003:00000024 00000004H .CRT$XTZ                DATA
 0003:00000030 00017a24H .data                   DATA
 0003:00017a58 007606b8H .bss                    DATA
 0004:00000000 00000178H .rsrc$01                DATA
 0004:00000180 000015f8H .rsrc$02                DATA

  Address         Publics by Value              Rva+Base     Lib:Object

 0001:00000000       _ALUKA_ControllersEnabled  00401000 f   aluka.obj
 0001:00000020       _ALUKA_SetPitch            00401020 f   aluka.obj
 0001:00000080       _ALUKA_EnableControllers   00401080 f   aluka.obj


Does cheat engine support this already or is it something that could be added in future? The "Publics by Value" column and Rva+Base column would simply be added to the user defines symbols list.[/code]
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 458

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

PostPosted: Sat Jan 09, 2016 3:12 pm    Post subject: Reply with quote

ce does load embedded debug symbols as well as .pdb files, but no .map files

You can add that yourself though by parsing the .map file manually and then add them to a custom SymbolList class object which you then register with the main symbol handler

_________________
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
CodeReaver
Newbie cheater
Reputation: 0

Joined: 19 Apr 2005
Posts: 24

PostPosted: Fri Sep 02, 2016 12:32 am    Post subject: Reply with quote

I know this is an old topic, but it's still something I could really do with getting working.

I figured out how to use the plugin system, but it doesn't look like there's any way to add user defined symbols that way. There is documentation online, but it's just spread over the web from what I can I've seen.

I can't tell how the way you describe it could be done from a plugin, but if the function to add user defined symbols was exposed in the SDK, the rest would be easy at this point. I have most of it ready to go. I'm not familiar with Delphi, so the C++ plugin is the easier route for me.

Sorry if I not explaining too well. It's late and I'm pretty tired.
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 458

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

PostPosted: Fri Sep 02, 2016 5:38 am    Post subject: Reply with quote

This lua code adds 2 symbols
Code:

extralist=createSymbolList()
extralist.register()

extralist.addSymbol('aluka','_ALUKA_ControllersEnabled',0x00401000,0x20)
extralist.addSymbol('aluka','_ALUKA_SetPitch',0x00401020,0x60)


I recommend using lua in the form of an autorun script to add the functionality, but if you wish to use a plugin, then take a look at
http://cheatengine.org/download/memviewexample.rar

_________________
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
CodeReaver
Newbie cheater
Reputation: 0

Joined: 19 Apr 2005
Posts: 24

PostPosted: Fri Sep 02, 2016 7:09 am    Post subject: Reply with quote

So, if I edited the example to have the following, would it then add those two symbols? Is there a way to get the extralist to stick around like refto_openmvandshowaddress does in the second example? It's easier for me to set up a loop with shorter strings that way instead of putting everything in one huge buffer.

Code:
lua_State *L = (lua_State*)_ef.GetLuaState();
int i;

char *addSymbols= "extralist=createSymbolList()\nextralist.register()\n
extralist.addSymbol('aluka','_ALUKA_ControllersEnabled',0x00401000,0x20)\n
extralist.addSymbol('aluka','_ALUKA_SetPitch',0x00401020,0x60)\n";

i = lua_gettop(L);
luaL_dostring(L, addSymbols);

lua_settop(L, i);
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 458

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

PostPosted: Fri Sep 02, 2016 7:19 am    Post subject: Reply with quote

the first line : extralist=createSymbolList() makes of extralist a global.
That way it can be accessed from subsequent scripts without having to reregister/create

so all you have to do is create a loop of extralist.addsymbol() commands
(or in the example of openmvandshowaddress create your own function that takes some parameters, and then call that function using a reference and params only)

_________________
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
CodeReaver
Newbie cheater
Reputation: 0

Joined: 19 Apr 2005
Posts: 24

PostPosted: Fri Sep 02, 2016 11:45 am    Post subject: Reply with quote

OK, that sounds like it should do what I need. Are there any instructions on where to get the lua library from or whether I need to get a specific version in order to use it in Cheat Engine?

Is the symbol list object somewhere in CE's source code? It would be useful to see what functions it has available and in particular what that last parameter in the addSymbol function is for. It looks like the length of the function (calculated from the next entry in the file), however some of the symbol are likely to be variables rather than functions, so I won't know what to use in that case.

I found a code documentation page for CE, but it's hard to navigate without links to the parent/child folders. The git page works much better, but it's still hard to find the parts that relate to plugins and the parts that relate to the symbol list.

I really like the way the user defined symbols dialog works because it's easy to find everything and can instantly navigate to the addresses. Is there a way to get the symbols in that interface when I load them this way? I suppose I could recreate the interface in my own implementation if necessary, but I'd find it convenient if they already get added to the same list.
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 458

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

PostPosted: Fri Sep 02, 2016 3:05 pm    Post subject: Reply with quote

https://github.com/cheat-engine/cheat-engine/blob/master/Cheat%20Engine/bin/main.lua
Look for the symbollist class description


The symboklist you mean is accessed by registerSymbol

_________________
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
CodeReaver
Newbie cheater
Reputation: 0

Joined: 19 Apr 2005
Posts: 24

PostPosted: Fri Sep 02, 2016 4:41 pm    Post subject: Reply with quote

That only looks like the class declaration, but not the implementation. It says what parameters the function takes, but not what it does with them.

I'm not trying to de difficult. I'm just not used to delphi or lua, so it's difficult to make deductions on what the next step would be.

I'm trying to see what the size and module are needed for, in order to deal with variables and not just the functions. Does CE have a list built in where I'll be able to see these symbols? I'm assuming they won't be treated as the user defined ones that I've seen in the menus.

EDIT: This is what I've ended up with:
Code:
      lua_State *L = static_cast<lua_State*>(Exported.GetLuaState());

      if (RefToAddSymbol == -1)
      {
         int i = lua_gettop(L);

         char *addSymbol =
            "function addSymbol(module, name, address, size)\n"
            "extralist.addSymbol(module, name, address, size)\n"
            "end\n";
         luaL_dostring(L, addSymbol);

         lua_getglobal(L, "addSymbol");
         RefToAddSymbol = luaL_ref(L, LUA_REGISTRYINDEX);

         char *createSymbolList =
            "extralist=createSymbolList()\n"
            "extralist.register()\n";
         luaL_dostring(L, createSymbolList);

         lua_settop(L, i);
      }

      if (RefToAddSymbol != -1)
      {
         int i = lua_gettop(L);

         lua_rawgeti(L, LUA_REGISTRYINDEX, RefToAddSymbol);
         lua_pushstring(L, "ALUKA");
         lua_pushstring(L, "_ALUKA_ControllersEnabled");
         lua_pushinteger(L, 0x00401000);
         lua_pushinteger(L, 0x00000020);
         lua_call(L, 4, 0, 0);

         lua_settop(L, i);
      }

      if (RefToAddSymbol != -1)
      {
         int i = lua_gettop(L);

         lua_rawgeti(L, LUA_REGISTRYINDEX, RefToAddSymbol);
         lua_pushstring(L, "ALUKA");
         lua_pushstring(L, "_ALUKA_SetPitch");
         lua_pushinteger(L, 0x00401020);
         lua_pushinteger(L, 0x00000060);
         lua_call(L, 4, 0, 0);

         lua_settop(L, i);
      }


Module just seems to me an extra string for grouping symbols into a category or something and length is just there to help the user see other addresses that are part of the same function. It seems like it would be safe to just use 1 for the length then I don't know what else to use.

I still have a couple of questions though.

Do I need to use the same version of the lua library that you used to build Cheat Engine and what's the best way to check which one that is?

Is it safe to move the whole of the duplicated "if (RefToAddSymbol != -1)" blocks into their own function? In other words, am I storing and restoring the top correctly.

The questions before the edit aren't as urgent now, but it would still be helpful if you can answer them.
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 458

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

PostPosted: Sat Sep 03, 2016 9:13 am    Post subject: Reply with quote

If you static link the library like the example then there is no need for a version check. If i ever change from lua 5.3 to something else (unlikely) the plugin won't be able to load as the dll can't be found.

You can move those blocks into a function

The gettop/settop is only needed in case of errors. Under normal usage the lua stack should remain the same

_________________
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
CodeReaver
Newbie cheater
Reputation: 0

Joined: 19 Apr 2005
Posts: 24

PostPosted: Mon Sep 12, 2016 1:27 pm    Post subject: Reply with quote

OK, so I got my extra list working, but now I want to get a list working from which I can browse it and potentially add, edit or remove the entries and set the memory viewer to one if those locations.

Do you know how I'd go about extracting the data from the list? I'd probably need to know what functions are available in the symbol list class for getting the item by index or for iterating through the entries. If they are returned as a structure, I'd need to know that as well.

Although I looked in the file you referred me to earlier, it only appeared to have the name of the function, it's parameters and a description of what it does, and not the implementation. If that's somehow in one of the *.pas files, does the implementation use the same class name?

I could also use some examples of how to get function's return values out of lua and into C++.

One other thing I noticed is that when I used registerSymbol, the entries from the mapfile were added to the user defined symbols list like I wanted to happen from the beginning. Was it unsafe to do this, or did you think that wouldn't have met my requirements?

EDIT: So, I found a bit more data in main.lua. It says something like:

Code:

    Symbol Table:
      modulename: string
      searchkey: string
      address: integer
      symbolsize: integer


Is Symbol the name of the data? Could I access entries directly by using Symbol[0].address and Symbol[0].searchkey?
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 458

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

PostPosted: Mon Sep 12, 2016 7:16 pm    Post subject: Reply with quote

to get a return value, setup pcall so it sets up a return value.
when it returns without error, you can use lua_tointeger(luastate, -1) to get the return value. (or lua_tostring, or lua_tonumber, etc... And you can also return more than 1 result)

registerSymbol is fine. It just doesn't let you describe the size.



As for the symbol table, yes and no.

The symbol table in this case is just a lua table
Code:

Symbol={}
Symbol.modulename='xxx'
Symbol.searchkey='something'
Symbol.address=0x12345678
Symbol.symbolsize=128

which the function then reads out and processes

but lua does allow you to set things like this up as an array like that
e.g
Code:

arr={}
arr[0]={}
arr[0].modulename='xxx'
...

_________________
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
CodeReaver
Newbie cheater
Reputation: 0

Joined: 19 Apr 2005
Posts: 24

PostPosted: Mon Sep 12, 2016 7:43 pm    Post subject: Reply with quote

That's not quite what I meant. I'm not trying to treat the members of the Symbol object as array elements. I'm trying to access the table containing the Symbol objects as if it was as array. I want to pass in an index and get out the Symbol object at that position. If it doesn't work like that, I'd like to integrate through every Symbol object in the table instead.

**The above isn't so relevant after my recent findings**

OK, so I think I understand how the code works now.

Am I correct that these functions from luasymbollisthandler.pas are the only members of the symbol list class accessible from lua and that the actual symbol list itself that I'd be able to look up symbols for enumeration into a ListView is actually in symbollisthandler.pas as the TAvgLvlTree called AddressToString and StringToAddress?
Code:
221 procedure SymbolList_addMetaData(L: PLua_state; metatable: integer; userdata: integer );
222 begin
223   object_addMetaData(L, metatable, userdata);
224   luaclass_addClassFunctionToTable(L, metatable, userdata, 'clear', SymbolList_clear);
225   luaclass_addClassFunctionToTable(L, metatable, userdata, 'getSymbolFromAddress', SymbolList_GetSymbolFromAddress);
226   luaclass_addClassFunctionToTable(L, metatable, userdata, 'getSymbolFromString', SymbolList_getSymbolFromString);
227   luaclass_addClassFunctionToTable(L, metatable, userdata, 'addSymbol', SymbolList_addSymbol);
228   luaclass_addClassFunctionToTable(L, metatable, userdata, 'deleteSymbol', SymbolList_deleteSymbol);
229   luaclass_addClassFunctionToTable(L, metatable, userdata, 'register', SymbolList_register);
230   luaclass_addClassFunctionToTable(L, metatable, userdata, 'unregister', SymbolList_unregister);
231 end;
232
 
233 procedure initializeLuaSymbolListHandler;
234 begin
235   lua_register(LuaVM, 'createSymbolList', createSymbolList);
236 end;


If that's the case, there's no way I could extract a list from those from which to fill the ListView. It looks like the entries contain pointers to each other, so maybe I could just store the most recently added one and somehow traverse the list that way.

I spotted a function called FindFirstSymbolFromBase that could do the job if it was exposed to lua. I'd just pass in 0 the first time, then store the address of the one I found and pass that plus 1 in the next time, and so on. Then I could loop through them all that way.


Last edited by CodeReaver on Tue Sep 13, 2016 8:09 pm; edited 1 time in total
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 458

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

PostPosted: Thu Sep 15, 2016 10:56 am    Post subject: Reply with quote

the symbolList object is an extension to the internal symbol handler. It just helps with address<->symbolname translation

and you're right, the class doesn't have an listSymbols method.

But, since you do add all the symbols yourself, you can just add a secondary list yourself

e.g:
Code:

secondarylist={}


and in the subsequent lua code just do:
Code:

secondarylist['symbolname']=address


and then use a for loop with pairs() to enumerate that table to get a list

example code that might help:
Code:

s={}
s['something']=123
s['something else']=456
for symbolname,address in pairs(s) do
  print(symbolname..' = '..address)
end

_________________
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
CodeReaver
Newbie cheater
Reputation: 0

Joined: 19 Apr 2005
Posts: 24

PostPosted: Sat Sep 17, 2016 5:46 pm    Post subject: Reply with quote

If I decided to implement my own list, then I might as well do that entirely from the plugin in C++ rather than trying to pass it through lua. The main benefit of going through lua was that the addresses I added appeared in both the disassembler window and the userdefined symbol list so that I could see what calls what and use the list in the menu to jump to them.

Anyway I've mostly got it working the way I want, except that CE isn't responding well to duplicates. I modified my lua function to check for a duplicate before passing it into the registerSymbol function. It seemed to work to begin with and then as my parser was able to find more symbols, it started complaining about symbols already in the list again.

Here's the function:
Code:
      if (RefToAddSymbol == -1)
      {
         lua_State *L = static_cast<lua_State*>(Exported.GetLuaState());
         int i = lua_gettop(L);

         char *addSymbol =
            "function addSymbol(module, name, address, size)\n"
            "if getAddress(name) ~= 0 then return false end\n"
            "registerSymbol(name, address)\n"
            "return true\n"
            "end\n"
            "errorOnLookupFailure(false)\n";
         luaL_dostring(L, addSymbol);

         lua_getglobal(L, "addSymbol");
         RefToAddSymbol = luaL_ref(L, LUA_REGISTRYINDEX);

         lua_settop(L, i);
      }


And here's the one I use after it in my loop:
Code:
   for (int dupe = 0; dupe <= 99; dupe++)
   {
      int i = lua_gettop(L);
      int success = 0;

      if (dupe > 0)
      {
         adjustedName[stringLength] = '#';
         _itoa(dupe, &(adjustedName[stringLength +1]), 10);
      }

      lua_rawgeti(L, LUA_REGISTRYINDEX, RefToAddSymbol);
      lua_pushstring(L, module);
      lua_pushstring(L, const_cast<const char*>(adjustedName));
      lua_pushinteger(L, address);
      lua_pushinteger(L, length);
      lua_pcall(L, 4, 1, 0);
      success = lua_toboolean(L, -1);
      lua_pop(L, 1);

      lua_settop(L, i);

      if (success || strcmp(adjustedName, "`string'") == 0)
      {
         break;
      }
   }


Given that I'm checking for the existence of the symbol before actually adding it, I should never get the error about it already existing, right/

The worst thing is that CE stops running my function as soon as lua gets an error. It doesn't even let me try to recover.

EDIT: Is there a limit on the size of the names used, because it could be truncating when I add them or something like that. Then my modified strings wouldn't have the suffix I'm adding to the duplicates and it would incorrectly think the new symbol is safe to add.
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