Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
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
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
#include <memory>
#include <assert.h>
#include "interfaces/idapro/all.h"
#include "interfaces/STARSTypes.h"
#include "interfaces/STARSIDATypes.h"
#include "base/SMPDataFlowAnalysis.h"
#include "base/SMPInstr.h"
#include "interfaces/SMPDBInterface.h"
#include "interfaces/abstract/all.h"
#if 0
#include <pro.h>
#include <nalt.hpp>
#include <ua.hpp>
#include <xref.hpp>
#endif
using namespace std;
static uint32_t UseMacros[STARS_UA_MAXOP] = {STARS_CF_USE1, STARS_CF_USE2, STARS_CF_USE3, STARS_CF_USE4, STARS_CF_USE5, STARS_CF_USE6};
static uint32_t DefMacros[STARS_UA_MAXOP] = {STARS_CF_CHG1, STARS_CF_CHG2, STARS_CF_CHG3, STARS_CF_CHG4, STARS_CF_CHG5, STARS_CF_CHG6};
STARS_InstructionID_t STARS_IDA_Instruction_t::GetNextInstructionID(void) const {
STARS_ea_t addr = this->m_id.GetIDWithinFile();
SMPInstr TempInst(addr);
if (!TempInst.FillCmd()) {
return STARS_BADADDR;
}
STARS_ea_t next_addr = addr + TempInst.GetSize();
return STARS_InstructionID_t(next_addr, this->m_id.GetFileNum());
}
STARS_InstructionID_t STARS_IDA_Instruction_t::GetTargetInstructionID(void) const {
assert(NULL != this->STARScmd.Operands[0]);
STARS_ea_t TargetAddr = this->STARScmd.Operands[0]->GetAddr();
return STARS_InstructionID_t(TargetAddr, this->m_id.GetFileNum());
}
void STARS_IDA_Instruction_t::InitOperand(op_t &InitOp) const {
#if 0
InitOp.n = 0;
InitOp.type = o_void;
InitOp.offb = 0;
InitOp.offo = 0;
InitOp.flags = 0;
InitOp.set_showed();
// NOTE: InitOp.dtyp field is initialized in IDAP_run() to 32 or 64 bits.
InitOp.reg = R_none;
InitOp.value = 0;
InitOp.addr = 0;
InitOp.specval = 0;
InitOp.specflag1 = 0;
InitOp.specflag2 = 0;
InitOp.specflag3 = 0;
InitOp.specflag4 = 0;
#else // not 0
#if __GNUC__ >= 8
#pragma GCC diagnostic ignored "-Wclass-memaccess"
#endif
(void) memset(&InitOp, 0, sizeof(op_t));
#if __GNUC__ >= 8
#pragma GCC diagnostic pop
#endif
#if (IDA_SDK_VERSION < 700)
InitOp.dtyp = global_STARS_program->GetSTARS_ISA_dtyp();
#else
InitOp.dtype = global_STARS_program->GetSTARS_ISA_dtyp();
#endif
#if IDA_SDK_VERSION < 680
InitOp.set_showed();
#else
InitOp.set_shown();
#endif
#endif
return;
} // end of STARS_IDA_Instruction_t::InitOperand()
// Get instruction info by address from IDA Pro.
bool STARS_IDA_Instruction_t::STARS_GetCmd(void) {
bool success = true;
int InstrLen = 0;
this->VoidOpndsPtr = nullptr;
op_t TempOp;
this->InitOperand(TempOp);
this->VoidOpndsPtr = dynamic_pointer_cast<STARS_op_t>(std::make_shared<STARS_IDA_op_t>(TempOp));
// Fill cmd structure with disassembly of instr
#if (IDA_SDK_VERSION < 700)
InstrLen = decode_insn(m_id.GetIDWithinFile());
// Copy cmd fields to member STARScmd.
this->STARScmd.itype = cmd.itype;
this->STARScmd.size = cmd.size;
this->STARScmd.auxpref = cmd.auxpref;
this->STARScmd.segpref = cmd.segpref;
this->STARScmd.insnpref = cmd.insnpref;
this->STARScmd.flags = cmd.flags;
// Get the canonical features into member STARSfeatures.
this->STARSfeatures = cmd.get_canon_feature();
#else
insn_t NewInsn;
InstrLen = ::decode_insn(&NewInsn, m_id.GetIDWithinFile());
// Copy cmd fields to member STARScmd.
this->STARScmd.itype = NewInsn.itype;
this->STARScmd.size = NewInsn.size;
this->STARScmd.auxpref = NewInsn.auxpref;
this->STARScmd.segpref = NewInsn.segpref;
this->STARScmd.insnpref = NewInsn.insnpref;
this->STARScmd.flags = NewInsn.flags;
// Get the canonical features into member STARSfeatures.
#if (IDA_SDK_VERSION < 750)
this->STARSfeatures = NewInsn.get_canon_feature();
#else
this->STARSfeatures = NewInsn.get_canon_feature(PH);
#endif
#endif
if (0 >= InstrLen) {
SMP_msg("ERROR: decode_insn failed at %ullx in file %u\n", (unsigned long long) m_id.GetIDWithinFile(), m_id.GetFileNum());
this->STARScmd.size = 0;
for (int i = 0; i < STARS_UA_MAXOP; ++i) {
this->STARScmd.Operands.push_back(nullptr);
this->STARScmd.Operands[i] = this->MakeVoidOpnd();
}
success = false;
return success;
}
for (int i = 0; i < STARS_UA_MAXOP; ++i) {
#if (IDA_SDK_VERSION < 700)
this->STARScmd.Operands.push_back(std::make_shared<STARS_IDA_op_t>(cmd.Operands[i]));
#else
this->STARScmd.Operands.push_back(std::make_shared<STARS_IDA_op_t>(NewInsn.ops[i]));
#endif
assert(dynamic_pointer_cast<STARS_IDA_op_t>(this->STARScmd.Operands[i]) != nullptr);
dynamic_pointer_cast<STARS_IDA_op_t>(this->STARScmd.Operands[i])->SetSpecFlag4(0);
#ifdef __EA64__
if (global_STARS_program->GetSTARS_ISA_Bitwidth() == 64) {
// Copy the cmd.rex prefix into the op_t.specflag4 field for each operand
// that has a SIB byte.
dynamic_pointer_cast<STARS_IDA_op_t>(this->STARScmd.Operands[i])->SetSpecFlag4(this->STARScmd.rex);
char Flag4Value = this->STARScmd.Operands[i]->GetSpecFlag4();
if (this->STARScmd.Operands[i]->IsMemOp() && (Flag4Value & STARS_REX_R)) {
// Only various register types can have the registger extension, e.g. RBX becomes R11 with extension bit.
Flag4Value -= STARS_REX_R;
dynamic_pointer_cast<STARS_IDA_op_t>(this->STARScmd.Operands[i])->SetSpecFlag4(Flag4Value);
}
}
#endif
// See comments on STARS_VEXPR and STARS_VSIB in SMPDataFlowAnalysis.h.
// These bits do not (as of IDA Pro 6.4) conflict with cmd.rex bits.
#if (IDA_SDK_VERSION < 700)
if ((cmd.auxpref & aux_vexpr) != 0) {
#else
if ((NewInsn.auxpref & aux_vexpr) != 0) {
#endif
dynamic_pointer_cast<STARS_IDA_op_t>(this->STARScmd.Operands[i])->SetBitInSpecFlag4(STARS_VEXPR);
}
switch (this->STARScmd.itype) {
case NN_vgatherdps:
case NN_vgatherdpd:
case NN_vgatherqps:
case NN_vgatherqpd:
case NN_vpgatherdd:
case NN_vpgatherdq:
case NN_vpgatherqd:
case NN_vpgatherqq:
dynamic_pointer_cast<STARS_IDA_op_t>(this->STARScmd.Operands[i])->SetBitInSpecFlag4(STARS_VSIB);
default:
;
}
} // end for all operands
// Simplify the operand encoding so that identical operands don't appear to be different.
for (std::size_t i = 0; i < STARS_UA_MAXOP; ++i) {
this->GetOpnd(i)->CleanOpndEncoding();
}
return success;
} // end of STARS_IDA_Instruction_t::STARS_GetCmd()
bool STARS_IDA_Instruction_t::Has64BitOperands(void) {
#ifdef __EA64__
return (((this->STARScmd.auxpref & aux_use64) != 0)
&& ((this->STARScmd.rex & REX_W) != 0
|| (((this->STARScmd.auxpref & aux_natop) != 0) && this->OpcodeDefaultsTo64BitOperands())));
// 64-bit segment, rex.w or insns-64
#else
return false;
#endif
}
bool STARS_IDA_Instruction_t::Uses32BitAddressing(void) const {
int Temp = this->STARScmd.auxpref & (aux_use32 | aux_use64 | aux_natad);
return (Temp == (aux_natad | aux_use32))
|| (Temp == 0)
|| (Temp == aux_use64);
}
bool STARS_IDA_Instruction_t::IsUseOpnd(std::size_t OpndNum) const {
return (this->GetInstFeatures() & UseMacros[OpndNum]);
}
bool STARS_IDA_Instruction_t::IsDefOpnd(std::size_t OpndNum) const {
return (this->GetInstFeatures() & DefMacros[OpndNum]);
}
// set the USE bit
void STARS_IDA_Instruction_t::SetOpUsed(std::size_t OpndNum) {
this->STARSfeatures |= UseMacros[OpndNum];
return;
}
// reset the USE bit
void STARS_IDA_Instruction_t::SetOpNotUsed(std::size_t OpndNum) {
this->STARSfeatures &= (~UseMacros[OpndNum]);
return;
}
// set the DEF bit
void STARS_IDA_Instruction_t::SetOpDefed(std::size_t OpndNum) {
this->STARSfeatures |= DefMacros[OpndNum];
return;
}
// reset the DEF bit
void STARS_IDA_Instruction_t::SetOpNotDefed(std::size_t OpndNum) {
this->STARSfeatures &= (~DefMacros[OpndNum]);
return;
}
// Fix up IDA Pro IMUL instruction by removing operand 1
void STARS_IDA_Instruction_t::RemoveIDAOp1ForIMUL(void) {
this->STARScmd.Operands[1] = this->STARScmd.Operands[2];
this->STARScmd.Operands[2] = this->VoidOpndsPtr;
return;
}
STARSOpndTypePtr STARS_IDA_Instruction_t::MakeVoidOpnd(void) const {
return this->VoidOpndsPtr;
} // end of STARS_IDA_Instruction_t::MakeVoidOpnd()
STARSOpndTypePtr STARS_IDA_Instruction_t::MakeImmediateOpnd(STARS_uval_t value) const {
op_t TempOp;
this->InitOperand(TempOp);
TempOp.type = o_imm;
TempOp.value = value;
return dynamic_pointer_cast<STARS_op_t>(std::make_shared<STARS_IDA_op_t>(TempOp));
} // end of STARS_IDA_Instruction_t::MakeVoidOpnd()
STARSOpndTypePtr STARS_IDA_Instruction_t::MakeRegOpnd(STARS_regnum_t RegNum, bool DefaultToMachineWidth) {
op_t TempOp;
this->InitOperand(TempOp);
TempOp.type = o_reg;
#if (IDA_SDK_VERSION < 700)
TempOp.dtyp = GetRegDtyp(RegNum, (DefaultToMachineWidth && (global_STARS_program->GetSTARS_ISA_Bitwidth() == 64)));
#else
TempOp.dtype = GetRegDtyp(RegNum, (DefaultToMachineWidth && (global_STARS_program->GetSTARS_ISA_Bitwidth() == 64)));
#endif
TempOp.reg = RegNum;
return dynamic_pointer_cast<STARS_op_t>(std::make_shared<STARS_IDA_op_t>(TempOp));
} // end of STARS_IDA_Instruction_t::MakeRegOpnd()
STARSOpndTypePtr STARS_IDA_Instruction_t::MakeFloatingPointRegOpnd(STARS_regnum_t RegNum) {
op_t TempOp;
this->InitOperand(TempOp);
TempOp.type = o_fpreg;
if (RegNum < STARS_x86_R_st0) {
// X86 encodes STARS_x86_R_st0 as register 0, STARS_x86_R_st1 as register 1, with o_fpreg flag indicating adjustment.
// We want to encode using the STARS_regnum_t enumeration alone.
RegNum = (STARS_regnum_t) (((int) STARS_x86_R_st0) + ((int) RegNum));
}
TempOp.reg = RegNum;
#if (IDA_SDK_VERSION < 700)
TempOp.dtyp = GetRegDtyp(RegNum, false);
#else
TempOp.dtype = GetRegDtyp(RegNum, false);
#endif
return dynamic_pointer_cast<STARS_op_t>(std::make_shared<STARS_IDA_op_t>(TempOp));
} // end of STARS_IDA_Instruction_t::MakeFloatingPointRegOpnd()
STARSOpndTypePtr STARS_IDA_Instruction_t::MakeMMXRegOpnd(STARS_regnum_t RegNum) {
op_t TempOp;
this->InitOperand(TempOp);
TempOp.type = o_mmxreg;
TempOp.reg = RegNum;
#if (IDA_SDK_VERSION < 700)
TempOp.dtyp = GetRegDtyp(RegNum, false);
#else
TempOp.dtype = GetRegDtyp(RegNum, false);
#endif
return dynamic_pointer_cast<STARS_op_t>(std::make_shared<STARS_IDA_op_t>(TempOp));
} // end of STARS_IDA_Instruction_t::MakeMMXRegOpnd()
STARSOpndTypePtr STARS_IDA_Instruction_t::MakeXMMRegOpnd(STARS_regnum_t RegNum) {
op_t TempOp;
this->InitOperand(TempOp);
TempOp.type = o_xmmreg;
TempOp.reg = RegNum;
#if (IDA_SDK_VERSION < 700)
TempOp.dtyp = GetRegDtyp(RegNum, false);
#else
TempOp.dtype = GetRegDtyp(RegNum, false);
#endif
return dynamic_pointer_cast<STARS_op_t>(std::make_shared<STARS_IDA_op_t>(TempOp));
} // end of STARS_IDA_Instruction_t::MakeXMMRegOpnd()
STARSOpndTypePtr STARS_IDA_Instruction_t::MakeYMMRegOpnd(STARS_regnum_t RegNum) {
op_t TempOp;
this->InitOperand(TempOp);
TempOp.type = o_ymmreg;
TempOp.reg = RegNum;
#if (IDA_SDK_VERSION < 700)
TempOp.dtyp = GetRegDtyp(RegNum, false);
#else
TempOp.dtype = GetRegDtyp(RegNum, false);
#endif
return dynamic_pointer_cast<STARS_op_t>(std::make_shared<STARS_IDA_op_t>(TempOp));
} // end of STARS_IDA_Instruction_t::MakeYMMRegOpnd()
STARSOpndTypePtr STARS_IDA_Instruction_t::MakeNearPointerOpnd(STARS_ea_t TargetAddr) const {
op_t TempOp;
this->InitOperand(TempOp);
TempOp.type = o_near;
TempOp.addr = TargetAddr;
return dynamic_pointer_cast<STARS_op_t>(std::make_shared<STARS_IDA_op_t>(TempOp));
}
STARSOpndTypePtr STARS_IDA_Instruction_t::MakeMemPhraseOpnd(STARS_regnum_t BaseRegNum, STARS_regnum_t IndexRegNum, uint16_t ScaleFactor) {
// TODO: Construct SIB byte when IndexRegNum is used.
op_t TempOp;
this->InitOperand(TempOp);
TempOp.type = o_phrase;
TempOp.reg = BaseRegNum;
#if (IDA_SDK_VERSION < 700)
TempOp.dtyp = GetRegDtyp(BaseRegNum, this->Has64BitOperands());
#else
TempOp.dtype = GetRegDtyp(BaseRegNum, this->Has64BitOperands());
#endif
return dynamic_pointer_cast<STARS_op_t>(std::make_shared<STARS_IDA_op_t>(TempOp));
} // end of STARS_IDA_Instruction_t::MakeMemPhraseOpnd()
STARSOpndTypePtr STARS_IDA_Instruction_t::MakeMemDisplacementOpnd(STARS_regnum_t BaseRegNum, STARS_regnum_t IndexRegNum, uint16_t ScaleFactor, STARS_ea_t offset) {
// TODO: Construct SIB byte when IndexRegNum is used.
op_t TempOp;
this->InitOperand(TempOp);
TempOp.type = o_displ;
TempOp.reg = BaseRegNum;
TempOp.addr = (ea_t) offset;
#if (IDA_SDK_VERSION < 700)
TempOp.dtyp = GetRegDtyp(BaseRegNum, this->Has64BitOperands());
#else
TempOp.dtype = GetRegDtyp(BaseRegNum, this->Has64BitOperands());
#endif
return dynamic_pointer_cast<STARS_op_t>(std::make_shared<STARS_IDA_op_t>(TempOp));
} // end of STARS_IDA_Instruction_t::MakeMemDisplacementOpnd()
bool STARS_IDA_Instruction_t::IsBranchToFarChunk(SMPInstr *CurrInst, STARS_ea_t &TargetAddr) {
bool FarBranch = false;
set<DefOrUse, LessDefUse>::iterator CurrUse;
func_t *CurrChunk = ::get_fchunk(this->m_id.GetIDWithinFile());
if (nullptr != CurrChunk) { // CurrInst is not an orphan
for (CurrUse = CurrInst->GetFirstUse(); CurrUse != CurrInst->GetLastUse(); ++CurrUse) {
STARSOpndTypePtr JumpTarget = CurrUse->GetOp();
if (JumpTarget->IsNearPointer() || JumpTarget->IsFarPointer()) {
// Branches to a code address
TargetAddr = JumpTarget->GetAddr();
// stdclib sometimes has jumps to zero and calls to zero. These are dead code.
if ((0 != TargetAddr) && (STARS_BADADDR != TargetAddr)) {
func_t *TargetChunk = ::get_fchunk(TargetAddr);
// Is target address within the same chunk as the branch?
#if (IDA_SDK_VERSION < 700)
FarBranch = (NULL == TargetChunk) || (CurrChunk->startEA != TargetChunk->startEA);
#else
FarBranch = (NULL == TargetChunk) || (CurrChunk->start_ea != TargetChunk->start_ea);
#endif
}
}
} // end for all USEs
}
return FarBranch;
} // end of STARS_IDA_Instruction_t::IsBranchToFarChunk()
bool STARS_IDA_Instruction_t::IsPushFromFixedCall(void) const {
STARS_ea_t TargetAddr = this->STARScmd.Operands[0]->GetAddr();
bool PushOfInternalAddress = global_STARS_program->AreInstIDsInSameFunction(this->m_id.GetIDWithinFile(), TargetAddr);
return PushOfInternalAddress;
}
STARS_InstructionID_Set_t STARS_IDA_Instruction_t::GetReferencedInstructionIDs(bool &success) {
assert(false);
return STARS_InstructionID_Set_t();
}
// Get inst IDs of jump targets, call targets, etc., including for analyzeable indirect calls and jumps; success = false otherwise
STARS_InstructionID_Set_t STARS_IDA_Instruction_t::GetTargetedInstructionIDs(bool &success) {
STARS_InstructionID_Set_t TargetIDSet;
// Use code xrefs to find non-fallthrough code targets.
SMP_xref_t InstXrefs;
for (bool ok = InstXrefs.SMP_first_from(this->m_id.GetIDWithinFile(), XREF_FAR); ok; ok = InstXrefs.SMP_next_from()) {
if (!InstXrefs.GetIscode())
break; // no need to go on to data xrefs
assert(fl_F != InstXrefs.GetType()); // should not be ordinary fall-through
STARS_ea_t TargetAddr = InstXrefs.GetTo();
assert(STARS_BADADDR != TargetAddr);
STARS_InstructionID_t TargetID(TargetAddr);
pair<STARS_InstructionID_Set_t::iterator, bool> InsertResult = TargetIDSet.insert(TargetID);
assert(InsertResult.second);
}
success = (!TargetIDSet.empty());
return TargetIDSet;
}
// return inst ID addr for fall-through from this inst
STARS_ea_t STARS_IDA_Instruction_t::GetFallThroughInstID(void) {
STARS_ea_t FallThroughAddr = STARS_BADADDR;
SMP_xref_t InstXrefs;
for (bool ok = InstXrefs.SMP_first_from(this->m_id.GetIDWithinFile(), XREF_ALL); ok; ok = InstXrefs.SMP_next_from()) {
if (!InstXrefs.GetIscode())
break; // no need to go on to data xrefs
if (fl_F == InstXrefs.GetType()) { // ordinary fall-through
FallThroughAddr = InstXrefs.GetTo();
break;
}
}
if (STARS_BADADDR == FallThroughAddr) {
// We could try to use SMPBasicBlock::FindCallInstFallThrough() here
// to audit the completeness of the Xrefs.
;
}
return FallThroughAddr;
} // end of STARS_IDA_Instruction_t::GetFallThroughInstID()
// Analyze the indirect jump at IndirJumpInst, put switch table info in TableInfo if available, return false otherwise.
// Note: The TableInfo.FollowNodeNum field must be determined by later analysis.
bool STARS_IDA_Instruction_t::AnalyzeSwitchStatement(SMPInstr *IndirJumpInst, struct SwitchTableInfo &TableInfo) {
bool success = false;
assert(NULL != IndirJumpInst);
assert(INDIR_JUMP == IndirJumpInst->GetDataFlowType());
STARS_ea_t IndirJumpAddr = IndirJumpInst->GetAddr();
#if (IDA_SDK_VERSION < 700)
switch_info_ex_t SwitchInfo;
if (get_switch_info_ex(IndirJumpAddr, &SwitchInfo, sizeof(SwitchInfo)) > 0) {
#else
switch_info_t SwitchInfo;
if (get_switch_info(&SwitchInfo, IndirJumpAddr) > 0) {
#endif
casevec_t CaseVector;
eavec_t TargetAddrsVector;
#if (IDA_SDK_VERSION < 700)
success = ::calc_switch_cases(IndirJumpAddr, &SwitchInfo, &CaseVector, &TargetAddrsVector);
#else
success = ::calc_switch_cases(&CaseVector, &TargetAddrsVector, IndirJumpAddr, SwitchInfo);
#endif
if (success) {
success = (CaseVector.size() == TargetAddrsVector.size()); // sanity check
}
if (success) {
// Transfer data into TableInfo.
TableInfo.FollowNodeNum = SMP_BLOCKNUM_UNINIT;
TableInfo.IDomBlockNum = SMP_BLOCKNUM_UNINIT;
TableInfo.IndirJumpBlockNum = IndirJumpInst->GetBlock()->GetNumber();
TableInfo.DefaultJumpAddr = SwitchInfo.defjump; // will be STARS_BADADDR if no default case
if (STARS_BADADDR != TableInfo.DefaultJumpAddr) {
// We have a default case
// Guard against bad disassembly by making sure the default case addr is in the function.
if (! IndirJumpInst->GetBlock()->GetFunc()->IsInstIDInFunc(TableInfo.DefaultJumpAddr)) {
success = false;
SMP_msg("ERROR: AnalyzeSwitchStatement: Switch default case addr %llx not in func %s\n", (uint64_t)TableInfo.DefaultJumpAddr,
IndirJumpInst->GetBlock()->GetFunc()->GetFuncName());
return success;
}
SMPBasicBlock *DefaultCaseBlock = IndirJumpInst->GetBlock()->GetFunc()->GetBlockFromInstAddr(TableInfo.DefaultJumpAddr);
assert(NULL != DefaultCaseBlock);
int DefaultBlockNum = DefaultCaseBlock->GetNumber();
assert(SMP_BLOCKNUM_UNINIT != DefaultBlockNum);
TableInfo.DefaultCaseBlockNum = DefaultBlockNum;
}
else {
TableInfo.DefaultCaseBlockNum = SMP_BLOCKNUM_UNINIT;
}
std::size_t IndexLimit = CaseVector.size();
for (std::size_t Index = 0; Index < IndexLimit; ++Index) {
std::vector<STARS_sval_t> CurrCaseValues;
std::size_t CaseIndexLimit = CaseVector[Index].size();
for (std::size_t CaseIndex = 0; CaseIndex < CaseIndexLimit; ++CaseIndex) {
// Can have case 2, case 4, case 7 etc. all map to one target block
CurrCaseValues.push_back((STARS_sval_t) CaseVector[Index].at(CaseIndex));
}
TableInfo.IndexValue.push_back(CurrCaseValues);
STARS_ea_t TargetAddr = (STARS_ea_t) TargetAddrsVector[Index];
// Translate TargetAddr to a block number.
if (STARS_BADADDR == TargetAddr) {
success = false;
break;
}
int TargetBlockNum = IndirJumpInst->GetBlock()->GetFunc()->GetBlockNumFromInstAddr(TargetAddr);
if (SMP_BLOCKNUM_UNINIT == TargetBlockNum) {
success = false;
break;
}
TableInfo.CaseBlockNums.push_back(TargetBlockNum);
} // end for Index = 0 to IndexLimit
} // end if success
} // end if get_switch_info_ex() > 0
return success;
} // end of STARS_IDA_Instruction_t::AnalyzeSwitchStatement()