Tutorial 3: Dealing with Ghidra arrays, field pointers, and ADJ()¶
Example 1¶
A lot of assembly that accesses structs is optimized by the compiler to use relative offsets. Usually one field of a struct is chosen as the reference point. For example, in this function, owner is chosen as the reference point as can be seen in line 11:
1int __thiscall
2UnitsState::getAliveLordForPlayer(UnitsState *this,int playerID)
3
4{
5 int _unit;
6 Unit * 150 _ptrUnit;
7
8 _unit = 1;
9 if (1 < (int)DAT_UnitsState.maxUnitCount) {
10 /* Unit offset 150 */
11 _ptrUnit = &DAT_UnitsState.units[1].owner;
12 do {
13 if ((((ADJ(_ptrUnit)->unitType == UT_LORD) && (ADJ(_ptrUnit)->owner == playerID)) &&
14 (ADJ(_ptrUnit)->logicalState == ULS_NORMAL)) && (ADJ(_ptrUnit)->dying == 0)) {
15 return _unit;
16 }
17 _unit = _unit + 1;
18 _ptrUnit = _ptrUnit + 0x248;
19 } while (_unit < (int)DAT_UnitsState.maxUnitCount);
20 }
21 return 0;
22}
Fields and arrays¶
Furthermore, the line _ptrUnit = _ptrUnit + 0x248 is deceptive. Technically, it is incrementing 0x248, but as ptrUnit is of type int, it is actually increment 4 * 0x248 = 0x490 (the struct size of Unit).
Solution¶
Note how we changed the line referring to owner and instead refer to the unit instead. Then, when incrementing the pointer, we increment by 1 (1 Unit).
We remove ADJ().
1#include "OpenSHC/Map/Units/UnitsState.hpp"
2
3#include "OpenSHC/Map/Units/UnitLogicState.hpp"
4#include "OpenSHC/Map/Units/UnitType.hpp"
5
6namespace OpenSHC {
7namespace Map {
8 namespace Units {
9
10 // FUNCTION: STRONGHOLDCRUSADER 0x005377f0
11 int UnitsState::getAliveLordForPlayer(int playerID)
12
13 {
14 int _unit = 1;
15 if (1 < (int)this->maxUnitCount) {
16 /* Unit offset 150 */
17 Unit* _ptrUnit = &this->units[1];
18 do {
19 if ((((_ptrUnit->unitType == UT_LORD) && (_ptrUnit->owner == playerID))
20 && (_ptrUnit->logicalState == ULS_NORMAL))
21 && (_ptrUnit->dying == 0)) {
22 return _unit;
23 }
24 _unit = _unit + 1;
25 _ptrUnit = _ptrUnit + 1;
26 } while (_unit < (int)this->maxUnitCount);
27 }
28 return 0;
29 }
30
31 }
32}
33}