@@ -125,6 +125,65 @@ def __ge__(self, other):
125125 else :
126126 return self ._value .GetValueAsUnsigned () >= int (other )
127127
128+ def __add__ (self , other ):
129+ """Add to this value.
130+
131+ Args:
132+ other: Value, SBValue, or integer to add
133+
134+ Returns:
135+ Integer result of addition
136+ """
137+ if isinstance (other , Value ):
138+ return self ._value .GetValueAsUnsigned () + other ._value .GetValueAsUnsigned ()
139+ elif isinstance (other , lldb .SBValue ):
140+ return self ._value .GetValueAsUnsigned () + other .GetValueAsUnsigned ()
141+ else :
142+ return self ._value .GetValueAsUnsigned () + int (other )
143+
144+ def __radd__ (self , other ):
145+ """Reverse add - when Value is on the right side of +.
146+
147+ Args:
148+ other: Value, SBValue, or integer to add
149+
150+ Returns:
151+ Integer result of addition
152+ """
153+ return self .__add__ (other )
154+
155+ def __sub__ (self , other ):
156+ """Subtract from this value.
157+
158+ Args:
159+ other: Value, SBValue, or integer to subtract
160+
161+ Returns:
162+ Integer result of subtraction
163+ """
164+ if isinstance (other , Value ):
165+ return self ._value .GetValueAsUnsigned () - other ._value .GetValueAsUnsigned ()
166+ elif isinstance (other , lldb .SBValue ):
167+ return self ._value .GetValueAsUnsigned () - other .GetValueAsUnsigned ()
168+ else :
169+ return self ._value .GetValueAsUnsigned () - int (other )
170+
171+ def __rsub__ (self , other ):
172+ """Reverse subtract - when Value is on the right side of -.
173+
174+ Args:
175+ other: Value, SBValue, or integer to subtract from
176+
177+ Returns:
178+ Integer result of subtraction
179+ """
180+ if isinstance (other , Value ):
181+ return other ._value .GetValueAsUnsigned () - self ._value .GetValueAsUnsigned ()
182+ elif isinstance (other , lldb .SBValue ):
183+ return other .GetValueAsUnsigned () - self ._value .GetValueAsUnsigned ()
184+ else :
185+ return int (other ) - self ._value .GetValueAsUnsigned ()
186+
128187 def cast (self , type_obj ):
129188 """Cast this value to a different type.
130189
@@ -164,10 +223,15 @@ def __getitem__(self, key):
164223 key: Field name (str) or array index (int)
165224
166225 Returns:
167- Value of the field/element
226+ Value of the field/element, or None if field doesn't exist or is invalid
168227 """
169228 if isinstance (key , str ):
170- return Value (self ._value .GetChildMemberWithName (key ))
229+ result = self ._value .GetChildMemberWithName (key )
230+ # Check if the result is valid
231+ if result .IsValid () and not result .GetError ().Fail ():
232+ return Value (result )
233+ else :
234+ return None
171235 else :
172236 # For integer index: check if this is a pointer type or array type
173237 # Both need pointer-style arithmetic (arrays for flexible array members)
@@ -317,6 +381,17 @@ def pointer(self):
317381 """
318382 return Type (self ._type .GetPointerType ())
319383
384+ def array (self , count ):
385+ """Get array type of this type.
386+
387+ Args:
388+ count: Number of elements in the array (count - 1 for LLDB)
389+
390+ Returns:
391+ Type representing array of this type
392+ """
393+ return Type (self ._type .GetArrayType (count + 1 ))
394+
320395 @property
321396 def native (self ):
322397 """Get the underlying native LLDB type.
@@ -618,9 +693,20 @@ def create_value(address, value_type):
618693 if hasattr (address , '__int__' ):
619694 address = int (address )
620695
696+ target = lldb .debugger .GetSelectedTarget ()
697+
698+ # For array types, use expression evaluation (CreateValueFromData doesn't work for large arrays)
699+ if value_type .IsArrayType ():
700+ type_name = value_type .GetName ()
701+ expr = f"*({ type_name } *)0x{ address :x} "
702+ addr_value = target .CreateValueFromExpression (
703+ f"array_0x{ address :x} " ,
704+ expr
705+ )
706+ return Value (addr_value )
707+
621708 # OPTIMIZATION: For simple types like VALUE (unsigned long), use CreateValueFromData
622709 # which avoids expression evaluation and is much faster for bulk operations
623- target = lldb .debugger .GetSelectedTarget ()
624710 process = target .GetProcess ()
625711
626712 # For scalar types (integers/pointers), we can read and create directly
@@ -655,6 +741,56 @@ def create_value(address, value_type):
655741 return Value (addr_value )
656742
657743
744+ def create_value_from_address (address , value_type ):
745+ """Create a typed Value from a memory address.
746+
747+ This uses CreateValueFromAddress to create a value of the given type at the
748+ specified address. This is more efficient than CreateValueFromExpression
749+ and supports array types directly.
750+
751+ Args:
752+ address: Memory address (as integer, or Value object representing a pointer)
753+ value_type: Type object (or native lldb.SBType) representing the type
754+
755+ Returns:
756+ Value object representing the data at that address
757+
758+ Examples:
759+ >>> rbasic_type = debugger.lookup_type('struct RBasic')
760+ >>> array_type = rbasic_type.array(100)
761+ >>> page_start = page['start'] # Value object
762+ >>> page_array = debugger.create_value_from_address(page_start, array_type)
763+ """
764+ # Convert to integer address if needed (handles Value objects via __int__)
765+ if hasattr (address , '__int__' ):
766+ address = int (address )
767+
768+ # Unwrap Type if needed
769+ if isinstance (value_type , Type ):
770+ value_type = value_type ._type
771+
772+ target = lldb .debugger .GetSelectedTarget ()
773+
774+ # CreateValueFromAddress takes an SBAddress, not an integer
775+ # We need to create an SBAddress from the load address
776+ sb_addr = target .ResolveLoadAddress (address )
777+ if not sb_addr .IsValid ():
778+ raise MemoryError (f"Invalid address: 0x{ address :x} " )
779+
780+ # CreateValueFromAddress takes an address and creates a value of the given type
781+ # reading from that memory location
782+ addr_value = target .CreateValueFromAddress (
783+ f"val_at_0x{ address :x} " ,
784+ sb_addr ,
785+ value_type
786+ )
787+
788+ if not addr_value .IsValid ():
789+ raise MemoryError (f"Failed to create value from address 0x{ address :x} " )
790+
791+ return Value (addr_value )
792+
793+
658794def create_value_from_int (int_value , value_type ):
659795 """Create a typed Value from an integer (not a memory address to read from).
660796
@@ -663,16 +799,21 @@ def create_value_from_int(int_value, value_type):
663799 the integer itself.
664800
665801 Args:
666- int_value: Integer value (not an address to read from)
802+ int_value: Integer value, or Value object that will be converted to int
667803 value_type: Type object (or native lldb.SBType) to cast to
668804
669805 Returns:
670806 Value object with the integer value
671807
672808 Examples:
673809 >>> value_type = debugger.lookup_type('VALUE')
674- >>> obj = debugger.create_value_from_int(0x7fff12345678, value_type)
810+ >>> obj_address = page['start'] # Value object
811+ >>> obj = debugger.create_value_from_int(obj_address, value_type)
675812 """
813+ # Convert to integer if needed (handles Value objects via __int__)
814+ if hasattr (int_value , '__int__' ):
815+ int_value = int (int_value )
816+
676817 # Unwrap Type if needed
677818 if isinstance (value_type , Type ):
678819 value_type = value_type ._type
0 commit comments