chklib.cpp 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017
  1. /*
  2. * Code to check for library functions. If found, replaces procNNNN with the
  3. * library function name. Also checks startup code for correct DS, and the
  4. * address of main()
  5. * (C) Mike van Emmerik
  6. */
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #ifdef __BORLAND__
  10. #include <mem.h>
  11. #else
  12. #include <memory.h>
  13. #endif
  14. #include <string.h>
  15. #include "dcc.h"
  16. #include "perfhlib.h"
  17. #define NIL -1 /* Used like NULL, but 0 is valid */
  18. /* Hash table structure */
  19. typedef struct HT_tag
  20. {
  21. char htSym[SYMLEN];
  22. byte htPat[PATLEN];
  23. } HT;
  24. /* Structure of the prototypes table. Same as the struct in parsehdr.h,
  25. except here we don't need the "next" index (the elements are already
  26. sorted by function name) */
  27. typedef
  28. struct ph_func_tag
  29. {
  30. char name[SYMLEN]; /* Name of function or arg */
  31. hlType typ; /* Return type */
  32. int numArg; /* Number of args */
  33. int firstArg; /* Index of first arg in chain */
  34. // int next; /* Index of next function in chain */
  35. bool bVararg; /* True if variable arguements */
  36. } PH_FUNC_STRUCT;
  37. #define NUM_PLIST 64 /* Number of entries to increase allocation by */
  38. /* statics */
  39. char buf[100]; /* A general purpose buffer */
  40. int numKeys; /* Number of hash table entries (keys) */
  41. int numVert; /* Number of vertices in the graph (also size of g[]) */
  42. unsigned PatLen; /* Size of the keys (pattern length) */
  43. unsigned SymLen; /* Max size of the symbols, including null */
  44. FILE *f; /* File being read */
  45. static char sSigName[100]; /* Full path name of .sig file */
  46. static word *T1base, *T2base; /* Pointers to start of T1, T2 */
  47. static word *g; /* g[] */
  48. static HT *ht; /* The hash table */
  49. static PH_FUNC_STRUCT *pFunc; /* Points to the array of func names */
  50. static hlType *pArg=0; /* Points to the array of param types */
  51. static int numFunc; /* Number of func names actually stored */
  52. static int numArg; /* Number of param names actually stored */
  53. #define DCCLIBS "dcclibs.dat" /* Name of the prototypes data file */
  54. /* prototypes */
  55. void grab(int n, FILE *f);
  56. word readFileShort(FILE *f);
  57. void readFileSection(word* p, int len, FILE *f);
  58. void cleanup(void);
  59. void checkStartup(STATE *state);
  60. void readProtoFile(void);
  61. void fixNewline(char *s);
  62. int searchPList(char *name);
  63. void checkHeap(char *msg); /* For debugging */
  64. void fixWildCards(byte pat[]); /* In fixwild.c */
  65. static boolT locatePattern(byte *source, Int iMin, Int iMax, byte *pattern,
  66. Int iPatLen, Int *index);
  67. /* * * * * * * * * * * * * * * *\
  68. * *
  69. * S t a r t P a t t e r n s ( V e n d o r i d ) *
  70. * *
  71. \* * * * * * * * * * * * * * * */
  72. static byte pattMsC5Start[] =
  73. {
  74. 0xB4, 0x30, /* Mov ah, 30 */
  75. 0xCD, 0x21, /* int 21 (dos version number) */
  76. 0x3C, 0x02, /* cmp al, 2 */
  77. 0x73, 0x02, /* jnb $+4 */
  78. 0xCD, 0x20, /* int 20 (exit) */
  79. 0xBF /* Mov di, DSEG */
  80. };
  81. static byte pattMsC8Start[] =
  82. {
  83. 0xB4, 0x30, /* Mov ah, 30 */
  84. 0xCD, 0x21, /* int 21 */
  85. 0x3C, 0x02, /* cmp al,2 */
  86. 0x73, 0x05, /* jnb $+7 */
  87. 0x33, 0xC0, /* xor ax, ax */
  88. 0x06, 0x50, /* push es:ax */
  89. 0xCB, /* retf */
  90. 0xBF /* mov di, DSEG */
  91. };
  92. static byte pattMsC8ComStart[] =
  93. {
  94. 0xB4, 0x30, /* Mov ah, 30 */
  95. 0xCD, 0x21, /* int 21 (dos version number) */
  96. 0x3C, 0x02, /* cmp al, 2 */
  97. 0x73, 0x01, /* jnb $+3 */
  98. 0xC3, /* ret */
  99. 0x8C, 0xDF /* Mov di, ds */
  100. };
  101. static byte pattBorl2Start[] =
  102. {
  103. 0xBA, WILD, WILD, /* Mov dx, dseg */
  104. 0x2E, 0x89, 0x16, /* mov cs:[], dx */
  105. WILD, WILD,
  106. 0xB4, 0x30, /* mov ah, 30 */
  107. 0xCD, 0x21, /* int 21 (dos version number) */
  108. 0x8B, 0x2E, 0x02, 0, /* mov bp, [2] */
  109. 0x8B, 0x1E, 0x2C, 0, /* mov bx, [2C] */
  110. 0x8E, 0xDA, /* mov ds, dx */
  111. 0xA3, WILD, WILD, /* mov [xx], ax */
  112. 0x8C, 0x06, WILD, WILD, /* mov [xx], es */
  113. 0x89, 0x1E, WILD, WILD, /* mov [xx], bx */
  114. 0x89, 0x2E, WILD, WILD, /* mov [xx], bp */
  115. 0xC7 /* mov [xx], -1 */
  116. };
  117. static byte pattBorl3Start[] =
  118. {
  119. 0xBA, WILD, WILD, /* Mov dx, dseg */
  120. 0x2E, 0x89, 0x16, /* mov cs:[], dx */
  121. WILD, WILD,
  122. 0xB4, 0x30, /* mov ah, 30 */
  123. 0xCD, 0x21, /* int 21 (dos version number) */
  124. 0x8B, 0x2E, 0x02, 0, /* mov bp, [2] */
  125. 0x8B, 0x1E, 0x2C, 0, /* mov bx, [2C] */
  126. 0x8E, 0xDA, /* mov ds, dx */
  127. 0xA3, WILD, WILD, /* mov [xx], ax */
  128. 0x8C, 0x06, WILD, WILD, /* mov [xx], es */
  129. 0x89, 0x1E, WILD, WILD, /* mov [xx], bx */
  130. 0x89, 0x2E, WILD, WILD, /* mov [xx], bp */
  131. 0xE8 /* call ... */
  132. };
  133. static byte pattBorl4on[] =
  134. {
  135. 0x9A, 0, 0, WILD, WILD /* Call init (offset always 0) */
  136. };
  137. static byte pattBorl4Init[] =
  138. {
  139. 0xBA, WILD, WILD, /* Mov dx, dseg */
  140. 0x8E, 0xDA, /* mov ds, dx */
  141. 0x8C, 0x06, WILD, WILD, /* mov [xx], es */
  142. 0x8B, 0xC4, /* mov ax, sp */
  143. 0x05, 0x13, 0, /* add ax, 13h */
  144. 0xB1, 0x04, /* mov cl, 4 */
  145. 0xD3, 0xE8, /* shr ax, cl */
  146. 0x8C, 0xD2 /* mov dx, ss */
  147. };
  148. static byte pattBorl5Init[] =
  149. {
  150. 0xBA, WILD, WILD, /* Mov dx, dseg */
  151. 0x8E, 0xDA, /* mov ds, dx */
  152. 0x8C, 0x06, 0x30, 0, /* mov [0030], es */
  153. 0x33, 0xED, /* xor bp, bp <----- */
  154. 0x8B, 0xC4, /* mov ax, sp */
  155. 0x05, 0x13, 0, /* add ax, 13h */
  156. 0xB1, 0x04, /* mov cl, 4 */
  157. 0xD3, 0xE8, /* shr ax, cl */
  158. 0x8C, 0xD2 /* mov dx, ss */
  159. };
  160. static byte pattBorl7Init[] =
  161. {
  162. 0xBA, WILD, WILD, /* Mov dx, dseg */
  163. 0x8E, 0xDA, /* mov ds, dx */
  164. 0x8C, 0x06, 0x30, 0, /* mov [0030], es */
  165. 0xE8, WILD, WILD, /* call xxxx */
  166. 0xE8, WILD, WILD, /* call xxxx... offset always 00A0? */
  167. 0x8B, 0xC4, /* mov ax, sp */
  168. 0x05, 0x13, 0, /* add ax, 13h */
  169. 0xB1, 0x04, /* mov cl, 4 */
  170. 0xD3, 0xE8, /* shr ax, cl */
  171. 0x8C, 0xD2 /* mov dx, ss */
  172. };
  173. static byte pattLogiStart[] =
  174. {
  175. 0xEB, 0x04, /* jmp short $+6 */
  176. WILD, WILD, /* Don't know what this is */
  177. WILD, WILD, /* Don't know what this is */
  178. 0xB8, WILD, WILD, /* mov ax, dseg */
  179. 0x8E, 0xD8 /* mov ds, ax */
  180. };
  181. static byte pattTPasStart[] =
  182. {
  183. 0xE9, 0x79, 0x2C /* Jmp 2D7C - Turbo pascal 3.0 */
  184. };
  185. /* * * * * * * * * * * * * * * *\
  186. * *
  187. * M a i n P a t t e r n s ( M o d e l i d ) *
  188. * *
  189. \* * * * * * * * * * * * * * * */
  190. /* This pattern works for MS and Borland, small and tiny model */
  191. static byte pattMainSmall[] =
  192. {
  193. 0xFF, 0x36, WILD, WILD, /* Push environment pointer */
  194. 0xFF, 0x36, WILD, WILD, /* Push argv */
  195. 0xFF, 0x36, WILD, WILD, /* Push argc */
  196. 0xE8, WILD, WILD /* call _main */
  197. /* 0x50, /* push ax... not in Borland V3 */
  198. /* 0xE8 /* call _exit */
  199. };
  200. /* Num bytes from start pattern to the relative offset of main() */
  201. #define OFFMAINSMALL 13
  202. /* This pattern works for MS and Borland, medium model */
  203. static byte pattMainMedium[] =
  204. {
  205. 0xFF, 0x36, WILD, WILD, /* Push environment pointer */
  206. 0xFF, 0x36, WILD, WILD, /* Push argv */
  207. 0xFF, 0x36, WILD, WILD, /* Push argc */
  208. 0x9A, WILD, WILD, WILD, WILD /* call far _main */
  209. /* 0x50 /* push ax */
  210. /* 0x0E, /* push cs NB not tested Borland */
  211. /* 0xE8 /* call _exit */
  212. };
  213. /* Num bytes from start pattern to the relative offset of main() */
  214. #define OFFMAINMEDIUM 13
  215. /* This pattern works for MS and Borland, compact model */
  216. static byte pattMainCompact[] =
  217. {
  218. 0xFF, 0x36, WILD, WILD, /* Push environment pointer lo */
  219. 0xFF, 0x36, WILD, WILD, /* Push environment pointer hi */
  220. 0xFF, 0x36, WILD, WILD, /* Push argv lo */
  221. 0xFF, 0x36, WILD, WILD, /* Push argv hi */
  222. 0xFF, 0x36, WILD, WILD, /* Push argc */
  223. 0xE8, WILD, WILD, /* call _main */
  224. /* 0x50, /* push ax */
  225. /* 0xE8 /* call _exit */
  226. };
  227. /* Num bytes from start pattern to the relative offset of main() */
  228. #define OFFMAINCOMPACT 21
  229. /* This pattern works for MS and Borland, large model */
  230. static byte pattMainLarge[] =
  231. {
  232. 0xFF, 0x36, WILD, WILD, /* Push environment pointer lo */
  233. 0xFF, 0x36, WILD, WILD, /* Push environment pointer hi */
  234. 0xFF, 0x36, WILD, WILD, /* Push argv lo */
  235. 0xFF, 0x36, WILD, WILD, /* Push argv hi */
  236. 0xFF, 0x36, WILD, WILD, /* Push argc */
  237. 0x9A, WILD, WILD, WILD, WILD /* call far _main */
  238. /* 0x50 /* push ax */
  239. /* 0x0E, /* push cs */
  240. /* 0xE8 /* call _exit */
  241. };
  242. /* Num bytes from start pattern to the relative offset of main() */
  243. #define OFFMAINLARGE 21
  244. /* * * * * * * * * * * * * * * *\
  245. * *
  246. * M i s c e l l a n e o u s P a t t e r n s *
  247. * *
  248. \* * * * * * * * * * * * * * * */
  249. /* This pattern is for the stack check code in Microsoft compilers */
  250. static byte pattMsChkstk[] =
  251. {
  252. 0x59, /* pop cx */
  253. 0x8B, 0xDC, /* mov bx, sp */
  254. 0x2B, 0xD8, /* sub bx, ax */
  255. 0x72, 0x0A, /* jb bad */
  256. 0x3B, 0x1E, WILD, WILD, /* cmp bx, XXXX */
  257. 0x72, 0x04, /* jb bad */
  258. 0x8B, 0xE3, /* mov sp, bx */
  259. 0xFF, 0xE1, /* jmp [cx] */
  260. 0x33, 0xC0, /* xor ax, ax */
  261. 0xE9 /* jmp XXXX */
  262. };
  263. /* This procedure is called to initialise the library check code */
  264. void SetupLibCheck(void)
  265. {
  266. word w, len;
  267. int i;
  268. if ((f = fopen(sSigName, "rb")) == NULL)
  269. {
  270. printf("Warning: cannot open signature file %s\n", sSigName);
  271. return;
  272. }
  273. readProtoFile();
  274. prog.bSigs = FALSE; /* False unless everything goes right */
  275. /* Read the parameters */
  276. grab(4, f);
  277. if (memcmp("dccs", buf, 4) != 0)
  278. {
  279. printf("Not a dcc signature file!\n");
  280. exit(3);
  281. }
  282. numKeys = readFileShort(f);
  283. numVert = readFileShort(f);
  284. PatLen = readFileShort(f);
  285. SymLen = readFileShort(f);
  286. if ((PatLen != PATLEN) || (SymLen != SYMLEN))
  287. {
  288. printf("Sorry! Compiled for sym and pattern lengths of %d and %d\n",
  289. SYMLEN, PATLEN);
  290. exit(1);
  291. }
  292. /* Initialise the perfhlib stuff. Also allocates T1, T2, g, etc */
  293. /* Set the parameters for the hash table */
  294. g_pattern_hasher.init(
  295. numKeys, /* The number of symbols */
  296. PatLen, /* The length of the pattern to be hashed */
  297. 256, /* The character set of the pattern (0-FF) */
  298. 0, /* Minimum pattern character value */
  299. numVert); /* Specifies c, the sparseness of the graph.
  300. See Czech, Havas and Majewski for details */
  301. T1base = g_pattern_hasher.readT1();
  302. T2base = g_pattern_hasher.readT2();
  303. g = g_pattern_hasher.readG();
  304. /* Read T1 and T2 tables */
  305. grab(2, f);
  306. if (memcmp("T1", buf, 2) != 0)
  307. {
  308. printf("Expected 'T1'\n");
  309. exit(3);
  310. }
  311. len = (word) (PatLen * 256 * sizeof(word));
  312. w = readFileShort(f);
  313. if (w != len)
  314. {
  315. printf("Problem with size of T1: file %d, calc %d\n", w, len);
  316. exit(4);
  317. }
  318. readFileSection(T1base, len, f);
  319. grab(2, f);
  320. if (memcmp("T2", buf, 2) != 0)
  321. {
  322. printf("Expected 'T2'\n");
  323. exit(3);
  324. }
  325. w = readFileShort(f);
  326. if (w != len)
  327. {
  328. printf("Problem with size of T2: file %d, calc %d\n", w, len);
  329. exit(4);
  330. }
  331. readFileSection(T2base, len, f);
  332. /* Now read the function g[] */
  333. grab(2, f);
  334. if (memcmp("gg", buf, 2) != 0)
  335. {
  336. printf("Expected 'gg'\n");
  337. exit(3);
  338. }
  339. len = (word)(numVert * sizeof(word));
  340. w = readFileShort(f);
  341. if (w != len)
  342. {
  343. printf("Problem with size of g[]: file %d, calc %d\n", w, len);
  344. exit(4);
  345. }
  346. readFileSection(g, len, f);
  347. /* This is now the hash table */
  348. /* First allocate space for the table */
  349. ht = new HT[numKeys];
  350. if ( 0 == ht)
  351. {
  352. printf("Could not allocate hash table\n");
  353. exit(1);
  354. }
  355. grab(2, f);
  356. if (memcmp("ht", buf, 2) != 0)
  357. {
  358. printf("Expected 'ht'\n");
  359. exit(3);
  360. }
  361. w = readFileShort(f);
  362. if (w != numKeys * (SymLen + PatLen + sizeof(word)))
  363. {
  364. printf("Problem with size of hash table: file %d, calc %d\n", w, len);
  365. exit(6);
  366. }
  367. for (i=0; i < numKeys; i++)
  368. {
  369. if (fread(&ht[i], 1, SymLen + PatLen, f) != SymLen + PatLen)
  370. {
  371. printf("Could not read signature\n");
  372. exit(11);
  373. }
  374. }
  375. fclose(f);
  376. prog.bSigs = TRUE;
  377. }
  378. void CleanupLibCheck(void)
  379. {
  380. /* Deallocate all the stuff allocated in SetupLibCheck() */
  381. delete [] ht;
  382. delete [] pFunc;
  383. }
  384. /* Check this function to see if it is a library function. Return TRUE if
  385. it is, and copy its name to pProc->name
  386. */
  387. bool LibCheck(Function & pProc)
  388. {
  389. long fileOffset;
  390. int h, i, j, arg;
  391. Int Idx;
  392. byte pat[PATLEN];
  393. if (prog.bSigs == FALSE)
  394. {
  395. /* No signatures... can't rely on hash parameters to be initialised
  396. so always return false */
  397. return FALSE;
  398. }
  399. fileOffset = pProc.procEntry; /* Offset into the image */
  400. if (fileOffset == prog.offMain)
  401. {
  402. /* Easy - this function is called main! */
  403. pProc.name = "main";
  404. return false;
  405. }
  406. memmove(pat, &prog.Image[fileOffset], PATLEN);
  407. fixWildCards(pat); /* Fix wild cards in the copy */
  408. h = g_pattern_hasher.hash(pat); /* Hash the found proc */
  409. /* We always have to compare keys, because the hash function will
  410. always return a valid index */
  411. if (memcmp(ht[h].htPat, pat, PATLEN) == 0)
  412. {
  413. /* We have a match. Save the name, if not already set */
  414. if (pProc.name.empty() ) /* Don't overwrite existing name */
  415. {
  416. /* Give proc the new name */
  417. pProc.name = ht[h].htSym;
  418. }
  419. /* But is it a real library function? */
  420. i = NIL;
  421. if ((numFunc == 0) || (i=searchPList(ht[h].htSym)) != NIL)
  422. {
  423. pProc.flg |= PROC_ISLIB; /* It's a lib function */
  424. if (i != NIL)
  425. {
  426. /* Allocate space for the arg struct, and copy the hlType to
  427. the appropriate field */
  428. arg = pFunc[i].firstArg;
  429. pProc.args.numArgs = pFunc[i].numArg;
  430. pProc.args.sym.resize(pFunc[i].numArg);
  431. for (j=0; j < pFunc[i].numArg; j++)
  432. {
  433. pProc.args.sym[j].type = pArg[arg++];
  434. }
  435. if (pFunc[i].typ != TYPE_UNKNOWN)
  436. {
  437. pProc.retVal.type = pFunc[i].typ;
  438. pProc.flg |= PROC_IS_FUNC;
  439. switch (pProc.retVal.type) {
  440. case TYPE_LONG_SIGN: case TYPE_LONG_UNSIGN:
  441. pProc.liveOut = duReg[rDX] | duReg[rAX];
  442. break;
  443. case TYPE_WORD_SIGN: case TYPE_WORD_UNSIGN:
  444. pProc.liveOut = duReg[rAX];
  445. break;
  446. case TYPE_BYTE_SIGN: case TYPE_BYTE_UNSIGN:
  447. pProc.liveOut = duReg[rAL];
  448. break;
  449. /*** other types are not considered yet ***/
  450. }
  451. }
  452. if (pFunc[i].bVararg)
  453. pProc.flg |= PROC_VARARG;
  454. }
  455. }
  456. else if (i == NIL)
  457. {
  458. /* Have a symbol for it, but does not appear in a header file.
  459. Treat it as if it is not a library function */
  460. pProc.flg |= PROC_RUNTIME; /* => is a runtime routine */
  461. }
  462. }
  463. if (locatePattern(prog.Image, pProc.procEntry,
  464. pProc.procEntry+sizeof(pattMsChkstk),
  465. pattMsChkstk, sizeof(pattMsChkstk), &Idx))
  466. {
  467. /* Found _chkstk */
  468. pProc.name = "chkstk";
  469. pProc.flg |= PROC_ISLIB; /* We'll say its a lib function */
  470. pProc.args.numArgs = 0; /* With no args */
  471. }
  472. return (boolT)((pProc.flg & PROC_ISLIB) != 0);
  473. }
  474. void grab(int n, FILE *f)
  475. {
  476. if (fread(buf, 1, n, f) != (unsigned)n)
  477. {
  478. printf("Could not grab\n");
  479. exit(11);
  480. }
  481. }
  482. word
  483. readFileShort(FILE *f)
  484. {
  485. byte b1, b2;
  486. if (fread(&b1, 1, 1, f) != 1)
  487. {
  488. printf("Could not read short\n");
  489. exit(11);
  490. }
  491. if (fread(&b2, 1, 1, f) != 1)
  492. {
  493. printf("Could not read short\n");
  494. exit(11);
  495. }
  496. return (word)(b2 << 8) + (word)b1;
  497. }
  498. // Read a section of the file, considering endian issues
  499. void
  500. readFileSection(word* p, int len, FILE* f)
  501. {
  502. for (int i=0; i < len; i += 2)
  503. {
  504. *p++ = readFileShort(f);
  505. }
  506. }
  507. /* The following two functions are dummies, since we don't call map() */
  508. void getKey(int i, byte **keys)
  509. {
  510. }
  511. void dispKey(int i)
  512. {
  513. }
  514. /* Search the source array between limits iMin and iMax for the pattern (length
  515. iPatLen). The pattern can contain wild bytes; if you really want to match
  516. for the pattern that is used up by the WILD byte, tough - it will match with
  517. everything else as well. */
  518. static boolT locatePattern(byte *source, Int iMin, Int iMax, byte *pattern, Int iPatLen,
  519. Int *index)
  520. {
  521. Int i, j;
  522. byte *pSrc; /* Pointer to start of considered source */
  523. Int iLast;
  524. iLast = iMax - iPatLen; /* Last source byte to consider */
  525. for (i=iMin; i <= iLast; i++)
  526. {
  527. pSrc = &source[i]; /* Start of current part of source */
  528. /* i is the index of the start of the moving pattern */
  529. for (j=0; j < iPatLen; j++)
  530. {
  531. /* j is the index of the byte being considered in the pattern. */
  532. if ((*pSrc != pattern[j]) && (pattern[j] != WILD))
  533. {
  534. /* A definite mismatch */
  535. break; /* Break to outer loop */
  536. }
  537. pSrc++;
  538. }
  539. if (j >= iPatLen)
  540. {
  541. /* Pattern has been found */
  542. *index = i; /* Pass start of pattern */
  543. return 1; /* Indicate success */
  544. }
  545. /* Else just try next value of i */
  546. }
  547. /* Pattern was not found */
  548. *index = -1; /* Invalidate index */
  549. return 0; /* Indicate failure */
  550. }
  551. void STATE::checkStartup()
  552. {
  553. /* This function checks the startup code for various compilers' way of
  554. loading DS. If found, it sets DS. This may not be needed in the future if
  555. pushing and popping of registers is implemented.
  556. Also sets prog.offMain and prog.segMain if possible */
  557. Int startOff; /* Offset into the Image of the initial CS:IP */
  558. Int i, rel, para, init;
  559. char chModel = 'x';
  560. char chVendor = 'x';
  561. char chVersion = 'x';
  562. char *pPath;
  563. char temp[4];
  564. startOff = ((dword)prog.initCS << 4) + prog.initIP;
  565. /* Check the Turbo Pascal signatures first, since they involve only the
  566. first 3 bytes, and false positives may be founf with the others later */
  567. if (locatePattern(prog.Image, startOff, startOff+5, pattBorl4on,sizeof(pattBorl4on), &i))
  568. {
  569. /* The first 5 bytes are a far call. Follow that call and
  570. determine the version from that */
  571. rel = LH(&prog.Image[startOff+1]); /* This is abs off of init */
  572. para= LH(&prog.Image[startOff+3]);/* This is abs seg of init */
  573. init = ((dword)para << 4) + rel;
  574. if (locatePattern(prog.Image, init, init+26, pattBorl4Init,
  575. sizeof(pattBorl4Init), &i))
  576. {
  577. setState(rDS, LH(&prog.Image[i+1]));
  578. printf("Borland Pascal v4 detected\n");
  579. chVendor = 't'; /* Trubo */
  580. chModel = 'p'; /* Pascal */
  581. chVersion = '4'; /* Version 4 */
  582. prog.offMain = startOff; /* Code starts immediately */
  583. prog.segMain = prog.initCS; /* At the 5 byte jump */
  584. goto gotVendor; /* Already have vendor */
  585. }
  586. else if (locatePattern(prog.Image, init, init+26, pattBorl5Init,
  587. sizeof(pattBorl5Init), &i))
  588. {
  589. setState( rDS, LH(&prog.Image[i+1]));
  590. printf("Borland Pascal v5.0 detected\n");
  591. chVendor = 't'; /* Trubo */
  592. chModel = 'p'; /* Pascal */
  593. chVersion = '5'; /* Version 5 */
  594. prog.offMain = startOff; /* Code starts immediately */
  595. prog.segMain = prog.initCS;
  596. goto gotVendor; /* Already have vendor */
  597. }
  598. else if (locatePattern(prog.Image, init, init+26, pattBorl7Init,
  599. sizeof(pattBorl7Init), &i))
  600. {
  601. setState( rDS, LH(&prog.Image[i+1]));
  602. printf("Borland Pascal v7 detected\n");
  603. chVendor = 't'; /* Trubo */
  604. chModel = 'p'; /* Pascal */
  605. chVersion = '7'; /* Version 7 */
  606. prog.offMain = startOff; /* Code starts immediately */
  607. prog.segMain = prog.initCS;
  608. goto gotVendor; /* Already have vendor */
  609. }
  610. }
  611. /* Search for the call to main pattern. This is compiler independant,
  612. but decides the model required. Note: must do the far data models
  613. (large and compact) before the others, since they are the same pattern
  614. as near data, just more pushes at the start. */
  615. if(prog.cbImage>startOff+0x180+sizeof(pattMainLarge))
  616. {
  617. if (locatePattern(prog.Image, startOff, startOff+0x180, pattMainLarge,sizeof(pattMainLarge), &i))
  618. {
  619. rel = LH(&prog.Image[i+OFFMAINLARGE]); /* This is abs off of main */
  620. para= LH(&prog.Image[i+OFFMAINLARGE+2]);/* This is abs seg of main */
  621. /* Save absolute image offset */
  622. prog.offMain = ((dword)para << 4) + rel;
  623. prog.segMain = (word)para;
  624. chModel = 'l'; /* Large model */
  625. }
  626. else if (locatePattern(prog.Image, startOff, startOff+0x180, pattMainCompact,
  627. sizeof(pattMainCompact), &i))
  628. {
  629. rel = LH_SIGNED(&prog.Image[i+OFFMAINCOMPACT]);/* This is the rel addr of main */
  630. prog.offMain = i+OFFMAINCOMPACT+2+rel; /* Save absolute image offset */
  631. prog.segMain = prog.initCS;
  632. chModel = 'c'; /* Compact model */
  633. }
  634. else if (locatePattern(prog.Image, startOff, startOff+0x180, pattMainMedium,
  635. sizeof(pattMainMedium), &i))
  636. {
  637. rel = LH(&prog.Image[i+OFFMAINMEDIUM]); /* This is abs off of main */
  638. para= LH(&prog.Image[i+OFFMAINMEDIUM+2]);/* This is abs seg of main */
  639. prog.offMain = ((dword)para << 4) + rel;
  640. prog.segMain = (word)para;
  641. chModel = 'm'; /* Medium model */
  642. }
  643. else if (locatePattern(prog.Image, startOff, startOff+0x180, pattMainSmall,
  644. sizeof(pattMainSmall), &i))
  645. {
  646. rel = LH_SIGNED(&prog.Image[i+OFFMAINSMALL]); /* This is rel addr of main */
  647. prog.offMain = i+OFFMAINSMALL+2+rel; /* Save absolute image offset */
  648. prog.segMain = prog.initCS;
  649. chModel = 's'; /* Small model */
  650. }
  651. else if (memcmp(&prog.Image[startOff], pattTPasStart, sizeof(pattTPasStart)) == 0)
  652. {
  653. rel = LH_SIGNED(&prog.Image[startOff+1]); /* Get the jump offset */
  654. prog.offMain = rel+startOff+3; /* Save absolute image offset */
  655. prog.offMain += 0x20; /* These first 32 bytes are setting up */
  656. prog.segMain = prog.initCS;
  657. chVendor = 't'; /* Turbo.. */
  658. chModel = 'p'; /* ...Pascal... (only 1 model) */
  659. chVersion = '3'; /* 3.0 */
  660. printf("Turbo Pascal 3.0 detected\n");
  661. printf("Main at %04X\n", prog.offMain);
  662. goto gotVendor; /* Already have vendor */
  663. }
  664. else
  665. {
  666. printf("Main could not be located!\n");
  667. prog.offMain = -1;
  668. }
  669. }
  670. else
  671. {
  672. printf("Main could not be located!\n");
  673. prog.offMain = -1;
  674. }
  675. printf("Model: %c\n", chModel);
  676. /* Now decide the compiler vendor and version number */
  677. if (memcmp(&prog.Image[startOff], pattMsC5Start, sizeof(pattMsC5Start)) == 0)
  678. {
  679. /* Yes, this is Microsoft startup code. The DS is sitting right here
  680. in the next 2 bytes */
  681. setState( rDS, LH(&prog.Image[startOff+sizeof(pattMsC5Start)]));
  682. chVendor = 'm'; /* Microsoft compiler */
  683. chVersion = '5'; /* Version 5 */
  684. printf("MSC 5 detected\n");
  685. }
  686. /* The C8 startup pattern is different from C5's */
  687. else if (memcmp(&prog.Image[startOff], pattMsC8Start, sizeof(pattMsC8Start)) == 0)
  688. {
  689. setState( rDS, LH(&prog.Image[startOff+sizeof(pattMsC8Start)]));
  690. printf("MSC 8 detected\n");
  691. chVendor = 'm'; /* Microsoft compiler */
  692. chVersion = '8'; /* Version 8 */
  693. }
  694. /* The C8 .com startup pattern is different again! */
  695. else if (memcmp(&prog.Image[startOff], pattMsC8ComStart,
  696. sizeof(pattMsC8ComStart)) == 0)
  697. {
  698. printf("MSC 8 .com detected\n");
  699. chVendor = 'm'; /* Microsoft compiler */
  700. chVersion = '8'; /* Version 8 */
  701. }
  702. else if (locatePattern(prog.Image, startOff, startOff+0x30, pattBorl2Start,
  703. sizeof(pattBorl2Start), &i))
  704. {
  705. /* Borland startup. DS is at the second byte (offset 1) */
  706. setState( rDS, LH(&prog.Image[i+1]));
  707. printf("Borland v2 detected\n");
  708. chVendor = 'b'; /* Borland compiler */
  709. chVersion = '2'; /* Version 2 */
  710. }
  711. else if (locatePattern(prog.Image, startOff, startOff+0x30, pattBorl3Start,
  712. sizeof(pattBorl3Start), &i))
  713. {
  714. /* Borland startup. DS is at the second byte (offset 1) */
  715. setState( rDS, LH(&prog.Image[i+1]));
  716. printf("Borland v3 detected\n");
  717. chVendor = 'b'; /* Borland compiler */
  718. chVersion = '3'; /* Version 3 */
  719. }
  720. else if (locatePattern(prog.Image, startOff, startOff+0x30, pattLogiStart,
  721. sizeof(pattLogiStart), &i))
  722. {
  723. /* Logitech modula startup. DS is 0, despite appearances */
  724. printf("Logitech modula detected\n");
  725. chVendor = 'l'; /* Logitech compiler */
  726. chVersion = '1'; /* Version 1 */
  727. }
  728. /* Other startup idioms would go here */
  729. else
  730. {
  731. printf("Warning - compiler not recognised\n");
  732. }
  733. gotVendor:
  734. /* Use the DCC environment variable to set where the .sig files will
  735. be found. Otherwise, assume current directory */
  736. pPath = getenv("DCC");
  737. if (pPath)
  738. {
  739. strcpy(sSigName, pPath); /* Use path given */
  740. if (sSigName[strlen(sSigName)-1] != '/')
  741. {
  742. strcat(sSigName, "/"); /* Append a slash if necessary */
  743. }
  744. }
  745. else
  746. {
  747. strcpy(sSigName, "./"); /* Current directory */
  748. }
  749. strcat(sSigName, "dcc");
  750. temp[1] = '\0';
  751. temp[0] = chVendor;
  752. strcat(sSigName, temp); /* Add vendor */
  753. temp[0] = chVersion;
  754. strcat(sSigName, temp); /* Add version */
  755. temp[0] = chModel;
  756. strcat(sSigName, temp); /* Add model */
  757. strcat(sSigName, ".sig"); /* Add extension */
  758. printf("Signature file: %s\n", sSigName);
  759. }
  760. /* DCCLIBS.DAT is a data file sorted on function name containing names and
  761. return types of functions found in include files, and the names and types
  762. of arguements. Only functions in this list will be considered library
  763. functions; others (like LXMUL@) are helper files, and need to be analysed
  764. by dcc, rather than considered as known functions. When a prototype is
  765. found (in searchPList()), the parameter info is written to the proc struct.
  766. */
  767. void
  768. readProtoFile(void)
  769. {
  770. FILE *fProto;
  771. char *pPath; /* Point to the environment string */
  772. char szProFName[81]; /* Full name of dclibs.lst */
  773. int i;
  774. /* Use the DCC environment variable to set where the dcclibs.lst file will
  775. be found. Otherwise, assume current directory */
  776. pPath = getenv("DCC");
  777. if (pPath)
  778. {
  779. strcpy(szProFName, pPath); /* Use path given */
  780. if (szProFName[strlen(szProFName)-1] != '/')
  781. {
  782. strcat(szProFName, "/"); /* Append a slash if necessary */
  783. }
  784. }
  785. else
  786. {
  787. strcpy(szProFName, "./"); /* Current directory */
  788. }
  789. strcat(szProFName, DCCLIBS);
  790. if ((fProto = fopen(szProFName, "rb")) == NULL)
  791. {
  792. printf("Warning: cannot open library prototype data file %s\n", szProFName);
  793. return;
  794. }
  795. grab(4, fProto);
  796. if (strncmp(buf, "dccp", 4) != 0)
  797. {
  798. printf("%s is not a dcc prototype file\n", szProFName);
  799. exit(1);
  800. }
  801. grab(2, fProto);
  802. if (strncmp(buf, "FN", 2) != 0)
  803. {
  804. printf("FN (Function Name) subsection expected in %s\n", szProFName);
  805. exit(2);
  806. }
  807. numFunc = readFileShort(fProto); /* Num of entries to allocate */
  808. /* Allocate exactly correct # entries */
  809. pFunc = new PH_FUNC_STRUCT[numFunc];
  810. for (i=0; i < numFunc; i++)
  811. {
  812. fread(&pFunc[i], 1, SYMLEN, fProto);
  813. pFunc[i].typ = (hlType)readFileShort(fProto);
  814. pFunc[i].numArg = readFileShort(fProto);
  815. pFunc[i].firstArg = readFileShort(fProto);
  816. fread(&pFunc[i].bVararg, 1, 1, fProto);
  817. }
  818. grab(2, fProto);
  819. if (strncmp(buf, "PM", 2) != 0)
  820. {
  821. printf("PM (Parameter) subsection expected in %s\n", szProFName);
  822. exit(2);
  823. }
  824. numArg = readFileShort(fProto); /* Num of entries to allocate */
  825. /* Allocate exactly correct # entries */
  826. delete [] pArg;
  827. pArg = new hlType[numArg];
  828. for (i=0; i < numArg; i++)
  829. {
  830. // fread(&pArg[i], 1, SYMLEN, fProto); /* No names to read as yet */
  831. pArg[i] = (hlType) readFileShort(fProto);
  832. }
  833. fclose(fProto);
  834. }
  835. int
  836. searchPList(char *name)
  837. {
  838. /* Search through the symbol names for the name */
  839. /* Use binary search */
  840. int mx, mn, i, res;
  841. mx = numFunc;
  842. mn = 0;
  843. while (mn < mx)
  844. {
  845. i = (mn + mx) /2;
  846. res = strcmp(pFunc[i].name, name);
  847. if (res == 0)
  848. {
  849. return i; /* Found! */
  850. }
  851. else
  852. {
  853. if (res < 0)
  854. {
  855. mn = i+1;
  856. }
  857. else
  858. {
  859. mx = i-1;
  860. }
  861. }
  862. }
  863. /* Still could be the case that mn == mx == required record */
  864. res = strcmp(pFunc[mn].name, name);
  865. if (res == 0)
  866. {
  867. return mn; /* Found! */
  868. }
  869. else
  870. {
  871. return NIL;
  872. }
  873. }
  874. #if DEBUG_HEAP
  875. void
  876. checkHeap(char *msg)
  877. /* HEAPCHK.C: This program checks the heap for
  878. * consistency and prints an appropriate message.
  879. */
  880. {
  881. int heapstatus;
  882. printf("%s\n", msg);
  883. /* Check heap status */
  884. heapstatus = _heapchk();
  885. switch( heapstatus )
  886. {
  887. case _HEAPOK:
  888. printf(" OK - heap is fine\n" );
  889. break;
  890. case _HEAPEMPTY:
  891. printf(" OK - heap is empty\n" );
  892. break;
  893. case _HEAPBADBEGIN:
  894. printf( "ERROR - bad start of heap\n" );
  895. break;
  896. case _HEAPBADNODE:
  897. printf( "ERROR - bad node in heap\n" );
  898. break;
  899. }
  900. }
  901. #endif