parser.cpp 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362
  1. /****************************************************************************
  2. * dcc project procedure list builder
  3. * (C) Cristina Cifuentes, Mike van Emmerik, Jeff Ledermann
  4. ****************************************************************************/
  5. #include "dcc.h"
  6. #include "project.h"
  7. #include "CallGraph.h"
  8. #include "msvc_fixes.h"
  9. #include <QMap>
  10. #include <QtCore/QDebug>
  11. #include <inttypes.h>
  12. #include <cstring>
  13. #include <cstdlib> /* For exit() */
  14. #include <cstdio>
  15. #include <sstream>
  16. #include <algorithm>
  17. #include <deque>
  18. using namespace std;
  19. //static void FollowCtrl (Function * pProc, CALL_GRAPH * pcallGraph, STATE * pstate);
  20. static void setBits(int16_t type, uint32_t start, uint32_t len);
  21. static void process_MOV(LLInst &ll, STATE * pstate);
  22. static SYM * lookupAddr (LLOperand *pm, STATE * pstate, int size, uint16_t duFlag);
  23. void interactDis(Function * initProc, int ic);
  24. extern uint32_t SynthLab;
  25. /* Returns the size of the string pointed by sym and delimited by delim.
  26. * Size includes delimiter. */
  27. int strSize (const uint8_t *sym, char delim)
  28. {
  29. PROG &prog(Project::get()->prog);
  30. int till_end = sym-prog.image();
  31. const uint8_t *end_ptr=std::find(sym,sym+(prog.cbImage-(till_end)),delim);
  32. return end_ptr-sym+1;
  33. }
  34. ICODE * Function::translate_DIV(LLInst *ll, ICODE &_Icode)
  35. {
  36. /* MOV rTMP, reg */
  37. ICODE eIcode = ICODE();
  38. eIcode.type = LOW_LEVEL_ICODE;
  39. eIcode.ll()->set(iMOV,0,rTMP);
  40. if (ll->testFlags(B) )
  41. {
  42. eIcode.ll()->setFlags( B );
  43. eIcode.ll()->replaceSrc(rAX);
  44. }
  45. else /* implicit dx:ax */
  46. {
  47. eIcode.ll()->setFlags( IM_SRC );
  48. eIcode.setRegDU( rDX, eUSE);
  49. }
  50. eIcode.setRegDU( rAX, eUSE);
  51. eIcode.setRegDU( rTMP, eDEF);
  52. eIcode.ll()->setFlags( SYNTHETIC );
  53. /* eIcode.ll()->label = SynthLab++; */
  54. eIcode.ll()->label = _Icode.ll()->label;
  55. Icode.addIcode(&eIcode);
  56. /* iDIV, iIDIV */
  57. Icode.addIcode(&_Icode);
  58. /* iMOD */
  59. eIcode = ICODE();
  60. eIcode.type = LOW_LEVEL_ICODE;
  61. eIcode.ll()->set(iMOD,ll->getFlag() | SYNTHETIC | IM_TMP_DST);
  62. eIcode.ll()->replaceSrc(_Icode.ll()->src());
  63. eIcode.du = _Icode.du;
  64. eIcode.ll()->label = SynthLab++;
  65. return Icode.addIcode(&eIcode);
  66. }
  67. ICODE *Function::translate_XCHG(LLInst *ll,ICODE &_Icode)
  68. {
  69. /* MOV rTMP, regDst */
  70. ICODE eIcode;
  71. eIcode.type = LOW_LEVEL_ICODE;
  72. eIcode.ll()->set(iMOV,SYNTHETIC,rTMP,ll->m_dst);
  73. eIcode.setRegDU( rTMP, eDEF);
  74. if(eIcode.ll()->src().getReg2())
  75. {
  76. eReg srcreg=eIcode.ll()->src().getReg2();
  77. eIcode.setRegDU( srcreg, eUSE);
  78. if((srcreg>=rAL) and (srcreg<=rBH))
  79. eIcode.ll()->setFlags( B );
  80. }
  81. eIcode.ll()->label = ll->label;
  82. Icode.addIcode(&eIcode);
  83. /* MOV regDst, regSrc */
  84. ll->set(iMOV,SYNTHETIC|ll->getFlag());
  85. Icode.addIcode(&_Icode);
  86. ll->setOpcode(iXCHG); /* for next case */
  87. /* MOV regSrc, rTMP */
  88. eIcode = ICODE();
  89. eIcode.type = LOW_LEVEL_ICODE;
  90. eIcode.ll()->set(iMOV,SYNTHETIC);
  91. eIcode.ll()->replaceDst(ll->src());
  92. if(eIcode.ll()->m_dst.regi)
  93. {
  94. if((eIcode.ll()->m_dst.regi>=rAL) and (eIcode.ll()->m_dst.regi<=rBH))
  95. eIcode.ll()->setFlags( B );
  96. eIcode.setRegDU( eIcode.ll()->m_dst.regi, eDEF);
  97. }
  98. eIcode.ll()->replaceSrc(rTMP);
  99. eIcode.setRegDU( rTMP, eUSE);
  100. eIcode.ll()->label = SynthLab++;
  101. return Icode.addIcode(&eIcode);
  102. }
  103. /** FollowCtrl - Given an initial procedure, state information and symbol table
  104. * builds a list of procedures reachable from the initial procedure
  105. * using a depth first search. */
  106. void Function::FollowCtrl(CALL_GRAPH * pcallGraph, STATE *pstate)
  107. {
  108. PROG &prog(Project::get()->prog);
  109. ICODE _Icode, *pIcode; /* This gets copied to pProc->Icode[] later */
  110. SYM * psym;
  111. uint32_t offset;
  112. eErrorId err;
  113. bool done = false;
  114. SYMTAB &global_symbol_table(Project::get()->symtab);
  115. if (name.contains("chkstk"))
  116. {
  117. // Danger! Dcc will likely fall over in this code.
  118. // So we act as though we have done with this proc
  119. // pProc->flg &= ~TERMINATES; // Not sure about this
  120. // And mark it as a library function, so structure() won't choke on it
  121. flg |= PROC_ISLIB;
  122. return;
  123. }
  124. if (option.VeryVerbose)
  125. {
  126. qDebug() << "Parsing proc" << name << "at" << QString::number(pstate->IP,16).toUpper();
  127. }
  128. while (not done )
  129. {
  130. err = scan(pstate->IP, _Icode);
  131. if(err)
  132. break;
  133. LLInst *ll = _Icode.ll();
  134. pstate->IP += (uint32_t)ll->numBytes;
  135. setBits(BM_CODE, ll->label, (uint32_t)ll->numBytes);
  136. process_operands(_Icode,pstate);
  137. /* Keep track of interesting instruction flags in procedure */
  138. flg |= (ll->getFlag() & (NOT_HLL | FLOAT_OP));
  139. /* Check if this instruction has already been parsed */
  140. iICODE labLoc = Icode.labelSrch(ll->label);
  141. if (Icode.end()!=labLoc)
  142. { /* Synthetic jump */
  143. _Icode.type = LOW_LEVEL_ICODE;
  144. ll->set(iJMP,I | SYNTHETIC | NO_OPS);
  145. ll->replaceSrc(LLOperand::CreateImm2(labLoc->ll()->GetLlLabel()));
  146. ll->label = SynthLab++;
  147. }
  148. /* Copy Icode to Proc */
  149. if ((ll->getOpcode() == iDIV) or (ll->getOpcode() == iIDIV))
  150. pIcode = translate_DIV(ll, _Icode);
  151. else if (_Icode.ll()->getOpcode() == iXCHG)
  152. pIcode = translate_XCHG(ll, _Icode);
  153. else
  154. pIcode = Icode.addIcode(&_Icode);
  155. switch (ll->getOpcode()) {
  156. /*** Conditional jumps ***/
  157. case iLOOP: case iLOOPE: case iLOOPNE:
  158. case iJB: case iJBE: case iJAE: case iJA:
  159. case iJL: case iJLE: case iJGE: case iJG:
  160. case iJE: case iJNE: case iJS: case iJNS:
  161. case iJO: case iJNO: case iJP: case iJNP:
  162. case iJCXZ:
  163. {
  164. STATE StCopy;
  165. uint32_t lastIp = pstate->IP - 2;
  166. int ip = Icode.size()-1; /* Index of this jump */
  167. ICODE &prev(*(++Icode.rbegin())); /* Previous icode */
  168. bool fBranch = false;
  169. pstate->JCond.regi = 0;
  170. /* This sets up range check for indexed JMPs hopefully
  171. * Handles JA/JAE for fall through and JB/JBE on branch
  172. */
  173. if (ip > 0 and prev.ll()->getOpcode() == iCMP and (prev.ll()->testFlags(I)))
  174. {
  175. pstate->JCond.immed = (int16_t)prev.ll()->src().getImm2();
  176. if (ll->match(iJA) or ll->match(iJBE) )
  177. pstate->JCond.immed++;
  178. if (ll->getOpcode() == iJAE or ll->getOpcode() == iJA)
  179. pstate->JCond.regi = prev.ll()->m_dst.regi;
  180. fBranch = (bool) (ll->getOpcode() == iJB or ll->getOpcode() == iJBE);
  181. }
  182. StCopy = *pstate;
  183. //printf("From %X condJump to %X\n", lastIp, pstate->IP);
  184. /* Straight line code */
  185. this->FollowCtrl (pcallGraph, &StCopy); // recurrent ?
  186. if (fBranch) /* Do branching code */
  187. {
  188. pstate->JCond.regi = prev.ll()->m_dst.regi;
  189. }
  190. /* Next icode. Note: not the same as GetLastIcode() because of the call
  191. to FollowCtrl() */
  192. pIcode = Icode.GetIcode(ip);
  193. } /* Fall through to do the jump path */
  194. /*** Jumps ***/
  195. case iJMP:
  196. case iJMPF: /* Returns true if we've run into a loop */
  197. done = process_JMP (*pIcode, pstate, pcallGraph);
  198. break;
  199. /*** Calls ***/
  200. case iCALL:
  201. case iCALLF:
  202. done = process_CALL (*pIcode, pcallGraph, pstate);
  203. pstate->kill(rBX);
  204. pstate->kill(rCX);
  205. break;
  206. /*** Returns ***/
  207. case iRET:
  208. case iRETF:
  209. this->flg |= (ll->getOpcode() == iRET)? PROC_NEAR:PROC_FAR;
  210. /* Fall through */
  211. case iIRET:
  212. this->flg &= ~TERMINATES;
  213. done = true;
  214. break;
  215. case iINT:
  216. if (ll->src().getImm2() == 0x21 and pstate->f[rAH])
  217. {
  218. int funcNum = pstate->r[rAH];
  219. int operand;
  220. int size;
  221. /* Save function number */
  222. Icode.back().ll()->m_dst.off = (int16_t)funcNum;
  223. //Icode.GetIcode(Icode.GetNumIcodes() - 1)->
  224. /* Program termination: int21h, fn 00h, 31h, 4Ch */
  225. done = (bool)(funcNum == 0x00 or funcNum == 0x31 or
  226. funcNum == 0x4C);
  227. /* String functions: int21h, fn 09h */
  228. if (pstate->f[rDX]) /* offset goes into DX */
  229. if (funcNum == 0x09)
  230. {
  231. operand = ((uint32_t)(uint16_t)pstate->r[rDS]<<4) +
  232. (uint32_t)(uint16_t)pstate->r[rDX];
  233. size = prog.fCOM ?
  234. strSize (&prog.image()[operand], '$') :
  235. strSize (&prog.image()[operand], '$'); // + 0x100
  236. global_symbol_table.updateSymType (operand, TypeContainer(TYPE_STR, size));
  237. }
  238. }
  239. else if ((ll->src().getImm2() == 0x2F) and (pstate->f[rAH]))
  240. {
  241. Icode.back().ll()->m_dst.off = pstate->r[rAH];
  242. }
  243. else /* Program termination: int20h, int27h */
  244. done = (ll->src().getImm2() == 0x20 or ll->src().getImm2() == 0x27);
  245. if (done)
  246. pIcode->ll()->setFlags(TERMINATES);
  247. break;
  248. case iMOV:
  249. process_MOV(*pIcode->ll(), pstate);
  250. break;
  251. /* case iXCHG:
  252. process_MOV (pIcode, pstate);
  253. break; **** HERE ***/
  254. case iSHL:
  255. if (pstate->JCond.regi == ll->m_dst.regi)
  256. {
  257. if ((ll->testFlags(I)) and ll->src().getImm2() == 1)
  258. pstate->JCond.immed *= 2;
  259. else
  260. pstate->JCond.regi = 0;
  261. }
  262. break;
  263. case iLEA:
  264. if (ll->src().getReg2()== rUNDEF) /* direct mem offset */
  265. pstate->setState( ll->m_dst.getReg2(), ll->src().off);
  266. break;
  267. case iLDS: case iLES:
  268. if ((psym = lookupAddr(&ll->src(), pstate, 4, eDuVal::USE))
  269. /* and (Icode.ll()->flg & SEG_IMMED) */ )
  270. {
  271. offset = LH(&prog.image()[psym->label]);
  272. pstate->setState( (ll->getOpcode() == iLDS)? rDS: rES,
  273. LH(&prog.image()[psym->label + 2]));
  274. pstate->setState( ll->m_dst.regi, (int16_t)offset);
  275. psym->type = TYPE_PTR;
  276. }
  277. break;
  278. }
  279. }
  280. if (err) {
  281. this->flg &= ~TERMINATES;
  282. if (err == INVALID_386OP or err == INVALID_OPCODE)
  283. {
  284. fatalError(err, prog.image()[_Icode.ll()->label], _Icode.ll()->label);
  285. this->flg |= PROC_BADINST;
  286. }
  287. else if (err == IP_OUT_OF_RANGE)
  288. fatalError (err, _Icode.ll()->label);
  289. else
  290. reportError(err, _Icode.ll()->label);
  291. }
  292. }
  293. /* Firstly look for a leading range check of the form:-
  294. * CMP {BX | SI | DI}, immed
  295. * JA | JAE | JB | JBE
  296. * This is stored in the current state as if we had just
  297. * followed a JBE branch (i.e. [reg] lies between 0 - immed).
  298. */
  299. void Function::extractJumpTableRange(ICODE& pIcode, STATE *pstate, JumpTable &table)
  300. {
  301. static uint8_t i2r[4] = {rSI, rDI, rBP, rBX};
  302. if (pstate->JCond.regi == i2r[pIcode.ll()->src().getReg2()-INDEX_SI])
  303. table.finish = table.start + pstate->JCond.immed;
  304. else
  305. table.finish = table.start + 2;
  306. }
  307. /* process_JMP - Handles JMPs, returns true if we should end recursion */
  308. bool Function::followAllTableEntries(JumpTable &table, uint32_t cs, ICODE& pIcode, CALL_GRAPH* pcallGraph, STATE *pstate)
  309. {
  310. PROG &prog(Project::get()->prog);
  311. STATE StCopy;
  312. setBits(BM_DATA, table.start, table.size()*table.entrySize());
  313. pIcode.ll()->setFlags(SWITCH);
  314. pIcode.ll()->caseTbl2.resize( table.size() );
  315. assert(pIcode.ll()->caseTbl2.size()<512);
  316. uint32_t k=0;
  317. for (size_t i = table.start; i < table.finish; i += 2)
  318. {
  319. StCopy = *pstate;
  320. StCopy.IP = cs + LH(&prog.image()[i]);
  321. iICODE last_current_insn = (++Icode.rbegin()).base();
  322. FollowCtrl (pcallGraph, &StCopy);
  323. ++last_current_insn; // incremented here because FollowCtrl might have adde more instructions after the Jmp
  324. last_current_insn->ll()->caseEntry = k++;
  325. last_current_insn->ll()->setFlags(CASE);
  326. pIcode.ll()->caseTbl2.push_back( last_current_insn->ll()->GetLlLabel() );
  327. }
  328. return true;
  329. }
  330. bool Function::decodeIndirectJMP(ICODE & pIcode, STATE *pstate, CALL_GRAPH * pcallGraph)
  331. {
  332. PROG &prog(Project::get()->prog);
  333. // mov cx,NUM_CASES
  334. // mov bx,JUMP_TABLE
  335. // LAB1:
  336. // mov ax, [bx]
  337. // cmp ax,VAL
  338. // jz LAB2
  339. // add bx,2
  340. // loop LAB1
  341. // jmp DEFAULT_CASE
  342. // LAB2
  343. // jmp word ptr [bx+2*NUM_CASES]
  344. static const llIcode match_seq[] = {iMOV,iMOV,iMOV,iCMP,iJE,iADD,iLOOP,iJMP,iJMP};
  345. if(Icode.size()<8)
  346. return false;
  347. if(&Icode.back()!=&pIcode) // not the last insn in the list skip it
  348. return false;
  349. if(pIcode.ll()->src().regi != INDEX_BX) {
  350. return false;
  351. }
  352. // find address-wise predecessors of the icode
  353. std::deque<ICODE *> matched;
  354. QMap<uint32_t,ICODE *> addrmap;
  355. for(ICODE & ic : Icode) {
  356. addrmap[ic.ll()->GetLlLabel()] = &ic;
  357. }
  358. auto iter = addrmap.find(pIcode.ll()->GetLlLabel());
  359. while(matched.size()<9) {
  360. matched.push_front(*iter);
  361. --iter;
  362. if(iter==addrmap.end())
  363. return false;
  364. }
  365. // pattern starts at the last jmp
  366. ICODE *load_num_cases = matched[0];
  367. ICODE *load_jump_table_addr = matched[1];
  368. ICODE *read_case_entry_insn = matched[2];
  369. ICODE *cmp_case_val_insn = matched[3];
  370. ICODE *exit_loop_insn = matched[4];
  371. ICODE *add_bx_insn = matched[5];
  372. ICODE *loop_insn = matched[6];
  373. ICODE *default_jmp = matched[7];
  374. ICODE *last_jmp = matched[8];
  375. for(int i=0; i<8; ++i) {
  376. if(matched[i+1]->ll()->GetLlLabel()!=matched[i]->ll()->GetLlLabel()+matched[i]->ll()->numBytes) {
  377. qDebug() << "Matching jump pattern impossible - undecoded instructions in pattern area ";
  378. return false;
  379. }
  380. }
  381. for(int i=0; i<9; ++i) {
  382. if(matched[i]->ll()->getOpcode()!=match_seq[i]) {
  383. return false;
  384. }
  385. }
  386. // verify that bx+offset == 2* case count
  387. uint32_t num_cases = load_num_cases->ll()->src().getImm2();
  388. if(last_jmp->ll()->src().off != 2*num_cases)
  389. return false;
  390. const LLOperand &op = last_jmp->ll()->src();
  391. if(op.regi != INDEX_BX)
  392. return false;
  393. if(not load_jump_table_addr->ll()->src().isImmediate())
  394. return false;
  395. uint32_t cs = (uint32_t)(uint16_t)pstate->r[rCS] << 4;
  396. uint32_t table_addr = cs + load_jump_table_addr->ll()->src().getImm2();
  397. uint32_t default_label = cs + default_jmp->ll()->src().getImm2();
  398. setBits(BM_DATA, table_addr, num_cases*2 + num_cases*2); // num_cases of short values + num cases short ptrs
  399. pIcode.ll()->setFlags(SWITCH);
  400. for(int i=0; i<num_cases; ++i) {
  401. STATE StCopy = *pstate;
  402. uint32_t jump_target_location = table_addr + num_cases*2 + i*2;
  403. StCopy.IP = cs + *(uint16_t *)(prog.image()+jump_target_location);
  404. iICODE last_current_insn = (++Icode.rbegin()).base();
  405. FollowCtrl (pcallGraph, &StCopy);
  406. ++last_current_insn;
  407. last_current_insn->ll()->caseEntry = i;
  408. last_current_insn->ll()->setFlags(CASE);
  409. pIcode.ll()->caseTbl2.push_back( last_current_insn->ll()->GetLlLabel() );
  410. }
  411. return true;
  412. }
  413. bool Function::decodeIndirectJMP2(ICODE & pIcode, STATE *pstate, CALL_GRAPH * pcallGraph)
  414. {
  415. PROG &prog(Project::get()->prog);
  416. // mov cx,NUM_CASES
  417. // mov bx,JUMP_TABLE
  418. // LAB1:
  419. // mov ax, [bx]
  420. // cmp ax, LOW_WORD_OF_VAL
  421. // jnz LAB2
  422. // mov ax, [bx + 2 * NUM_CASES]
  423. // cmp ax, HIGH_WORD_OF_VAL
  424. // jz LAB3
  425. // LAB2
  426. // add bx,2
  427. // loop LAB1
  428. // jmp DEFAULT_CASE
  429. // LAB3
  430. // jmp word ptr [bx+2*NUM_CASES]
  431. static const llIcode match_seq[] = {iMOV,iMOV,iMOV,iCMP,iJNE,iMOV,iCMP,iJE,iADD,iLOOP,iJMP,iJMP};
  432. if(Icode.size()<12)
  433. return false;
  434. if(&Icode.back() != &pIcode) // not the last insn in the list skip it
  435. return false;
  436. if(pIcode.ll()->src().regi != INDEX_BX) {
  437. return false;
  438. }
  439. // find address-wise predecessors of the icode
  440. std::deque<ICODE *> matched;
  441. QMap<uint32_t,ICODE *> addrmap;
  442. for(ICODE & ic : Icode) {
  443. addrmap[ic.ll()->GetLlLabel()] = &ic;
  444. }
  445. auto iter = addrmap.find(pIcode.ll()->GetLlLabel());
  446. while(matched.size()<12) {
  447. matched.push_front(*iter);
  448. --iter;
  449. if(iter==addrmap.end())
  450. return false;
  451. }
  452. // pattern starts at the last jmp
  453. ICODE *load_num_cases = matched[0];
  454. ICODE *load_jump_table_addr = matched[1];
  455. ICODE *default_jmp = matched[10];
  456. ICODE *last_jmp = matched[11];
  457. for(int i=0; i<11; ++i) {
  458. if(matched[i+1]->ll()->GetLlLabel()!=matched[i]->ll()->GetLlLabel()+matched[i]->ll()->numBytes) {
  459. qDebug() << "Matching jump pattern impossible - undecoded instructions in pattern area ";
  460. return false;
  461. }
  462. }
  463. for(int i=0; i<12; ++i) {
  464. if(matched[i]->ll()->getOpcode()!=match_seq[i]) {
  465. return false;
  466. }
  467. }
  468. // verify that bx+offset == 2* case count
  469. uint32_t num_cases = load_num_cases->ll()->src().getImm2();
  470. if(last_jmp->ll()->src().off != 4*num_cases)
  471. return false;
  472. const LLOperand &op = last_jmp->ll()->src();
  473. if(op.regi != INDEX_BX)
  474. return false;
  475. if(not load_jump_table_addr->ll()->src().isImmediate())
  476. return false;
  477. uint32_t cs = (uint32_t)(uint16_t)pstate->r[rCS] << 4;
  478. uint32_t table_addr = cs + load_jump_table_addr->ll()->src().getImm2();
  479. int default_label = cs + default_jmp->ll()->src().getImm2();
  480. setBits(BM_DATA, table_addr, num_cases*4 + num_cases*2); // num_cases of long values + num cases short ptrs
  481. pIcode.ll()->setFlags(SWITCH);
  482. for(int i=0; i<num_cases; ++i) {
  483. STATE StCopy = *pstate;
  484. uint32_t jump_target_location = table_addr + num_cases*4 + i*2;
  485. StCopy.IP = cs + *(uint16_t *)(prog.image()+jump_target_location);
  486. iICODE last_current_insn = (++Icode.rbegin()).base();
  487. FollowCtrl (pcallGraph, &StCopy);
  488. ++last_current_insn;
  489. last_current_insn->ll()->caseEntry = i;
  490. last_current_insn->ll()->setFlags(CASE);
  491. pIcode.ll()->caseTbl2.push_back( last_current_insn->ll()->GetLlLabel() );
  492. }
  493. return true;
  494. }
  495. bool Function::process_JMP (ICODE & pIcode, STATE *pstate, CALL_GRAPH * pcallGraph)
  496. {
  497. PROG &prog(Project::get()->prog);
  498. static uint8_t i2r[4] = {rSI, rDI, rBP, rBX};
  499. ICODE _Icode;
  500. uint32_t lastIp = pstate->IP - 1;
  501. uint32_t cs, offTable, endTable;
  502. uint32_t i, k, seg, target;
  503. if (pIcode.ll()->testFlags(I))
  504. {
  505. if (pIcode.ll()->getOpcode() == iJMPF)
  506. pstate->setState( rCS, LH(prog.image() + pIcode.ll()->label + 3));
  507. pstate->IP = pIcode.ll()->src().getImm2();
  508. //printf("From seg:%04X JMP(F) to %X\n", lastIp, pstate->IP);
  509. if (pstate->IP == 0xFFFF0)
  510. {
  511. /* Nasty (wrong) trick use to reset, consider it as terminating */
  512. pIcode.ll()->setFlags(TERMINATES);
  513. pstate->setState( rCS, 0);
  514. pstate->IP = 0;
  515. }
  516. int64_t i = pIcode.ll()->src().getImm2();
  517. if (i < 0)
  518. {
  519. exit(1);
  520. }
  521. /* Return true if jump target is already parsed */
  522. return Icode.alreadyDecoded(i);
  523. }
  524. /* We've got an indirect JMP - look for switch() stmt. idiom of the form
  525. * JMP uint16_t ptr word_offset[rBX | rSI | rDI] */
  526. seg = (pIcode.ll()->src().seg)? pIcode.ll()->src().seg: rDS;
  527. /* Ensure we have a uint16_t offset & valid seg */
  528. if (pIcode.ll()->match(iJMP) and (pIcode.ll()->testFlags(WORD_OFF)) and
  529. pstate->f[seg] and
  530. (pIcode.ll()->src().regi == INDEX_SI or
  531. pIcode.ll()->src().regi == INDEX_DI or /* Idx reg. BX, SI, DI */
  532. pIcode.ll()->src().regi == INDEX_BX))
  533. {
  534. offTable = ((uint32_t)(uint16_t)pstate->r[seg] << 4) + pIcode.ll()->src().off;
  535. /* Firstly look for a leading range check of the form:-
  536. * CMP {BX | SI | DI}, immed
  537. * JA | JAE | JB | JBE
  538. * This is stored in the current state as if we had just
  539. * followed a JBE branch (i.e. [reg] lies between 0 - immed).
  540. */
  541. if (pstate->JCond.regi == i2r[pIcode.ll()->src().regi-(INDEX_BX_SI+4)])
  542. endTable = offTable + pstate->JCond.immed;
  543. else
  544. endTable = (uint32_t)prog.cbImage;
  545. /* Search for first uint8_t flagged after start of table */
  546. for (i = offTable; i <= endTable; i++)
  547. if (BITMAP(i, BM_CODE | BM_DATA))
  548. break;
  549. endTable = i & ~1; /* Max. possible table size */
  550. /* Now do some heuristic pruning. Look for ptrs. into the table
  551. * and for addresses that don't appear to point to valid code.
  552. */
  553. cs = (uint32_t)(uint16_t)pstate->r[rCS] << 4;
  554. for (i = offTable; i < endTable; i += 2)
  555. {
  556. target = cs + LH(&prog.image()[i]);
  557. if (target < endTable and target >= offTable)
  558. endTable = target;
  559. else if (target >= (uint32_t)prog.cbImage)
  560. endTable = i;
  561. }
  562. for (i = offTable; i < endTable; i += 2)
  563. {
  564. target = cs + LH(&prog.image()[i]);
  565. /* Be wary of 00 00 as code - it's probably data */
  566. if (not (prog.image()[target] or prog.image()[target+1]) or
  567. scan(target, _Icode))
  568. endTable = i;
  569. }
  570. /* Now for each entry in the table take a copy of the current
  571. * state and recursively call FollowCtrl(). */
  572. if (offTable < endTable)
  573. {
  574. assert(((endTable - offTable) / 2)<512);
  575. STATE StCopy;
  576. //int ip;
  577. //uint32_t *psw;
  578. setBits(BM_DATA, offTable, endTable - offTable);
  579. pIcode.ll()->setFlags(SWITCH);
  580. //pIcode.ll()->caseTbl2.numEntries = (endTable - offTable) / 2;
  581. for (i = offTable, k = 0; i < endTable; i += 2)
  582. {
  583. StCopy = *pstate;
  584. StCopy.IP = cs + LH(&prog.image()[i]);
  585. iICODE last_current_insn = (++Icode.rbegin()).base();
  586. //ip = Icode.size();
  587. FollowCtrl (pcallGraph, &StCopy);
  588. ++last_current_insn;
  589. last_current_insn->ll()->caseEntry = k++;
  590. last_current_insn->ll()->setFlags(CASE);
  591. pIcode.ll()->caseTbl2.push_back( last_current_insn->ll()->GetLlLabel() );
  592. }
  593. return true;
  594. }
  595. }
  596. if(decodeIndirectJMP(pIcode,pstate,pcallGraph)) {
  597. return true;
  598. }
  599. if(decodeIndirectJMP2(pIcode,pstate,pcallGraph)) {
  600. return true;
  601. }
  602. /* Can't do anything with this jump */
  603. flg |= PROC_IJMP;
  604. flg &= ~TERMINATES;
  605. interactDis(this, this->Icode.size()-1);
  606. return true;
  607. }
  608. /* Process procedure call.
  609. * Note: We assume that CALL's will return unless there is good evidence to
  610. * the contrary - thus we return false unless all paths in the called
  611. * procedure end in DOS exits. This is reasonable since C procedures
  612. * will always include the epilogue after the call anyway and it's to
  613. * be assumed that if an assembler program contains a CALL that the
  614. * programmer expected it to come back - otherwise surely a JMP would
  615. * have been used. */
  616. bool Function::process_CALL(ICODE & pIcode, CALL_GRAPH * pcallGraph, STATE *pstate)
  617. {
  618. PROG &prog(Project::get()->prog);
  619. ICODE &last_insn(Icode.back());
  620. STATE localState; /* Local copy of the machine state */
  621. uint32_t lastIp = pstate->IP - 2;
  622. uint32_t off;
  623. /* For Indirect Calls, find the function address */
  624. bool indirect = false;
  625. //pIcode.ll()->immed.proc.proc=fakeproc;
  626. if ( not pIcode.ll()->testFlags(I) )
  627. {
  628. /* Not immediate, i.e. indirect call */
  629. if (pIcode.ll()->m_dst.regi and (not option.Calls))
  630. {
  631. /* We have not set the brave option to attempt to follow
  632. the execution path through register indirect calls.
  633. So we just exit this function, and ignore the call.
  634. We probably should not have parsed this deep, anyway. */
  635. return false;
  636. }
  637. /* Offset into program image is seg:off of read input */
  638. /* Note: this assumes that the pointer itself is at
  639. es:0 where es:0 is the start of the image. This is
  640. usually wrong! Consider also CALL [BP+0E] in which the
  641. segment for the pointer is in SS! - Mike */
  642. if(pIcode.ll()->m_dst.isReg())
  643. {
  644. if( not pstate->isKnown(pIcode.ll()->m_dst.regi)
  645. or
  646. not pstate->isKnown(pIcode.ll()->m_dst.seg)
  647. )
  648. {
  649. fprintf(stderr,"Indirect call with unknown register values\n");
  650. return false;
  651. }
  652. off = pstate->r[pIcode.ll()->m_dst.seg];
  653. off <<=4;
  654. off += pstate->r[pIcode.ll()->m_dst.regi];
  655. }
  656. else
  657. {
  658. off = (uint32_t)(uint16_t)pIcode.ll()->m_dst.off +
  659. ((uint32_t)(uint16_t)pIcode.ll()->m_dst.segValue << 4);
  660. }
  661. /* Address of function is given by 4 (CALLF) or 2 (CALL) bytes at
  662. * previous offset into the program image */
  663. uint32_t tgtAddr=0;
  664. if (pIcode.ll()->getOpcode() == iCALLF)
  665. tgtAddr= LH(&prog.image()[off]) + ((uint32_t)(LH(&prog.image()[off+2])) << 4);
  666. else
  667. tgtAddr= LH(&prog.image()[off]) + ((uint32_t)(uint16_t)state.r[rCS] << 4);
  668. pIcode.ll()->replaceSrc(LLOperand::CreateImm2( tgtAddr ) );
  669. pIcode.ll()->setFlags(I);
  670. indirect = true;
  671. }
  672. /* Process CALL. Function address is located in pIcode.ll()->immed.op */
  673. if (pIcode.ll()->testFlags(I))
  674. {
  675. /* Search procedure list for one with appropriate entry point */
  676. ilFunction iter = Project::get()->findByEntry(pIcode.ll()->src().getImm2());
  677. /* Create a new procedure node and save copy of the state */
  678. if ( not Project::get()->valid(iter) )
  679. {
  680. iter = Project::get()->createFunction(0,"");
  681. Function &x(*iter);
  682. x.procEntry = pIcode.ll()->src().getImm2();
  683. LibCheck(x);
  684. if (x.flg & PROC_ISLIB)
  685. {
  686. /* A library function. No need to do any more to it */
  687. pcallGraph->insertCallGraph (this, iter);
  688. //iter = (++pProcList.rbegin()).base();
  689. last_insn.ll()->src().proc.proc = &x;
  690. return false;
  691. }
  692. if (indirect)
  693. x.flg |= PROC_ICALL;
  694. if (x.name.isEmpty()) /* Don't overwrite existing name */
  695. {
  696. x.name = QString("proc_%1_%2").arg(x.procEntry ,6,16,QChar('0')).arg(++prog.cProcs);
  697. }
  698. x.depth = x.depth + 1;
  699. x.flg |= TERMINATES;
  700. /* Save machine state in localState, load up IP and CS.*/
  701. localState = *pstate;
  702. pstate->IP = pIcode.ll()->src().getImm2();
  703. if (pIcode.ll()->getOpcode() == iCALLF)
  704. pstate->setState( rCS, LH(prog.image() + pIcode.ll()->label + 3));
  705. x.state = *pstate;
  706. /* Insert new procedure in call graph */
  707. - pcallGraph->insertCallGraph (this, iter);
  708. //printf("From %X CALL to %X\n", lastIp, pstate->IP);
  709. /* Process new procedure */
  710. x.FollowCtrl (pcallGraph, pstate);
  711. /* Restore segment registers & IP from localState */
  712. pstate->IP = localState.IP;
  713. pstate->setState( rCS, localState.r[rCS]);
  714. pstate->setState( rDS, localState.r[rDS]);
  715. pstate->setState( rES, localState.r[rES]);
  716. pstate->setState( rSS, localState.r[rSS]);
  717. }
  718. else
  719. Project::get()->callGraph->insertCallGraph (this, iter);
  720. last_insn.ll()->src().proc.proc = &(*iter); // ^ target proc
  721. /* return ((p->flg & TERMINATES) != 0); */
  722. }
  723. return false; // Cristina, please check!!
  724. }
  725. /* process_MOV - Handles state changes due to simple assignments */
  726. static void process_MOV(LLInst & ll, STATE * pstate)
  727. {
  728. PROG &prog(Project::get()->prog);
  729. SYM * psym, *psym2; /* Pointer to symbol in global symbol table */
  730. uint8_t dstReg = ll.m_dst.regi;
  731. uint8_t srcReg = ll.src().regi;
  732. if (dstReg > 0 and dstReg < INDEX_BX_SI)
  733. {
  734. if (ll.testFlags(I))
  735. pstate->setState( dstReg, (int16_t)ll.src().getImm2());
  736. else if (srcReg == 0) /* direct memory offset */
  737. {
  738. psym = lookupAddr(&ll.src(), pstate, 2, eDuVal::USE);
  739. if (psym and ((psym->flg & SEG_IMMED) or psym->duVal.val))
  740. pstate->setState( dstReg, LH(&prog.image()[psym->label]));
  741. }
  742. else if (srcReg < INDEX_BX_SI and pstate->f[srcReg]) /* reg */
  743. {
  744. pstate->setState( dstReg, pstate->r[srcReg]);
  745. /* Follow moves of the possible index register */
  746. if (pstate->JCond.regi == srcReg)
  747. pstate->JCond.regi = dstReg;
  748. }
  749. }
  750. else if (dstReg == 0) { /* direct memory offset */
  751. int size=2;
  752. if((ll.src().regi>=rAL)and(ll.src().regi<=rBH))
  753. size=1;
  754. psym = lookupAddr (&ll.m_dst, pstate, size, eDEF);
  755. if (psym and not (psym->duVal.val)) /* no initial value yet */
  756. {
  757. if (ll.testFlags(I)) /* immediate */
  758. {
  759. //prog.image()[psym->label] = (uint8_t)ll.src().getImm2();
  760. pstate->setMemoryByte(psym->label,(uint8_t)ll.src().getImm2());
  761. if(psym->size>1)
  762. {
  763. pstate->setMemoryByte(psym->label+1,uint8_t(ll.src().getImm2()>>8));
  764. //prog.image()[psym->label+1] = (uint8_t)(ll.src().getImm2()>>8);
  765. }
  766. psym->duVal.val = 1;
  767. }
  768. else if (srcReg == 0) /* direct mem offset */
  769. {
  770. psym2 = lookupAddr (&ll.src(), pstate, 2, eDuVal::USE);
  771. if (psym2 and ((psym->flg & SEG_IMMED) or (psym->duVal.val)))
  772. {
  773. //prog.image()[psym->label] = (uint8_t)prog.image()[psym2->label];
  774. pstate->setMemoryByte(psym->label,(uint8_t)prog.image()[psym2->label]);
  775. if(psym->size>1)
  776. {
  777. pstate->setMemoryByte(psym->label+1,(uint8_t)prog.image()[psym2->label+1]);
  778. //prog.image()[psym->label+1] = prog.image()[psym2->label+1];//(uint8_t)(prog.image()[psym2->label+1] >> 8);
  779. }
  780. psym->duVal.setFlags(eDuVal::DEF);
  781. psym2->duVal.setFlags(eDuVal::USE);
  782. }
  783. }
  784. else if (srcReg < INDEX_BX_SI and pstate->f[srcReg]) /* reg */
  785. {
  786. //prog.image()[psym->label] = (uint8_t)pstate->r[srcReg];
  787. pstate->setMemoryByte(psym->label,(uint8_t)pstate->r[srcReg]);
  788. if(psym->size>1)
  789. {
  790. pstate->setMemoryByte(psym->label,(uint8_t)pstate->r[srcReg]>>8);
  791. //prog.image()[psym->label+1] = (uint8_t)(pstate->r[srcReg] >> 8);
  792. }
  793. psym->duVal.setFlags(eDuVal::DEF);
  794. }
  795. }
  796. }
  797. }
  798. /* Updates the offset entry to the stack frame table (arguments),
  799. * and returns a pointer to such entry. */
  800. void STKFRAME::updateFrameOff ( int16_t off, int _size, uint16_t duFlag)
  801. {
  802. /* Check for symbol in stack frame table */
  803. auto iter=findByLabel(off);
  804. if(iter!=end())
  805. {
  806. if (iter->size < _size)
  807. {
  808. iter->size = _size;
  809. }
  810. }
  811. else
  812. {
  813. char nm[16];
  814. STKSYM new_sym;
  815. sprintf (nm, "arg%" PRIu64, uint64_t(size()));
  816. new_sym.name = nm;
  817. new_sym.label= off;
  818. new_sym.size = _size;
  819. new_sym.type = TypeContainer::defaultTypeForSize(_size);
  820. if (duFlag == eDuVal::USE) /* must already have init value */
  821. {
  822. new_sym.duVal.use=1;
  823. //new_sym.duVal.val=1;
  824. }
  825. else
  826. {
  827. new_sym.duVal.setFlags(duFlag);
  828. }
  829. push_back(new_sym);
  830. this->numArgs++;
  831. }
  832. /* Save maximum argument offset */
  833. if ((uint32_t)this->maxOff < (off + (uint32_t)_size))
  834. this->maxOff = off + (int16_t)_size;
  835. }
  836. /* lookupAddr - Looks up a data reference in the symbol table and stores it
  837. * if necessary.
  838. * Returns a pointer to the symbol in the
  839. * symbol table, or Null if it's not a direct memory offset. */
  840. static SYM * lookupAddr (LLOperand *pm, STATE *pstate, int size, uint16_t duFlag)
  841. {
  842. PROG &prog(Project::get()->prog);
  843. int i;
  844. SYM * psym=nullptr;
  845. uint32_t operand;
  846. bool created_new=false;
  847. if (pm->regi != rUNDEF)
  848. return nullptr; // register or indexed
  849. /* Global var */
  850. if (pm->segValue) /* there is a value in the seg field */
  851. {
  852. operand = opAdr (pm->segValue, pm->off);
  853. psym = Project::get()->symtab.updateGlobSym (operand, size, duFlag,created_new);
  854. }
  855. else if (pstate->f[pm->seg]) /* new value */
  856. {
  857. pm->segValue = pstate->r[pm->seg];
  858. operand = opAdr(pm->segValue, pm->off);
  859. psym = Project::get()->symtab.updateGlobSym (operand, size, duFlag,created_new);
  860. /* Flag new memory locations that are segment values */
  861. if (created_new)
  862. {
  863. if (size == 4)
  864. operand += 2; /* High uint16_t */
  865. for (i = 0; i < prog.cReloc; i++)
  866. if (prog.relocTable[i] == operand) {
  867. psym->flg = SEG_IMMED;
  868. break;
  869. }
  870. }
  871. }
  872. /* Check for out of bounds */
  873. if (psym and (psym->label < (uint32_t)prog.cbImage))
  874. return psym;
  875. return nullptr;
  876. }
  877. /* setState - Assigns a value to a reg. */
  878. void STATE::setState(uint16_t reg, int16_t value)
  879. {
  880. value &= 0xFFFF;
  881. r[reg] = value;
  882. f[reg] = true;
  883. switch (reg) {
  884. case rAX: case rCX: case rDX: case rBX:
  885. r[reg + rAL - rAX] = value & 0xFF;
  886. f[reg + rAL - rAX] = true;
  887. r[reg + rAH - rAX] = (value >> 8) & 0xFF;
  888. f[reg + rAH - rAX] = true;
  889. break;
  890. case rAL: case rCL: case rDL: case rBL:
  891. if (f[reg - rAL + rAH]) {
  892. r[reg - rAL + rAX] =(r[reg - rAL + rAH] << 8) + (value & 0xFF);
  893. f[reg - rAL + rAX] = true;
  894. }
  895. break;
  896. case rAH: case rCH: case rDH: case rBH:
  897. if (f[reg - rAH + rAL])
  898. {
  899. r[reg - rAH + rAX] = r[reg - rAH + rAL] + ((value & 0xFF) << 8);
  900. f[reg - rAH + rAX] = true;
  901. }
  902. break;
  903. }
  904. }
  905. /* labelSrchRepl - Searches Icode for instruction with label = target, and
  906. replaces *pIndex with an icode index */
  907. /* setBits - Sets memory bitmap bits for BM_CODE or BM_DATA (additively) */
  908. static void setBits(int16_t type, uint32_t start, uint32_t len)
  909. {
  910. PROG &prog(Project::get()->prog);
  911. uint32_t i;
  912. if (start < (uint32_t)prog.cbImage)
  913. {
  914. if (start + len > (uint32_t)prog.cbImage)
  915. len = (uint32_t)(prog.cbImage - start);
  916. for (i = start + len - 1; i >= start; i--)
  917. {
  918. prog.map[i >> 2] |= type << ((i & 3) << 1);
  919. if (i == 0) break; // Fixes inf loop!
  920. }
  921. }
  922. }
  923. /* Checks which registers were used and updates the du.u flag.
  924. * Places local variables on the local symbol table.
  925. * Arguments: d : SRC or DST icode operand
  926. * pIcode: ptr to icode instruction
  927. * pProc : ptr to current procedure structure
  928. * pstate: ptr to current procedure state
  929. * size : size of the operand
  930. * ix : current index into icode array */
  931. static void use (opLoc d, ICODE & pIcode, Function * pProc, STATE * pstate, int size)
  932. {
  933. const LLOperand * pm = pIcode.ll()->get(d) ;
  934. SYM * psym;
  935. if ( Machine_X86::isMemOff(pm->regi) )
  936. {
  937. if (pm->regi == INDEX_BP) /* indexed on bp */
  938. {
  939. if (pm->off >= 2)
  940. pProc->args.updateFrameOff ( pm->off, size, eDuVal::USE);
  941. else if (pm->off < 0)
  942. pProc->localId.newByteWordStk (TYPE_WORD_SIGN, pm->off, 0);
  943. }
  944. else if (pm->regi == INDEX_BP_SI or pm->regi == INDEX_BP_DI)
  945. pProc->localId.newByteWordStk (TYPE_WORD_SIGN, pm->off,
  946. (uint8_t)((pm->regi == INDEX_BP_SI) ? rSI : rDI));
  947. else if ((pm->regi >= INDEX_SI) and (pm->regi <= INDEX_BX))
  948. {
  949. if ((pm->seg == rDS) and (pm->regi == INDEX_BX)) /* bx */
  950. {
  951. if (pm->off > 0) /* global indexed variable */
  952. pProc->localId.newIntIdx(pm->segValue, pm->off, rBX,TYPE_WORD_SIGN);
  953. }
  954. pIcode.du.use.addReg(pm->regi);
  955. }
  956. else
  957. {
  958. psym = lookupAddr(const_cast<LLOperand *>(pm), pstate, size, eDuVal::USE);
  959. if( nullptr != psym )
  960. {
  961. setBits (BM_DATA, psym->label, (uint32_t)size);
  962. pIcode.ll()->setFlags(SYM_USE);
  963. pIcode.ll()->caseEntry = distance(&Project::get()->symtab[0],psym); //WARNING: was setting case count
  964. }
  965. }
  966. }
  967. /* Use of register */
  968. else if ((d == DST) or ((d == SRC) and (not pIcode.ll()->testFlags(I))))
  969. pIcode.du.use.addReg(pm->regi);
  970. }
  971. /* Checks which registers were defined (ie. got a new value) and updates the
  972. * du.d flag.
  973. * Places local variables in the local symbol table. */
  974. static void def (opLoc d, ICODE & pIcode, Function * pProc, STATE * pstate, int size)
  975. {
  976. LLOperand *pm = pIcode.ll()->get(d);
  977. if (pm->regi==0)
  978. {
  979. SYM * psym;
  980. psym = lookupAddr(pm, pstate, size, eDEF);
  981. if (nullptr!=psym)
  982. {
  983. setBits(BM_DATA, psym->label, (uint32_t)size);
  984. pIcode.ll()->setFlags(SYM_DEF);
  985. pIcode.ll()->caseEntry = distance(&Project::get()->symtab[0],psym); // WARNING: was setting Case count
  986. }
  987. }
  988. else if (pm->regi >= INDEX_BX_SI)
  989. {
  990. if (pm->regi == INDEX_BP) /* indexed on bp */
  991. {
  992. if (pm->off >= 2)
  993. pProc->args.updateFrameOff ( pm->off, size, eDEF);
  994. else if (pm->off < 0)
  995. pProc->localId.newByteWordStk (TYPE_WORD_SIGN, pm->off, 0);
  996. }
  997. else if (pm->regi == INDEX_BP_SI or pm->regi == INDEX_BP_DI)
  998. {
  999. pProc->localId.newByteWordStk(TYPE_WORD_SIGN, pm->off,
  1000. (uint8_t)((pm->regi == INDEX_BP_SI) ? rSI : rDI));
  1001. }
  1002. else if ((pm->regi >= INDEX_SI) and (pm->regi <= INDEX_BX))
  1003. {
  1004. if ((pm->seg == rDS) and (pm->regi == INDEX_BX)) /* bx */
  1005. {
  1006. if (pm->off > 0) /* global var */
  1007. pProc->localId.newIntIdx(pm->segValue, pm->off, rBX,TYPE_WORD_SIGN);
  1008. }
  1009. pIcode.du.use.addReg(pm->regi);
  1010. }
  1011. }
  1012. /* Definition of register */
  1013. else if ((d == DST) or ((d == SRC) and (not pIcode.ll()->testFlags(I))))
  1014. {
  1015. assert(not pIcode.ll()->match(iPUSH));
  1016. pIcode.du1.addDef(pm->regi);
  1017. pIcode.du.def.addReg(pm->regi);
  1018. }
  1019. }
  1020. /* use_def - operand is both use and def'd.
  1021. * Note: the destination will always be a register, stack variable, or global
  1022. * variable. */
  1023. static void use_def(opLoc d, ICODE & pIcode, Function * pProc, STATE * pstate, int cb)
  1024. {
  1025. const LLOperand * pm = pIcode.ll()->get(d);
  1026. use (d, pIcode, pProc, pstate, cb);
  1027. if (pm->regi < INDEX_BX_SI) /* register */
  1028. {
  1029. assert(not pIcode.ll()->match(iPUSH));
  1030. pIcode.du1.addDef(pm->regi);
  1031. pIcode.du.def.addReg(pm->regi);
  1032. }
  1033. }
  1034. /* Set DU vector, local variables and arguments, and DATA bits in the
  1035. * bitmap */
  1036. extern LLOperand convertOperand(const x86_op_t &from);
  1037. void Function::process_operands(ICODE & pIcode, STATE * pstate)
  1038. {
  1039. LLInst &ll_ins(*pIcode.ll());
  1040. int sseg = (ll_ins.src().seg)? ll_ins.src().seg: rDS;
  1041. int cb = pIcode.ll()->testFlags(B) ? 1: 2;
  1042. //x86_op_t *im= pIcode.insn.x86_get_imm();
  1043. bool Imm = (pIcode.ll()->testFlags(I));
  1044. switch (pIcode.ll()->getOpcode()) {
  1045. case iAND: case iOR: case iXOR:
  1046. case iSAR: case iSHL: case iSHR:
  1047. case iRCL: case iRCR: case iROL: case iROR:
  1048. case iADD: case iADC: case iSUB: case iSBB:
  1049. if (not Imm) {
  1050. use(SRC, pIcode, this, pstate, cb);
  1051. }
  1052. case iINC: case iDEC: case iNEG: case iNOT:
  1053. case iAAA: case iAAD: case iAAM: case iAAS:
  1054. case iDAA: case iDAS:
  1055. use_def(DST, pIcode, this, pstate, cb);
  1056. break;
  1057. case iXCHG:
  1058. /* This instruction is replaced by 3 instructions, only need
  1059. * to define the src operand and use the destination operand
  1060. * in the mean time. */
  1061. use(SRC, pIcode, this, pstate, cb);
  1062. def(DST, pIcode, this, pstate, cb);
  1063. break;
  1064. case iTEST: case iCMP:
  1065. if (not Imm)
  1066. use(SRC, pIcode, this, pstate, cb);
  1067. use(DST, pIcode, this, pstate, cb);
  1068. break;
  1069. case iDIV: case iIDIV:
  1070. use(SRC, pIcode, this, pstate, cb);
  1071. if (cb == 1)
  1072. pIcode.du.use.addReg(rTMP);
  1073. break;
  1074. case iMUL: case iIMUL:
  1075. use(SRC, pIcode, this, pstate, cb);
  1076. if (not Imm)
  1077. {
  1078. use (DST, pIcode, this, pstate, cb);
  1079. if (cb == 1)
  1080. {
  1081. pIcode.du.def.addReg(rAX);
  1082. pIcode.du1.addDef(rAX);
  1083. }
  1084. else
  1085. {
  1086. pIcode.du.def.addReg(rAX).addReg(rDX);
  1087. pIcode.du1.addDef(rAX).addDef(rDX);
  1088. }
  1089. }
  1090. else
  1091. def (DST, pIcode, this, pstate, cb);
  1092. break;
  1093. case iSIGNEX:
  1094. cb = pIcode.ll()->testFlags(SRC_B) ? 1 : 2;
  1095. if (cb == 1) /* uint8_t */
  1096. {
  1097. pIcode.du.def.addReg(rAX);
  1098. pIcode.du1.addDef(rAX);
  1099. pIcode.du.use.addReg(rAL);
  1100. }
  1101. else /* uint16_t */
  1102. {
  1103. pIcode.du.def.addReg(rDX).addReg(rAX);
  1104. pIcode.du1.addDef(rAX).addDef(rDX);
  1105. pIcode.du.use.addReg(rAX);
  1106. }
  1107. break;
  1108. case iCALLF: /* Ignore def's on CS for now */
  1109. cb = 4;
  1110. case iCALL: case iPUSH: case iPOP:
  1111. if (not Imm) {
  1112. if (pIcode.ll()->getOpcode() == iPOP)
  1113. def(DST, pIcode, this, pstate, cb);
  1114. else
  1115. use(DST, pIcode, this, pstate, cb);
  1116. }
  1117. break;
  1118. case iESC: /* operands may be larger */
  1119. use(DST, pIcode, this, pstate, cb);
  1120. break;
  1121. case iLDS: case iLES:
  1122. {
  1123. eReg r=((pIcode.ll()->getOpcode() == iLDS) ? rDS : rES);
  1124. pIcode.du.def.addReg(r);
  1125. pIcode.du1.addDef(r);
  1126. cb = 4;
  1127. // fallthrough
  1128. }
  1129. case iMOV:
  1130. use(SRC, pIcode, this, pstate, cb);
  1131. def(DST, pIcode, this, pstate, cb);
  1132. break;
  1133. case iLEA:
  1134. use(SRC, pIcode, this, pstate, 2);
  1135. def(DST, pIcode, this, pstate, 2);
  1136. break;
  1137. case iBOUND:
  1138. use(SRC, pIcode, this, pstate, 4);
  1139. use(DST, pIcode, this, pstate, cb);
  1140. break;
  1141. case iJMPF:
  1142. cb = 4;
  1143. case iJMP:
  1144. if (not Imm)
  1145. use(SRC, pIcode, this, pstate, cb);
  1146. break;
  1147. case iLOOP: case iLOOPE: case iLOOPNE:
  1148. pIcode.du.def.addReg(rCX);
  1149. pIcode.du1.addDef(rCX);
  1150. case iJCXZ:
  1151. pIcode.du.use.addReg(rCX);
  1152. break;
  1153. case iREPNE_CMPS: case iREPE_CMPS: case iREP_MOVS:
  1154. pIcode.du.addDefinedAndUsed(rCX);
  1155. pIcode.du1.addDef(rCX);
  1156. case iCMPS: case iMOVS:
  1157. pIcode.du.addDefinedAndUsed(rSI);
  1158. pIcode.du.addDefinedAndUsed(rDI);
  1159. pIcode.du1.addDef(rSI).addDef(rDI);
  1160. pIcode.du.use.addReg(rES).addReg(sseg);
  1161. break;
  1162. case iREPNE_SCAS: case iREPE_SCAS: case iREP_STOS: case iREP_INS:
  1163. pIcode.du.addDefinedAndUsed(rCX);
  1164. pIcode.du1.addDef(rCX);
  1165. case iSCAS: case iSTOS: case iINS:
  1166. pIcode.du.def.addReg(rDI);
  1167. pIcode.du1.addDef(rDI);
  1168. if (pIcode.ll()->getOpcode() == iREP_INS or pIcode.ll()->getOpcode()== iINS)
  1169. {
  1170. pIcode.du.use.addReg(rDI).addReg(rES).addReg(rDX);
  1171. }
  1172. else
  1173. {
  1174. pIcode.du.use.addReg(rDI).addReg(rES).addReg((cb == 2)? rAX: rAL);
  1175. }
  1176. break;
  1177. case iREP_LODS:
  1178. pIcode.du.addDefinedAndUsed(rCX);
  1179. pIcode.du1.addDef(rCX);
  1180. case iLODS:
  1181. {
  1182. eReg r = (cb==2)? rAX: rAL;
  1183. pIcode.du.addDefinedAndUsed(rSI);
  1184. pIcode.du1.addDef(rSI);
  1185. pIcode.du.def.addReg(r);
  1186. pIcode.du1.addDef(r);
  1187. pIcode.du.use.addReg(sseg);
  1188. }
  1189. break;
  1190. case iREP_OUTS:
  1191. pIcode.du.addDefinedAndUsed(rCX);
  1192. pIcode.du1.addDef(rCX);
  1193. case iOUTS:
  1194. pIcode.du.addDefinedAndUsed(rSI);
  1195. pIcode.du1.addDef(rSI);
  1196. pIcode.du.use.addReg(rDX).addReg(sseg);
  1197. break;
  1198. case iIN: case iOUT:
  1199. def(DST, pIcode, this, pstate, cb);
  1200. if (not Imm)
  1201. {
  1202. pIcode.du.use.addReg(rDX);
  1203. }
  1204. break;
  1205. }
  1206. for (int i = rSP; i <= rBH; i++) /* Kill all defined registers */
  1207. if (pIcode.ll()->flagDU.d & (1 << i))
  1208. pstate->f[i] = false;
  1209. }