diff --git a/Handle/BNType.cs b/Handle/BNType.cs index a5bbd97..968c0fd 100644 --- a/Handle/BNType.cs +++ b/Handle/BNType.cs @@ -203,6 +203,18 @@ public ulong Width } } + /// + /// Whether this integer-like type is signed (wraps BNIsTypeSigned). + /// + public BoolWithConfidence Signed + { + get + { + return BoolWithConfidence.FromNative(NativeMethods.BNIsTypeSigned(this.handle)); + } + } + + public ulong Alignment { get diff --git a/Type/EnumerationType.cs b/Type/EnumerationType.cs index f3bc8c2..55c328a 100644 --- a/Type/EnumerationType.cs +++ b/Type/EnumerationType.cs @@ -36,5 +36,72 @@ public EnumerationMember[] Members return this.Enumeration.Members; } } + + /// + /// The member values reinterpreted per this enumeration's signedness and width, mirroring + /// Python's EnumerationType.members (which applies + /// binaryninja.types.convert_integer to each raw u64). A signed enumeration reports + /// -1 for 0xFFFFFFFFFFFFFFFF; alone returns the + /// raw unsigned value, so signed enumerations previously appeared as huge unsigned numbers. + /// + /// + /// For an unsigned enumeration whose value exceeds , the + /// authoritative value is (ulong); the long returned + /// here wraps. Signed enumerations — the case this method exists for — are exact. + /// + public long[] GetMemberSignedValues() + { + EnumerationMember[] members = this.Members; + BoolWithConfidence signed = this.Signed; + ulong width = this.Width; + + long[] result = new long[members.Length]; + + for (int i = 0; i < members.Length; i++) + { + result[i] = ConvertInteger(members[i].Value, signed.Value, width); + } + + return result; + } + + // Reinterpret a raw 64-bit value as a signed or unsigned integer of the given byte width, + // mirroring Python binaryninja.types.convert_integer (types.py:68). Mask to the width first, + // then sign-extend when signed. + private static long ConvertInteger(ulong value, bool signed, ulong width) + { + ulong masked; + + switch (width) + { + case 1: + masked = value & 0xFFUL; + if (signed) + { + return (long)(sbyte)masked; + } + return (long)(byte)masked; + + case 2: + masked = value & 0xFFFFUL; + if (signed) + { + return (long)(short)masked; + } + return (long)(ushort)masked; + + case 4: + masked = value & 0xFFFFFFFFUL; + if (signed) + { + return (long)(int)masked; + } + return (long)(uint)masked; + + default: + // Width 8 (and any other value): the full 64 bits. + return (long)value; + } + } } }