Class: OneGadget::Emulators::Lambda
- Inherits:
-
Object
- Object
- OneGadget::Emulators::Lambda
- Defined in:
- lib/one_gadget/emulators/lambda.rb
Overview
Instance Attribute Summary collapse
-
#deref_count ⇒ Integer
The times of dereference.
-
#immi ⇒ Integer
The immidiate value currently added.
-
#obj ⇒ String, Lambda
The object currently related to.
-
#op ⇒ String?
The operator applied to #obj, for an operation (see Lambda.operation).
-
#rhs ⇒ Integer, ...
The operator's right operand.
Class Method Summary collapse
-
.operation(lhs, op, rhs) ⇒ Lambda
A value this emulator can name but not fold: an operation applied to
lhs, whose result no plain base+offset expresses. -
.parse(argument, predefined: {}) ⇒ OneGadget::Emulators::Lambda, Integer
Target: parse string like [rsp+0x50] into a Lambda object.
Instance Method Summary collapse
-
#+(other) ⇒ Lambda
Implement addition with
Numeric. -
#-(other) ⇒ Lambda
Implement subtract with
Numeric. -
#base_str ⇒ String
What #to_s renders before any offset: the operation this names, or the object it is based on.
-
#deref ⇒ Lambda
A new Lambda object with dereference count increase 1.
-
#deref! ⇒ void
Increase dereference count by 1.
-
#evaluate(context) ⇒ Integer
Evaluates the value of lambda.
-
#initialize(obj) ⇒ Lambda
constructor
Instantiate a Lambda object.
-
#operation? ⇒ Boolean
Whether this names an operation rather than a base+offset (see Lambda.operation).
-
#ref! ⇒ self
Decrease dereference count by 1.
-
#to_s ⇒ String
Expand the lambda presentation.
Constructor Details
#initialize(obj) ⇒ Lambda
Instantiate a OneGadget::Emulators::Lambda object.
22 23 24 25 26 |
# File 'lib/one_gadget/emulators/lambda.rb', line 22 def initialize(obj) @immi = 0 @obj = obj @deref_count = 0 end |
Instance Attribute Details
#deref_count ⇒ Integer
Returns The times of dereference.
16 17 18 |
# File 'lib/one_gadget/emulators/lambda.rb', line 16 def deref_count @deref_count end |
#immi ⇒ Integer
Returns The immidiate value currently added.
15 16 17 |
# File 'lib/one_gadget/emulators/lambda.rb', line 15 def immi @immi end |
#obj ⇒ String, Lambda
Returns The object currently related to.
14 15 16 |
# File 'lib/one_gadget/emulators/lambda.rb', line 14 def obj @obj end |
#op ⇒ String?
17 18 19 |
# File 'lib/one_gadget/emulators/lambda.rb', line 17 def op @op end |
#rhs ⇒ Integer, ...
Returns The operator's right operand.
18 19 20 |
# File 'lib/one_gadget/emulators/lambda.rb', line 18 def rhs @rhs end |
Class Method Details
.operation(lhs, op, rhs) ⇒ Lambda
A value this emulator can name but not fold: an operation applied to
lhs, whose result no plain base+offset expresses. Kept as the operation
itself, so a constraint on it still says what the caller has to arrange.
100 101 102 103 104 105 |
# File 'lib/one_gadget/emulators/lambda.rb', line 100 def self.operation(lhs, op, rhs) Lambda.new(lhs).tap do |lmda| lmda.op = op lmda.rhs = rhs end end |
.parse(argument, predefined: {}) ⇒ OneGadget::Emulators::Lambda, Integer
Target: parse string like [rsp+0x50] into a OneGadget::Emulators::Lambda object.
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 |
# File 'lib/one_gadget/emulators/lambda.rb', line 158 def parse(argument, predefined: {}) arg = argument return 0 if arg.empty? || arg == '!' literal = Integer(arg, exception: false) return literal unless literal.nil? # nested [] if arg[0] == '[' ridx = arg.rindex(']') immi = parse(arg[(ridx + 1)..]) inner = parse(arg[1...ridx], predefined:) # An absolute address (the +[0x1234]+ in +lea rax, [0x1234]+) parses to an Integer; # model it as a based-nowhere Lambda so it can still be dereferenced. inner = Lambda.new(nil).tap { |l| l.immi = inner } if inner.is_a?(Integer) lm = inner.deref lm += immi unless immi.zero? return lm end base, disp = mem_obj(arg) obj = predefined[base] # A register may currently hold a call-target string (after a call); # treat that as a fresh symbolic base. Lambda/Integer/xmm-array pass through. obj = Lambda.new(base) if obj.nil? || obj.is_a?(String) obj += disp unless disp.zero? obj end |
Instance Method Details
#+(other) ⇒ Lambda
Implement addition with Numeric.
31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/one_gadget/emulators/lambda.rb', line 31 def +(other) raise Error::InstructionArgumentError, "Expect other(#{other}) to be numeric." unless other.is_a?(Numeric) if deref_count.positive? ret = Lambda.new(self) else ret = Lambda.new(obj) ret.immi = immi ret.op = op ret.rhs = rhs end ret.immi += other ret end |
#-(other) ⇒ Lambda
Implement subtract with Numeric.
49 50 51 |
# File 'lib/one_gadget/emulators/lambda.rb', line 49 def -(other) self + -other end |
#base_str ⇒ String
What #to_s renders before any offset: the operation this names, or the object it is based on.
116 117 118 119 120 121 122 |
# File 'lib/one_gadget/emulators/lambda.rb', line 116 def base_str return '' if obj.nil? return obj.to_s unless operation? rendered = rhs.is_a?(Integer) ? OneGadget::Helper.hex(rhs) : rhs.to_s "(#{obj} #{op} #{rendered})" end |
#deref ⇒ Lambda
A new OneGadget::Emulators::Lambda object with dereference count increase 1.
71 72 73 74 75 76 77 78 |
# File 'lib/one_gadget/emulators/lambda.rb', line 71 def deref ret = Lambda.new(obj) ret.immi = immi ret.op = op ret.rhs = rhs ret.deref_count = deref_count + 1 ret end |
#deref! ⇒ void
This method returns an undefined value.
Increase dereference count by 1.
55 56 57 |
# File 'lib/one_gadget/emulators/lambda.rb', line 55 def deref! @deref_count += 1 end |
#evaluate(context) ⇒ Integer
Evaluates the value of lambda. Only supports +rsp+0x30+ form.
133 134 135 136 137 138 139 |
# File 'lib/one_gadget/emulators/lambda.rb', line 133 def evaluate(context) if deref_count.positive? || (obj && !context.key?(obj)) raise Error::InstructionArgumentError, "Can't eval #{self}" end context[obj] + immi end |
#operation? ⇒ Boolean
Whether this names an operation rather than a base+offset (see operation).
109 110 111 |
# File 'lib/one_gadget/emulators/lambda.rb', line 109 def operation? !op.nil? end |
#ref! ⇒ self
Decrease dereference count by 1.
62 63 64 65 66 67 |
# File 'lib/one_gadget/emulators/lambda.rb', line 62 def ref! raise Error::InstructionArgumentError, 'Cannot reference anymore!' if @deref_count <= 0 @deref_count -= 1 self end |