chklib.cpp 34 KB

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