Skip to content

Commit 51707bc

Browse files
committed
Binary: Add support for two new instructions (return with value and instruction references. These are needed for CIL translation.
1 parent a231572 commit 51707bc

9 files changed

Lines changed: 201 additions & 27 deletions

File tree

binary/ql/lib/semmle/code/binary/ast/ir/internal/Instruction0/Instruction.qll

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,12 @@ class RetInstruction extends Instruction {
131131
override Opcode::Ret opcode;
132132
}
133133

134+
class RetValueInstruction extends Instruction {
135+
override Opcode::RetValue opcode;
136+
137+
UnaryOperand getReturnValueOperand() { result = this.getAnOperand() }
138+
}
139+
134140
class InitInstruction extends Instruction {
135141
override Opcode::Init opcode;
136142
}
@@ -163,6 +169,21 @@ class CallInstruction extends Instruction {
163169
override string getImmediateValue() { result = this.getStaticTarget().getName() }
164170
}
165171

172+
class InstrRefInstruction extends Instruction {
173+
override Opcode::InstrRef opcode;
174+
175+
Instruction getReferencedInstruction() { result = te.getReferencedInstruction(tag) }
176+
177+
final override string getImmediateValue() {
178+
exists(Instruction ref | ref = this.getReferencedInstruction() |
179+
result = ref.getResultVariable().toString()
180+
or
181+
not exists(ref.getResultVariable()) and
182+
result = "<reference to instruction without result>"
183+
)
184+
}
185+
}
186+
166187
class BinaryInstruction extends Instruction {
167188
override Opcode::BinaryOpcode opcode;
168189

binary/ql/lib/semmle/code/binary/ast/ir/internal/Instruction0/TranslatedElement.qll

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,11 @@ class Opcode = Opcode::Opcode;
1414

1515
private predicate shouldTranslateX86Instr(Raw::X86Instruction instr) { any() }
1616

17-
private predicate shouldTranslateX86Operand(Raw::X86Operand operand) { any() }
17+
private predicate shouldTranslateX86Operand(Raw::X86Operand operand) {
18+
// If it has a target we will synthesize an instruction reference instruction
19+
// instead of translating the operand directly.
20+
not exists(operand.getUse().(Raw::X86Jmp).getTarget())
21+
}
1822

1923
newtype TTranslatedElement =
2024
TTranslatedX86Function(Raw::X86Instruction entry) {
@@ -88,6 +92,8 @@ abstract class TranslatedElement extends TTranslatedElement {
8892

8993
int getConstantValue(InstructionTag tag) { none() }
9094

95+
Instruction getReferencedInstruction(InstructionTag tag) { none() }
96+
9197
abstract Raw::Element getRawElement();
9298

9399
abstract Instruction getSuccessor(InstructionTag tag, SuccessorType succType);

binary/ql/lib/semmle/code/binary/ast/ir/internal/Instruction0/TranslatedInstruction.qll

Lines changed: 77 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -333,40 +333,66 @@ class TranslatedX86Jmp extends TranslatedX86Instruction, TTranslatedX86Jmp {
333333
final override predicate hasInstruction(
334334
Opcode opcode, InstructionTag tag, Option<Variable>::Option v
335335
) {
336-
tag = SingleTag() and
336+
tag = X86JumpTag() and
337337
opcode instanceof Opcode::Jump and
338338
v.isNone() // A jump has no result
339+
or
340+
exists(instr.getTarget()) and
341+
tag = X86JumpInstrRefTag() and
342+
opcode instanceof Opcode::InstrRef and
343+
v.asSome() = this.getVariable(X86JumpInstrRefVarTag())
339344
}
340345

341346
override predicate producesResult() { any() }
342347

348+
override predicate hasTempVariable(VariableTag tag) {
349+
exists(instr.getTarget()) and
350+
tag = X86JumpInstrRefVarTag()
351+
}
352+
353+
override Instruction getReferencedInstruction(InstructionTag tag) {
354+
tag = X86JumpInstrRefTag() and
355+
result = getTranslatedInstruction(instr.getTarget()).getEntry()
356+
}
357+
343358
override Variable getVariableOperand(InstructionTag tag, OperandTag operandTag) {
344-
tag = SingleTag() and
359+
tag = X86JumpTag() and
345360
operandTag = JumpTargetTag() and
346-
result = this.getTranslatedOperand().getResultVariable()
361+
if exists(instr.getTarget())
362+
then result = this.getInstruction(X86JumpInstrRefTag()).getResultVariable()
363+
else result = this.getTranslatedOperand().getResultVariable()
347364
}
348365

349366
TranslatedOperand getTranslatedOperand() { result = getTranslatedOperand(instr.getOperand(0)) }
350367

351368
override Instruction getChildSuccessor(TranslatedElement child, SuccessorType succType) {
369+
not exists(instr.getTarget()) and
352370
child = this.getTranslatedOperand() and
353371
succType instanceof DirectSuccessor and
354-
result = this.getInstruction(SingleTag())
372+
result = this.getInstruction(X86JumpTag())
355373
}
356374

357375
override Instruction getSuccessor(InstructionTag tag, SuccessorType succType) {
358-
tag = SingleTag() and
376+
exists(instr.getTarget()) and
377+
tag = X86JumpInstrRefTag() and
378+
succType instanceof DirectSuccessor and
379+
result = this.getInstruction(X86JumpTag())
380+
or
381+
tag = X86JumpTag() and
359382
succType instanceof DirectSuccessor and
360383
result = getTranslatedInstruction(instr.getTarget()).getEntry()
361384
}
362385

363386
override Instruction getEntry() {
364-
exists(Option<Instruction>::Option op | op = this.getTranslatedOperand().getEntry() |
365-
result = op.asSome()
366-
or
367-
op.isNone() and
368-
result = this.getInstruction(SingleTag())
369-
)
387+
if exists(instr.getTarget())
388+
then result = this.getInstruction(X86JumpInstrRefTag())
389+
else
390+
exists(Option<Instruction>::Option op | op = this.getTranslatedOperand().getEntry() |
391+
result = op.asSome()
392+
or
393+
op.isNone() and
394+
result = this.getInstruction(X86JumpTag())
395+
)
370396
}
371397

372398
override Variable getResultVariable() { none() }
@@ -728,13 +754,18 @@ class TranslatedX86ConditionalJump extends TranslatedX86Instruction, TTranslated
728754
final override predicate hasInstruction(
729755
Opcode opcode, InstructionTag tag, Option<Variable>::Option v
730756
) {
757+
exists(instr.getTarget()) and
758+
tag = X86CJumpInstrRefTag() and
759+
opcode instanceof Opcode::InstrRef and
760+
v.asSome() = this.getVariable(X86CJumpInstrRefVarTag())
761+
or
731762
opcode instanceof Opcode::CJump and
732-
tag = SingleTag() and
763+
tag = X86CJumpTag() and
733764
v.isNone() // A jump has no result
734765
}
735766

736767
override predicate hasJumpCondition(InstructionTag tag, Opcode::ConditionKind kind) {
737-
tag = SingleTag() and
768+
tag = X86CJumpTag() and
738769
(
739770
instr instanceof Raw::X86Jb and kind = Opcode::LT()
740771
or
@@ -762,15 +793,29 @@ class TranslatedX86ConditionalJump extends TranslatedX86Instruction, TTranslated
762793
)
763794
}
764795

796+
override predicate hasTempVariable(VariableTag tag) {
797+
exists(instr.getTarget()) and
798+
tag = X86CJumpInstrRefVarTag()
799+
}
800+
801+
override Instruction getReferencedInstruction(InstructionTag tag) {
802+
tag = X86CJumpInstrRefTag() and
803+
result = getTranslatedInstruction(instr.getTarget()).getEntry()
804+
}
805+
765806
override predicate hasSynthVariable(SynthRegisterTag tag) { tag = CmpRegisterTag() }
766807

767808
override predicate producesResult() { any() }
768809

769810
override Variable getVariableOperand(InstructionTag tag, OperandTag operandTag) {
770-
tag = SingleTag() and
811+
tag = X86CJumpTag() and
771812
(
772813
operandTag = CondJumpTargetTag() and
773-
result = this.getTranslatedOperand().getResultVariable()
814+
(
815+
if exists(instr.getTarget())
816+
then result = this.getInstruction(X86CJumpInstrRefTag()).getResultVariable()
817+
else result = this.getTranslatedOperand().getResultVariable()
818+
)
774819
or
775820
operandTag = CondTag() and
776821
result = getTranslatedVariableSynth(CmpRegisterTag())
@@ -780,13 +825,19 @@ class TranslatedX86ConditionalJump extends TranslatedX86Instruction, TTranslated
780825
TranslatedOperand getTranslatedOperand() { result = getTranslatedOperand(instr.getOperand(0)) }
781826

782827
override Instruction getChildSuccessor(TranslatedElement child, SuccessorType succType) {
828+
not exists(instr.getTarget()) and
783829
child = this.getTranslatedOperand() and
784830
succType instanceof DirectSuccessor and
785-
result = this.getInstruction(SingleTag())
831+
result = this.getInstruction(X86CJumpTag())
786832
}
787833

788834
override Instruction getSuccessor(InstructionTag tag, SuccessorType succType) {
789-
tag = SingleTag() and
835+
exists(instr.getTarget()) and
836+
tag = X86CJumpInstrRefTag() and
837+
succType instanceof DirectSuccessor and
838+
result = this.getInstruction(X86CJumpTag())
839+
or
840+
tag = X86CJumpTag() and
790841
(
791842
succType.(BooleanSuccessor).getValue() = true and
792843
result = getTranslatedInstruction(instr.getTarget()).getEntry()
@@ -797,12 +848,15 @@ class TranslatedX86ConditionalJump extends TranslatedX86Instruction, TTranslated
797848
}
798849

799850
override Instruction getEntry() {
800-
exists(Option<Instruction>::Option op | op = this.getTranslatedOperand().getEntry() |
801-
result = op.asSome()
802-
or
803-
op.isNone() and
804-
result = this.getInstruction(SingleTag())
805-
)
851+
if exists(instr.getTarget())
852+
then result = this.getInstruction(X86CJumpInstrRefTag())
853+
else
854+
exists(Option<Instruction>::Option op | op = this.getTranslatedOperand().getEntry() |
855+
result = op.asSome()
856+
or
857+
op.isNone() and
858+
result = this.getInstruction(X86CJumpTag())
859+
)
806860
}
807861

808862
override Variable getResultVariable() { none() }
@@ -941,8 +995,6 @@ class TranslatedX86Lea extends TranslatedX86Instruction, TTranslatedX86Lea {
941995
override Variable getResultVariable() {
942996
result = this.getTranslatedDestOperand().getResultVariable()
943997
}
944-
945-
override string toString() { result = TranslatedX86Instruction.super.toString() }
946998
}
947999

9481000
class TranslatedX86Pop extends TranslatedX86Instruction, TTranslatedX86Pop {

binary/ql/lib/semmle/code/binary/ast/ir/internal/Instruction1/Instruction1.qll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,8 @@ private module InstructionInput implements Transform<Instruction0>::TransformInp
289289
InstructionTag tag, SuccessorType succType
290290
);
291291

292+
EitherInstructionTranslatedElementTagPair getReferencedInstruction(InstructionTag tag) { none() }
293+
292294
abstract EitherInstructionTranslatedElementTagPair getInstructionSuccessor(
293295
Instruction0::Instruction i, SuccessorType succType
294296
);

binary/ql/lib/semmle/code/binary/ast/ir/internal/Instruction2/Instruction2.qll

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,10 @@ module InstructionInput implements Transform<Instruction1>::TransformInputSig {
259259

260260
int getConstantValue(InstructionTag tag) { none() }
261261

262+
EitherInstructionTranslatedElementTagPair getReferencedInstruction(InstructionTag tag) {
263+
none()
264+
}
265+
262266
predicate hasJumpCondition(InstructionTag tag, ConditionKind kind) { none() }
263267

264268
predicate hasTempVariable(VariableTag tag) { none() }

binary/ql/lib/semmle/code/binary/ast/ir/internal/InstructionSig.qll

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,10 @@ signature module InstructionSig {
110110

111111
class RetInstruction extends Instruction;
112112

113+
class RetValueInstruction extends Instruction {
114+
UnaryOperand getReturnValueOperand();
115+
}
116+
113117
class BinaryInstruction extends Instruction {
114118
LeftOperand getLeftOperand();
115119

@@ -148,6 +152,10 @@ signature module InstructionSig {
148152
JumpTargetOperand getJumpTargetOperand();
149153
}
150154

155+
class InstrRefInstruction extends Instruction {
156+
Instruction getReferencedInstruction();
157+
}
158+
151159
class CopyInstruction extends Instruction {
152160
UnaryOperand getOperand();
153161
}

binary/ql/lib/semmle/code/binary/ast/ir/internal/InstructionTag.qll

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@ private import Opcode
22

33
newtype TInstructionTag =
44
SingleTag() or
5+
X86JumpInstrRefTag() or
6+
X86JumpTag() or
7+
X86CJumpInstrRefTag() or
8+
X86CJumpTag() or
59
WriteTag() or
610
InitFramePtrTag() or
711
InitStackPtrTag() or
@@ -42,6 +46,18 @@ class InstructionTag extends TInstructionTag {
4246
this = SingleTag() and
4347
result = "Single"
4448
or
49+
this = X86JumpInstrRefTag() and
50+
result = "X86JumpInstrRef"
51+
or
52+
this = X86JumpTag() and
53+
result = "X86Jump"
54+
or
55+
this = X86CJumpInstrRefTag() and
56+
result = "X86CJumpInstrRef"
57+
or
58+
this = X86CJumpTag() and
59+
result = "X86CJump"
60+
or
4561
this = WriteTag() and
4662
result = "Write"
4763
or
@@ -134,6 +150,8 @@ class InstructionTag extends TInstructionTag {
134150
}
135151

136152
newtype VariableTag =
153+
X86JumpInstrRefVarTag() or
154+
X86CJumpInstrRefVarTag() or
137155
TestVarTag() or
138156
ZeroVarTag() or
139157
ImmediateOperandVarTag() or
@@ -162,6 +180,12 @@ string stringOfSynthRegisterTag(SynthRegisterTag tag) {
162180
}
163181

164182
string stringOfVariableTag(VariableTag tag) {
183+
tag = X86JumpInstrRefVarTag() and
184+
result = "j_ir"
185+
or
186+
tag = X86CJumpInstrRefVarTag() and
187+
result = "cj_ir"
188+
or
165189
tag = TestVarTag() and
166190
result = "t"
167191
or

binary/ql/lib/semmle/code/binary/ast/ir/internal/Opcode.qll

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,12 @@ private newtype TOpcode =
1919
TCopy() or
2020
TJump() or
2121
TCJump() or
22+
TRetValue() or
2223
TRet() or
2324
TNop() or
2425
TNot() or
25-
TInit()
26+
TInit() or
27+
TInstrRef()
2628

2729
class Opcode extends TOpcode {
2830
string toString() { none() }
@@ -116,6 +118,10 @@ class Ret extends Opcode, TRet {
116118
override string toString() { result = "Ret" }
117119
}
118120

121+
class RetValue extends Opcode, TRetValue {
122+
override string toString() { result = "RetValue" }
123+
}
124+
119125
class Nop extends Opcode, TNop {
120126
override string toString() { result = "Nop" }
121127
}
@@ -124,6 +130,10 @@ class Not extends Opcode, TNot {
124130
override string toString() { result = "Not" }
125131
}
126132

133+
class InstrRef extends Opcode, TInstrRef {
134+
override string toString() { result = "InstrRef" }
135+
}
136+
127137
class Init extends Opcode, TInit {
128138
override string toString() { result = "Init" }
129139
}

0 commit comments

Comments
 (0)