123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240 |
- #include "LIB_PatternCollector.h"
- #include "msvc_fixes.h"
- #include <cstring>
- #include <cstring>
- /** \note there is an untested assumption that the *first* segment definition
- with class CODE will be the one containing all useful functions in the
- LEDATA records. Functions such as _exit() have more than one segment
- declared with class CODE (MSC8 libraries) */
- extern void fixWildCards(uint8_t pat[]);
- void readNN(int n, FILE *fl)
- {
- if (fseek(fl, (long)n, SEEK_CUR) != 0)
- {
- printf("Could not seek file\n");
- exit(2);
- }
- }
- void LIB_PatternCollector::readString(FILE *fl)
- {
- uint8_t len;
- len = readByte(fl);
- if (fread(buf, 1, len, fl) != len)
- {
- printf("Could not read string len %d\n", len);
- exit(2);
- }
- buf[len] = '\0';
- offset += len;
- }
- int LIB_PatternCollector::readSyms(FILE *fl)
- {
- int i;
- int count = 0;
- int firstSym = 0; /* First symbol this module */
- uint8_t b, c, type;
- uint16_t w, len;
- codeLNAMES = NONE; /* Invalidate indexes for code segment */
- codeSEGDEF = NONE; /* Else won't be assigned */
- offset = 0; /* For diagnostics, really */
- if ((leData = (uint8_t *)malloc(0xFF80)) == 0)
- {
- printf("Could not malloc 64k bytes for LEDATA\n");
- exit(10);
- }
- while (not feof(fl))
- {
- type = readByte(fl);
- len = readWord(fl);
- /* Note: uncommenting the following generates a *lot* of output */
- /*printf("Offset %05lX: type %02X len %d\n", offset-3, type, len);//*/
- switch (type)
- {
- case 0x96: /* LNAMES */
- while (len > 1)
- {
- readString(fl);
- ++lnum;
- if (strcmp((char *)buf, "CODE") == 0)
- {
- /* This is the class name we're looking for */
- codeLNAMES= lnum;
- }
- len -= strlen((char *)buf)+1;
- }
- b = readByte(fl); /* Checksum */
- break;
- case 0x98: /* Segment definition */
- b = readByte(fl); /* Segment attributes */
- if ((b & 0xE0) == 0)
- {
- /* Alignment field is zero. Frame and offset follow */
- readWord(fl);
- readByte(fl);
- }
- w = readWord(fl); /* Segment length */
- b = readByte(fl); /* Segment name index */
- ++segnum;
- b = readByte(fl); /* Class name index */
- if ((b == codeLNAMES) and (codeSEGDEF == NONE))
- {
- /* This is the segment defining the code class */
- codeSEGDEF = segnum;
- }
- b = readByte(fl); /* Overlay index */
- b = readByte(fl); /* Checksum */
- break;
- case 0x90: /* PUBDEF: public symbols */
- b = readByte(fl); /* Base group */
- c = readByte(fl); /* Base segment */
- len -= 2;
- if (c == 0)
- {
- w = readWord(fl);
- len -= 2;
- }
- while (len > 1)
- {
- readString(fl);
- w = readWord(fl); /* Offset */
- b = readByte(fl); /* Type index */
- if (c == codeSEGDEF)
- {
- char *p;
- HASHENTRY entry;
- p = (char *)buf;
- if (buf[0] == '_') /* Leading underscore? */
- {
- p++; /* Yes, remove it*/
- }
- i = std::min(size_t(SYMLEN-1), strlen(p));
- memcpy(entry.name, p, i);
- entry.name[i] = '\0';
- entry.offset = w;
- /*printf("%04X: %s is sym #%d\n", w, keys[count].name, count);//*/
- keys.push_back(entry);
- count++;
- }
- len -= strlen((char *)buf) + 1 + 2 + 1;
- }
- b = readByte(fl); /* Checksum */
- break;
- case 0xA0: /* LEDATA */
- {
- b = readByte(fl); /* Segment index */
- w = readWord(fl); /* Offset */
- len -= 3;
- /*printf("LEDATA seg %d off %02X len %Xh, looking for %d\n", b, w, len-1, codeSEGDEF);//*/
- if (b != codeSEGDEF)
- {
- readNN(len,fl); /* Skip the data */
- break; /* Next record */
- }
- if (fread(&leData[w], 1, len-1, fl) != len-1)
- {
- printf("Could not read LEDATA length %d\n", len-1);
- exit(2);
- }
- offset += len-1;
- maxLeData = std::max<uint16_t>(maxLeData, w+len-1);
- readByte(fl); /* Checksum */
- break;
- }
- default:
- readNN(len,fl); /* Just skip the lot */
- if (type == 0x8A) /* Mod end */
- {
- /* Now find all the patterns for public code symbols that
- we have found */
- for (i=firstSym; i < count; i++)
- {
- uint16_t off = keys[i].offset;
- if (off == (uint16_t)-1)
- {
- continue; /* Ignore if already done */
- }
- if (keys[i].offset > maxLeData)
- {
- printf(
- "Warning: no LEDATA for symbol #%d %s "
- "(offset %04X, max %04X)\n",
- i, keys[i].name, off, maxLeData);
- /* To make things consistant, we set the pattern for
- this symbol to nulls */
- memset(&keys[i].pat, 0, PATLEN);
- continue;
- }
- /* Copy to temp buffer so don't overrun later patterns.
- (e.g. when chopping a short pattern).
- Beware of short patterns! */
- if (off+PATLEN <= maxLeData)
- {
- /* Available pattern is >= PATLEN */
- memcpy(buf, &leData[off], PATLEN);
- }
- else
- {
- /* Short! Only copy what is available (and malloced!) */
- memcpy(buf, &leData[off], maxLeData-off);
- /* Set rest to zeroes */
- memset(&buf[maxLeData-off], 0, PATLEN-(maxLeData-off));
- }
- fixWildCards((uint8_t *)buf);
- /* Save into the hash entry. */
- memcpy(keys[i].pat, buf, PATLEN);
- keys[i].offset = (uint16_t)-1; // Flag it as done
- //printf("Saved pattern for %s\n", keys[i].name);
- }
- while (readByte(fl) == 0);
- readNN(-1,fl); /* Unget the last byte (= type) */
- lnum = 0; /* Reset index into lnames */
- segnum = 0; /* Reset index into snames */
- firstSym = count; /* Remember index of first sym this mod */
- codeLNAMES = NONE; /* Invalidate indexes for code segment */
- codeSEGDEF = NONE;
- memset(leData, 0, maxLeData); /* Clear out old junk */
- maxLeData = 0; /* No data read this module */
- }
- else if (type == 0xF1)
- {
- /* Library end record */
- return count;
- }
- }
- }
- free(leData);
- keys.clear();
- return count;
- }
|