# smgdc SourceMod gamedata checker. Rewrite of a previous internal project. Faster. Stronger. More maintainable. ## Usage `smgdc --add-binary --add-binary ...` - `specfile` is a specification file or directory (tree) containing specification files. - `--add-binary` specifies one or more binaries to add for checking. - This may be a `os.pathsep`-separated pair of values that map a physical file to one present in the specification file. ### Specification file A specification file is an INI configuration file used to check aspects of one or more binary (code) files. Example: ``` ; reports presence of a byte sequence in the Windows server binary, yielding signature [CWeaponMedigun::SecondaryAttack()] target = bin/tf/server.dll type = bytesig contents = 55 8B EC 56 8B 75 08 85 F6 0F 84 ?? ?? ?? ?? 53 ; reports that a given immediate value in code is at a given location, yielding offsets, etc. [CTFProjectile_Flare::Explode_Air()::SelfDamageRadius LINUX] target = bin/tf/server_srv.so type = value symbol = _ZN19CTFProjectile_Flare11Explode_AirEP10CGameTraceib offset = 0x468 struct = [!WARNING] > Obviously, [Python's `eval` is dangerous][eval-danger]; this application was never designed > to accomodate adversarial inputs. You should never blindly perform validations with > user-submitted specification files. Depending on the entry type, one or more of these variables will be made available: - `addr`: An object representing a position in the binary. This is set to the configuration's result address and provides the following methods: - `read(offset: int = 0)`: Returns a new `BinaryPosition`, acting as if the position + offset was dereferenced as an absolute address. - `value(struct, offset = 0)`: Extracts the current position using a [struct.Struct][]-format string into a single result. - `string_value(encoding = "utf-8", errors = "strict", offset = 0)`: Extracts a string from the current position. - This is designed to mimic SourceMod's gamedata API of using reads via method chaining: ``` # process an indirection by dereferencing at position +3h addr.read(0x3).value(" [!IMPORTANT] > The constraint file specification is not finalized. Please ensure that you are reading the > documentation for the version of `smgdc` that you are working with. Linux binaries are sometimes compiled with flags that cause a many-to-one mapping of symbols to function addresses (in other words: link time optimization). While the application does attempt to uniquely identify symbols using other markers, there's sometimes insufficient information to do so. A constraint file is used as a last resort for end users to manually identify which symbols map to which positions for a given virtual table and its subclasses. This is done by specifying relative ordering constraints for each symbol, allowing for reuse between binary revisions (with the assumption that vtables aren't reordered across them). Example: ``` [[_ZTV17CBaseCombatWeapon]] constraint = "soft" symbols = [ "_ZN17CBaseCombatWeapon6DeleteEv", "_ZN17CBaseCombatWeapon4KillEv", ] [[_ZTV17CBaseCombatWeapon]] constraint = "consecutive" symbols = [ "_ZN17CBaseCombatWeapon27WeaponRangeAttack1ConditionEff", "_ZN17CBaseCombatWeapon27WeaponRangeAttack2ConditionEff", "_ZN17CBaseCombatWeapon27WeaponMeleeAttack1ConditionEff", "_ZN17CBaseCombatWeapon27WeaponMeleeAttack2ConditionEff", ] ``` In this `CBaseCombatWeapon` vtable, a *soft order* constraint is applied such that the offset of `CBaseCombatWeapon::Delete` is lower than `CBaseCombatWeapon::Kill` — both symbols point to the same address, and both are present at two offsets, so this ensures that once solved, each symbol will be assigned the correct offset. A *consecutive order* constraint is also applied such that `CBaseCombatWeapon::WeaponRangeAttack1Condition` and subsequent symbols have monotonically increasing offsets.