LIB_PatternCollector.cpp 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. #include "LIB_PatternCollector.h"
  2. #include <cstring>
  3. #include <cstring>
  4. /** \note there is an untested assumption that the *first* segment definition
  5. with class CODE will be the one containing all useful functions in the
  6. LEDATA records. Functions such as _exit() have more than one segment
  7. declared with class CODE (MSC8 libraries) */
  8. extern void fixWildCards(uint8_t pat[]);
  9. void readNN(int n, FILE *fl)
  10. {
  11. if (fseek(fl, (long)n, SEEK_CUR) != 0)
  12. {
  13. printf("Could not seek file\n");
  14. exit(2);
  15. }
  16. }
  17. void LIB_PatternCollector::readString(FILE *fl)
  18. {
  19. uint8_t len;
  20. len = readByte(fl);
  21. if (fread(buf, 1, len, fl) != len)
  22. {
  23. printf("Could not read string len %d\n", len);
  24. exit(2);
  25. }
  26. buf[len] = '\0';
  27. offset += len;
  28. }
  29. int LIB_PatternCollector::readSyms(FILE *fl)
  30. {
  31. int i;
  32. int count = 0;
  33. int firstSym = 0; /* First symbol this module */
  34. uint8_t b, c, type;
  35. uint16_t w, len;
  36. codeLNAMES = NONE; /* Invalidate indexes for code segment */
  37. codeSEGDEF = NONE; /* Else won't be assigned */
  38. offset = 0; /* For diagnostics, really */
  39. if ((leData = (uint8_t *)malloc(0xFF80)) == 0)
  40. {
  41. printf("Could not malloc 64k bytes for LEDATA\n");
  42. exit(10);
  43. }
  44. while (!feof(fl))
  45. {
  46. type = readByte(fl);
  47. len = readWord(fl);
  48. /* Note: uncommenting the following generates a *lot* of output */
  49. /*printf("Offset %05lX: type %02X len %d\n", offset-3, type, len);//*/
  50. switch (type)
  51. {
  52. case 0x96: /* LNAMES */
  53. while (len > 1)
  54. {
  55. readString(fl);
  56. ++lnum;
  57. if (strcmp((char *)buf, "CODE") == 0)
  58. {
  59. /* This is the class name we're looking for */
  60. codeLNAMES= lnum;
  61. }
  62. len -= strlen((char *)buf)+1;
  63. }
  64. b = readByte(fl); /* Checksum */
  65. break;
  66. case 0x98: /* Segment definition */
  67. b = readByte(fl); /* Segment attributes */
  68. if ((b & 0xE0) == 0)
  69. {
  70. /* Alignment field is zero. Frame and offset follow */
  71. readWord(fl);
  72. readByte(fl);
  73. }
  74. w = readWord(fl); /* Segment length */
  75. b = readByte(fl); /* Segment name index */
  76. ++segnum;
  77. b = readByte(fl); /* Class name index */
  78. if ((b == codeLNAMES) && (codeSEGDEF == NONE))
  79. {
  80. /* This is the segment defining the code class */
  81. codeSEGDEF = segnum;
  82. }
  83. b = readByte(fl); /* Overlay index */
  84. b = readByte(fl); /* Checksum */
  85. break;
  86. case 0x90: /* PUBDEF: public symbols */
  87. b = readByte(fl); /* Base group */
  88. c = readByte(fl); /* Base segment */
  89. len -= 2;
  90. if (c == 0)
  91. {
  92. w = readWord(fl);
  93. len -= 2;
  94. }
  95. while (len > 1)
  96. {
  97. readString(fl);
  98. w = readWord(fl); /* Offset */
  99. b = readByte(fl); /* Type index */
  100. if (c == codeSEGDEF)
  101. {
  102. char *p;
  103. HASHENTRY entry;
  104. p = (char *)buf;
  105. if (buf[0] == '_') /* Leading underscore? */
  106. {
  107. p++; /* Yes, remove it*/
  108. }
  109. i = std::min(size_t(SYMLEN-1), strlen(p));
  110. memcpy(entry.name, p, i);
  111. entry.name[i] = '\0';
  112. entry.offset = w;
  113. /*printf("%04X: %s is sym #%d\n", w, keys[count].name, count);//*/
  114. keys.push_back(entry);
  115. count++;
  116. }
  117. len -= strlen((char *)buf) + 1 + 2 + 1;
  118. }
  119. b = readByte(fl); /* Checksum */
  120. break;
  121. case 0xA0: /* LEDATA */
  122. {
  123. b = readByte(fl); /* Segment index */
  124. w = readWord(fl); /* Offset */
  125. len -= 3;
  126. /*printf("LEDATA seg %d off %02X len %Xh, looking for %d\n", b, w, len-1, codeSEGDEF);//*/
  127. if (b != codeSEGDEF)
  128. {
  129. readNN(len,fl); /* Skip the data */
  130. break; /* Next record */
  131. }
  132. if (fread(&leData[w], 1, len-1, fl) != len-1)
  133. {
  134. printf("Could not read LEDATA length %d\n", len-1);
  135. exit(2);
  136. }
  137. offset += len-1;
  138. maxLeData = std::max<uint16_t>(maxLeData, w+len-1);
  139. readByte(fl); /* Checksum */
  140. break;
  141. }
  142. default:
  143. readNN(len,fl); /* Just skip the lot */
  144. if (type == 0x8A) /* Mod end */
  145. {
  146. /* Now find all the patterns for public code symbols that
  147. we have found */
  148. for (i=firstSym; i < count; i++)
  149. {
  150. uint16_t off = keys[i].offset;
  151. if (off == (uint16_t)-1)
  152. {
  153. continue; /* Ignore if already done */
  154. }
  155. if (keys[i].offset > maxLeData)
  156. {
  157. printf(
  158. "Warning: no LEDATA for symbol #%d %s "
  159. "(offset %04X, max %04X)\n",
  160. i, keys[i].name, off, maxLeData);
  161. /* To make things consistant, we set the pattern for
  162. this symbol to nulls */
  163. memset(&keys[i].pat, 0, PATLEN);
  164. continue;
  165. }
  166. /* Copy to temp buffer so don't overrun later patterns.
  167. (e.g. when chopping a short pattern).
  168. Beware of short patterns! */
  169. if (off+PATLEN <= maxLeData)
  170. {
  171. /* Available pattern is >= PATLEN */
  172. memcpy(buf, &leData[off], PATLEN);
  173. }
  174. else
  175. {
  176. /* Short! Only copy what is available (and malloced!) */
  177. memcpy(buf, &leData[off], maxLeData-off);
  178. /* Set rest to zeroes */
  179. memset(&buf[maxLeData-off], 0, PATLEN-(maxLeData-off));
  180. }
  181. fixWildCards((uint8_t *)buf);
  182. /* Save into the hash entry. */
  183. memcpy(keys[i].pat, buf, PATLEN);
  184. keys[i].offset = (uint16_t)-1; // Flag it as done
  185. //printf("Saved pattern for %s\n", keys[i].name);
  186. }
  187. while (readByte(fl) == 0);
  188. readNN(-1,fl); /* Unget the last byte (= type) */
  189. lnum = 0; /* Reset index into lnames */
  190. segnum = 0; /* Reset index into snames */
  191. firstSym = count; /* Remember index of first sym this mod */
  192. codeLNAMES = NONE; /* Invalidate indexes for code segment */
  193. codeSEGDEF = NONE;
  194. memset(leData, 0, maxLeData); /* Clear out old junk */
  195. maxLeData = 0; /* No data read this module */
  196. }
  197. else if (type == 0xF1)
  198. {
  199. /* Library end record */
  200. return count;
  201. }
  202. }
  203. }
  204. free(leData);
  205. keys.clear();
  206. return count;
  207. }