Skip to main content
final attempt at fixing the formatting
Source Link

While looking at that old game I've found a class CStr that is used in an unusual (to me) manner. Most of the times a member of CStr is used, it's done as follows. In both cases, this is a CStr *.

Decompilation:

pcVar6 = *(char **)(*(int *)(this + 4) + 8); // pcVar6 is then used 

Disassembly

// since the func is a __thiscall, ECX contains "this" MOV ESI ,ECX MOV EAX ,dword ptr [ESI + 0x4] MOV EDI ,dword ptr [EAX + 0x8] // EDI is then used 

This strikes me as odd. If one of the members of CStr is a char array, why isn't it just a single offset? I'm thinking that this has something to do with inheritance, but I'm lacking experience with that to be certain.

For context, this particular member seems to be a C string. The code comes from a Win32 DLL.

How do I interpret this correctly? And how do I tell Ghidra how to interpret this?

EDIT: More examples

I put a lot more here at first, but deleted everything that isn't a case where the CStr object itself is used. It's just a lot more of the line already posted and I doubt that it'll clear anything up. Also, I'm yet to make significat progress in determining what the fields of the objects are, sadly :(


Example of CStr being used in constructor. this is a CMachineController here.

// CMachineController::CMachineController CStr::CStr((CStr *)&this->field_0x4); // could be labeled as "cstring"? 

Part of a longer function. It seems to acquire an instance by reading a config object, then does some manipulation and destroys the CStr. Var types as follows: ``` bool - bool bVar3; CConfig* - CConfig* pcVar8; CStr - CStr aCStack20[8]; undefined4 - undefined4 local4; // a(a 4-byte-wide number of some kind //) - stack0xff... is created by (`MOV this, ESP / MOV dword ptr [ESP+0x3c], ESP`) CMachineController* - CMachineController* this; ```
// CMachineController::Init() ... bVar3 = CConfig::HasValue(pCVar8,s_AutoStart_10056dc4); if (bVar3 != false) { CConfig::GetValue(this->config,(char *)aCStack20); CStr::CStr((CStr *)&stack0xffffffd0,aCStack20); (**(code **)(**(int **)&this->field_0x18 + 0x14))(); CStr::~CStr(aCStack20); } ...   

Without any more info on what would be considered useful, this is the best I can think of atm. Still, thanks a lot for the help!

While looking at that old game I've found a class CStr that is used in an unusual (to me) manner. Most of the times a member of CStr is used, it's done as follows. In both cases, this is a CStr *.

Decompilation:

pcVar6 = *(char **)(*(int *)(this + 4) + 8); // pcVar6 is then used 

Disassembly

// since the func is a __thiscall, ECX contains "this" MOV ESI ,ECX MOV EAX ,dword ptr [ESI + 0x4] MOV EDI ,dword ptr [EAX + 0x8] // EDI is then used 

This strikes me as odd. If one of the members of CStr is a char array, why isn't it just a single offset? I'm thinking that this has something to do with inheritance, but I'm lacking experience with that to be certain.

For context, this particular member seems to be a C string. The code comes from a Win32 DLL.

How do I interpret this correctly? And how do I tell Ghidra how to interpret this?

EDIT: More examples

I put a lot more here at first, but deleted everything that isn't a case where the CStr object itself is used. It's just a lot more of the line already posted and I doubt that it'll clear anything up. Also, I'm yet to make significat progress in determining what the fields of the objects are, sadly :(


Example of CStr being used in constructor. this is a CMachineController here.

// CMachineController::CMachineController CStr::CStr((CStr *)&this->field_0x4); // could be labeled as "cstring"? 

Part of a longer function. It seems to acquire an instance by reading a config object, then does some manipulation and destroys the CStr. Var types as follows: ``` bool bVar3; CConfig* pcVar8; CStr aCStack20[8]; undefined4 local4; // a 4-byte-wide number of some kind // stack0xff... is created by (`MOV this, ESP / MOV dword ptr [ESP+0x3c], ESP`) CMachineController* this; ```
// CMachineController::Init() ... bVar3 = CConfig::HasValue(pCVar8,s_AutoStart_10056dc4); if (bVar3 != false) { CConfig::GetValue(this->config,(char *)aCStack20); CStr::CStr((CStr *)&stack0xffffffd0,aCStack20); (**(code **)(**(int **)&this->field_0x18 + 0x14))(); CStr::~CStr(aCStack20); } ...   

Without any more info on what would be considered useful, this is the best I can think of atm. Still, thanks a lot for the help!

While looking at that old game I've found a class CStr that is used in an unusual (to me) manner. Most of the times a member of CStr is used, it's done as follows. In both cases, this is a CStr *.

Decompilation:

pcVar6 = *(char **)(*(int *)(this + 4) + 8); // pcVar6 is then used 

Disassembly

// since the func is a __thiscall, ECX contains "this" MOV ESI ,ECX MOV EAX ,dword ptr [ESI + 0x4] MOV EDI ,dword ptr [EAX + 0x8] // EDI is then used 

This strikes me as odd. If one of the members of CStr is a char array, why isn't it just a single offset? I'm thinking that this has something to do with inheritance, but I'm lacking experience with that to be certain.

For context, this particular member seems to be a C string. The code comes from a Win32 DLL.

How do I interpret this correctly? And how do I tell Ghidra how to interpret this?

EDIT: More examples

I put a lot more here at first, but deleted everything that isn't a case where the CStr object itself is used. It's just a lot more of the line already posted and I doubt that it'll clear anything up. Also, I'm yet to make significat progress in determining what the fields of the objects are, sadly :(


Example of CStr being used in constructor. this is a CMachineController here.

// CMachineController::CMachineController CStr::CStr((CStr *)&this->field_0x4); // could be labeled as "cstring"? 

Part of a longer function. It seems to acquire an instance by reading a config object, then does some manipulation and destroys the CStr. Var types as follows: - bool bVar3; - CConfig* pcVar8; - CStr aCStack20[8]; - undefined4 local4; (a 4-byte-wide number of some kind) - stack0xff... is created by (`MOV this, ESP / MOV dword ptr [ESP+0x3c], ESP`) - CMachineController* this;
// CMachineController::Init() ... bVar3 = CConfig::HasValue(pCVar8,s_AutoStart_10056dc4); if (bVar3 != false) { CConfig::GetValue(this->config,(char *)aCStack20); CStr::CStr((CStr *)&stack0xffffffd0,aCStack20); (**(code **)(**(int **)&this->field_0x18 + 0x14))(); CStr::~CStr(aCStack20); } ... 

Without any more info on what would be considered useful, this is the best I can think of atm.

Fixed formatting
Source Link
* bool```bool
* CConfig*CConfig*
* CStrCStr
* undefined4undefined4
(a// a
)*//
)* CMachineController* this```C++// CMachineController::Init()...bVar3 = CConfig::HasValue(pCVar8,s_AutoStart_10056dc4
;if(bVar3!= false){CConfig::GetValue(this->config,(char *)aCStack20);CStr::CStr((CStr *)&stack0xffffffd0,aCStack20);(**(code **)(**(int **)&this->field_0x18 + 0x14))();CStr::~CStr(aCStack20);CMachineController* this;}```...
// CMachineController::Init() ... bVar3 = CConfig::HasValue(pCVar8,s_AutoStart_10056dc4); if (bVar3 != false) { CConfig::GetValue(this->config,(char *)aCStack20); CStr::CStr((CStr *)&stack0xffffffd0,aCStack20); (**(code **)(**(int **)&this->field_0x18 + 0x14))(); CStr::~CStr(aCStack20); } ... 
Without any more info on what would be considered useful, this is the best I can think of atm. Still, thanks a lot for the help! 

Without any more info on what would be considered useful, this is the best I can think of atm. Still, thanks a lot for the help!

* bool
* CConfig*
* CStr
* undefined4
(a
)*
)* CMachineController* this```C++// CMachineController::Init()...bVar3 = CConfig::HasValue(pCVar8,s_AutoStart_10056dc4
;if(bVar3!= false){CConfig::GetValue(this->config,(char *)aCStack20);CStr::CStr((CStr *)&stack0xffffffd0,aCStack20);(**(code **)(**(int **)&this->field_0x18 + 0x14))();CStr::~CStr(aCStack20);}...
Without any more info on what would be considered useful, this is the best I can think of atm. Still, thanks a lot for the help! 
```bool
CConfig*
CStr
undefined4
// a
//
CMachineController* this;```
// CMachineController::Init() ... bVar3 = CConfig::HasValue(pCVar8,s_AutoStart_10056dc4); if (bVar3 != false) { CConfig::GetValue(this->config,(char *)aCStack20); CStr::CStr((CStr *)&stack0xffffffd0,aCStack20); (**(code **)(**(int **)&this->field_0x18 + 0x14))(); CStr::~CStr(aCStack20); } ... 

Without any more info on what would be considered useful, this is the best I can think of atm. Still, thanks a lot for the help!

added 1419 characters in body
Source Link

While looking at that old game I've found a class CStr that is used in an unusual (to me) manner. Most of the times a member of CStr is used, it's done as follows. In both cases, this is a CStr *.

Decompilation:

pcVar6 = *(char **)(*(int *)(this + 4) + 8); // pcVar6 is then used 

Disassembly

// since the func is a __thiscall, ECX contains "this" MOV ESI ,ECX MOV EAX ,dword ptr [ESI + 0x4] MOV EDI ,dword ptr [EAX + 0x8] // EDI is then used 

This strikes me as odd. If one of the members of CStr is a char array, why isn't it just a single offset? I'm thinking that this has something to do with inheritance, but I'm lacking experience with that to be certain.

For context, this particular member seems to be a C string. The code comes from a Win32 DLL.

How do I interpret this correctly? And how do I tell Ghidra how to interpret this?

EDIT: More examples

I put a lot more here at first, but deleted everything that isn't a case where the CStr object itself is used. It's just a lot more of the line already posted and I doubt that it'll clear anything up. Also, I'm yet to make significat progress in determining what the fields of the objects are, sadly :(


Example of CStr being used in constructor. this is a CMachineController here.

// CMachineController::CMachineController CStr::CStr((CStr *)&this->field_0x4); // could be labeled as "cstring"? 

Part of a longer function. It seems to acquire an instance by reading a config object, then does some manipulation and destroys the CStr. Var types as follows: * bool bVar3; * CConfig* pcVar8; * CStr aCStack20[8]; * undefined4 local4; (a 4-byte-wide number of some kind) * stack0xff... is created by (`MOV this, ESP / MOV dword ptr [ESP+0x3c], ESP`) * CMachineController* this ```C++ // CMachineController::Init() ... bVar3 = CConfig::HasValue(pCVar8,s_AutoStart_10056dc4); if (bVar3 != false) { CConfig::GetValue(this->config,(char *)aCStack20); CStr::CStr((CStr *)&stack0xffffffd0,aCStack20); (**(code **)(**(int **)&this->field_0x18 + 0x14))(); CStr::~CStr(aCStack20); } ...
Without any more info on what would be considered useful, this is the best I can think of atm. Still, thanks a lot for the help! 

While looking at that old game I've found a class CStr that is used in an unusual (to me) manner. Most of the times a member of CStr is used, it's done as follows. In both cases, this is a CStr *.

Decompilation:

pcVar6 = *(char **)(*(int *)(this + 4) + 8); // pcVar6 is then used 

Disassembly

// since the func is a __thiscall, ECX contains "this" MOV ESI ,ECX MOV EAX ,dword ptr [ESI + 0x4] MOV EDI ,dword ptr [EAX + 0x8] // EDI is then used 

This strikes me as odd. If one of the members of CStr is a char array, why isn't it just a single offset? I'm thinking that this has something to do with inheritance, but I'm lacking experience with that to be certain.

For context, this particular member seems to be a C string. The code comes from a Win32 DLL.

How do I interpret this correctly? And how do I tell Ghidra how to interpret this?

While looking at that old game I've found a class CStr that is used in an unusual (to me) manner. Most of the times a member of CStr is used, it's done as follows. In both cases, this is a CStr *.

Decompilation:

pcVar6 = *(char **)(*(int *)(this + 4) + 8); // pcVar6 is then used 

Disassembly

// since the func is a __thiscall, ECX contains "this" MOV ESI ,ECX MOV EAX ,dword ptr [ESI + 0x4] MOV EDI ,dword ptr [EAX + 0x8] // EDI is then used 

This strikes me as odd. If one of the members of CStr is a char array, why isn't it just a single offset? I'm thinking that this has something to do with inheritance, but I'm lacking experience with that to be certain.

For context, this particular member seems to be a C string. The code comes from a Win32 DLL.

How do I interpret this correctly? And how do I tell Ghidra how to interpret this?

EDIT: More examples

I put a lot more here at first, but deleted everything that isn't a case where the CStr object itself is used. It's just a lot more of the line already posted and I doubt that it'll clear anything up. Also, I'm yet to make significat progress in determining what the fields of the objects are, sadly :(


Example of CStr being used in constructor. this is a CMachineController here.

// CMachineController::CMachineController CStr::CStr((CStr *)&this->field_0x4); // could be labeled as "cstring"? 

Part of a longer function. It seems to acquire an instance by reading a config object, then does some manipulation and destroys the CStr. Var types as follows: * bool bVar3; * CConfig* pcVar8; * CStr aCStack20[8]; * undefined4 local4; (a 4-byte-wide number of some kind) * stack0xff... is created by (`MOV this, ESP / MOV dword ptr [ESP+0x3c], ESP`) * CMachineController* this ```C++ // CMachineController::Init() ... bVar3 = CConfig::HasValue(pCVar8,s_AutoStart_10056dc4); if (bVar3 != false) { CConfig::GetValue(this->config,(char *)aCStack20); CStr::CStr((CStr *)&stack0xffffffd0,aCStack20); (**(code **)(**(int **)&this->field_0x18 + 0x14))(); CStr::~CStr(aCStack20); } ...
Without any more info on what would be considered useful, this is the best I can think of atm. Still, thanks a lot for the help! 
Source Link
Loading