home *** CD-ROM | disk | FTP | other *** search
/ DOS/V Power Report 1997 October / VPR9710A.ISO / BENCH / DJ1SRC_K / 105 / SYMS.C < prev    next >
C/C++ Source or Header  |  1997-05-02  |  13KB  |  575 lines

  1.  
  2. /* This is file SYMS.C */
  3. /*
  4.    ** Copyright (C) 1991 DJ Delorie, 24 Kirsten Ave, Rochester NH 03867-2954
  5.    **
  6.    ** This file is distributed under the terms listed in the document
  7.    ** "copying.dj", available from DJ Delorie at the address above.
  8.    ** A copy of "copying.dj" should accompany this file; if not, a copy
  9.    ** should be available from where this file was obtained.  This file
  10.    ** may not be distributed without a verbatim copy of "copying.dj".
  11.    **
  12.    ** This file is distributed WITHOUT ANY WARRANTY; without even the implied
  13.    ** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  14.  */
  15. /* 1997/05/01 modified by Kimio Itoh(kitoh@nn.iij4u.or.jp) 
  16.    for reduce binary size and for dead code elimination.
  17.  */
  18.  
  19. /* History:250,1 */
  20.  
  21. #include "build.h"
  22.  
  23. #if DEBUGGER
  24. extern int __pascal wild(char *pattern, char *string);
  25.  
  26. #define SYMADDR 0xa0000000L
  27.  
  28. static word32 sym_brk = SYMADDR;
  29.  
  30. word32 __pascal salloc(word32 size)
  31. {
  32.     word32 r = sym_brk;
  33.     size = (size + 3) & ~3;
  34.     sym_brk += size;
  35.     return r;
  36. }
  37.  
  38. typedef struct SYMTREE {
  39.     word32 me;
  40.     word32 nleft, nright, ndown;
  41.     word32 vleft, vright, vdown;
  42.     word32 val;
  43.     word32 type;
  44.     word32 name_len;
  45. } SYMTREE;
  46.  
  47. typedef struct FILENODE {
  48.     word32 me;
  49.     word32 next;
  50.     word32 line_list;
  51.     word32 first_addr, last_addr;
  52.     word32 name_len;
  53. } FILENODE;
  54.  
  55. typedef struct LINENODE {
  56.     word32 me;
  57.     word32 next;
  58.     word32 num;
  59.     word32 addr;
  60. } LINENODE;
  61.  
  62. static word32 symtree_root = 0;
  63. static word32 file_list = 0;
  64. static word32 nsyms = 0;
  65.  
  66. static char tmps[256];
  67. static char tmps2[256];
  68.  
  69. static word32 __cdecl symtree_add(word32 val, word32 type, char *name)
  70. {
  71.     SYMTREE s, sv, temp;
  72.     int cval;
  73.     int32 cval32;
  74.  
  75.     memset(&temp, 0, sizeof(temp));
  76.     temp.name_len = strlen(name) + 1;
  77.     temp.me = salloc(sizeof(temp) + temp.name_len);
  78.     temp.val = val;
  79.     temp.type = type;
  80.     symsput(temp.me, &temp, sizeof(temp));
  81.     symsput(temp.me + sizeof(temp), name, temp.name_len);
  82.  
  83.     if (!symtree_root) {
  84.         symtree_root = temp.me;
  85.         return temp.me;
  86.     }
  87.     s.me = symtree_root;
  88.     while (1) {
  89.         symsget(s.me, &s, sizeof(s));
  90.         symsget(s.me + sizeof(s), tmps, s.name_len);
  91.         cval = strcmp(name, tmps);
  92.         if (!cval && (!s.val || !val || (s.val == val))) {
  93.             if (val) {
  94.                 s.val = val;
  95.                 s.type = type;
  96.                 symsput(s.me, &s, sizeof(s));
  97.             }
  98.             return temp.me;
  99.         } else if (!cval) {
  100.             if (!s.ndown) {
  101.                 s.ndown = temp.me;
  102.                 symsput(s.me, &s, sizeof(s));
  103.                 break;
  104.             }
  105.             s.me = s.ndown;
  106.         } else if (cval < 0) {
  107.             if (!s.nleft) {
  108.                 s.nleft = temp.me;
  109.                 symsput(s.me, &s, sizeof(s));
  110.                 break;
  111.             }
  112.             s.me = s.nleft;
  113.         } else {
  114.             if (!s.nright) {
  115.                 s.nright = temp.me;
  116.                 symsput(s.me, &s, sizeof(s));
  117.                 break;
  118.             }
  119.             s.me = s.nright;
  120.         }
  121.     }
  122.     nsyms++;
  123.  
  124.     sv.me = symtree_root;
  125.     while (1) {
  126.         symsget(sv.me, &sv, sizeof(sv));
  127.         if (sv.me == temp.me)
  128.             return temp.me;
  129.         cval32 = val - sv.val;
  130.         if (!cval32) {
  131.             if (!sv.vdown) {
  132.                 sv.vdown = temp.me;
  133.                 symsput(sv.me, &sv, sizeof(sv));
  134.                 break;
  135.             }
  136.             sv.me = sv.vdown;
  137.         } else if (cval32 < 0) {
  138.             if (!sv.vleft) {
  139.                 sv.vleft = temp.me;
  140.                 symsput(sv.me, &sv, sizeof(sv));
  141.                 break;
  142.             }
  143.             sv.me = sv.vleft;
  144.         } else {
  145.             if (!sv.vright) {
  146.                 sv.vright = temp.me;
  147.                 symsput(sv.me, &sv, sizeof(sv));
  148.                 break;
  149.             }
  150.             sv.me = sv.vright;
  151.         }
  152.     }
  153.     return temp.me;
  154. }
  155.  
  156. typedef struct SYM_ENTRY {
  157.     word32 string_off;
  158.     word8 type;
  159.     word8 other;
  160.     word16 desc;
  161.     word32 val;
  162. } SYM_ENTRY;
  163.  
  164. static void __cdecl get_string(FILE * f, word32 where)
  165. {
  166.     char *cp;
  167.     if (where != ftell(f))
  168.         fseek(f, where, 0);
  169.     cp = tmps2;
  170.     do {
  171.         *cp++ = fgetc(f);
  172.     } while (cp[-1]);
  173. }
  174.  
  175. void __pascal syms_init(char *fname)
  176. {
  177.     GNU_AOUT header;
  178.     int fd, per, oldper = -1;
  179.     word32 nsyms, i;
  180.     FILE *sfd;
  181.     word32 sfd_base;
  182.     SYM_ENTRY sym;
  183.     char *cp;
  184.     word32 last_dot_o = 0;
  185.     FILENODE filen;
  186.     LINENODE linen;
  187.  
  188.     filen.me = linen.me = 0;
  189.  
  190.     fd = open(fname, O_RDONLY | O_BINARY);
  191.     sfd = fopen(fname, "rb");
  192.  
  193.     read(fd, &header, sizeof(header));
  194.     if ((header.info & 0xffff) == 0x14c) {
  195.         lseek(fd, 0xa8L, 0);
  196.         read(fd, &header, sizeof(header));
  197.         lseek(fd, 0xa8 + sizeof(header) + header.tsize + header.dsize, 0);
  198.     } else if (((header.info & 0xffff) == 0x10b) || ((header.info & 0xffff) == 0x0107)) {
  199.         lseek(fd, sizeof(header) + header.tsize + header.dsize + header.txrel + header.dtrel, 0);
  200.     } else {
  201.         nsyms = 0;
  202.         return;
  203.     }
  204.  
  205.     printf("Reading symbols...   0%%");
  206.     fflush(stdout);
  207.  
  208.     nsyms = header.symsize / sizeof(SYM_ENTRY);
  209.  
  210.     fseek(sfd, tell(fd) + header.symsize, 0);
  211.     sfd_base = ftell(sfd);
  212.  
  213.     for (i = 0; i < nsyms; i++) {
  214.         if (nsyms > 1)
  215.             per = (int)(i * 100L / (nsyms - 1));
  216.         else
  217.             per = 100;
  218.         if (per != oldper) {
  219.             printf("\b\b\b\b%3d%%", per);
  220.             fflush(stdout);
  221.             oldper = per;
  222.         }
  223.         read(fd, &sym, sizeof(sym));
  224.         if (sym.string_off)
  225.             get_string(sfd, sfd_base + sym.string_off);
  226.         switch (sym.type) {
  227.         case N_TEXT:
  228.         case N_TEXT | N_EXT:
  229.             cp = tmps2;
  230.             cp += strlen(cp) - 2;
  231.             if (!strcmp(cp, ".o")) {
  232.                 last_dot_o = sym.val;
  233.                 if (filen.me && !filen.last_addr) {
  234.                     filen.last_addr = last_dot_o - 1;
  235.                     symsput(filen.me, &filen, sizeof(filen));
  236.                 }
  237.                 break;
  238.             }
  239.             if (!strcmp(cp, "d."))    /* as in gcc_compiled. */
  240.                 break;
  241.         case N_DATA:
  242.         case N_DATA | N_EXT:
  243.         case N_ABS:
  244.         case N_ABS | N_EXT:
  245.         case N_BSS:
  246.         case N_BSS | N_EXT:
  247.         case N_FN:
  248.         case N_SETV:
  249.         case N_SETV | N_EXT:
  250.         case N_SETA:
  251.         case N_SETA | N_EXT:
  252.         case N_SETT:
  253.         case N_SETT | N_EXT:
  254.         case N_SETD:
  255.         case N_SETD | N_EXT:
  256.         case N_SETB:
  257.         case N_SETB | N_EXT:
  258.         case N_INDR:
  259.         case N_INDR | N_EXT:
  260.             if (sym.string_off)
  261.                 symtree_add(sym.val, sym.type, tmps2);
  262.             break;
  263.         case N_SO:
  264.             memset(&filen, 0, sizeof(FILENODE));
  265.             filen.name_len = strlen(tmps2) + 1;
  266.             filen.me = salloc(sizeof(FILENODE) + filen.name_len);
  267.             symsput(filen.me + sizeof(filen), tmps2, filen.name_len);
  268.             filen.next = file_list;
  269.             file_list = filen.me;
  270.             filen.first_addr = last_dot_o;
  271.             symsput(filen.me, &filen, sizeof(filen));
  272.             break;
  273.         case N_SLINE:
  274.             memset(&linen, 0, sizeof(linen));
  275.             linen.me = salloc(sizeof(LINENODE));
  276.             linen.next = filen.line_list;
  277.             filen.line_list = linen.me;
  278.             linen.num = sym.desc;
  279.             linen.addr = sym.val;
  280.             symsput(linen.me, &linen, sizeof(linen));
  281.             symsput(filen.me, &filen, sizeof(filen));
  282.             break;
  283.         }
  284.     }
  285.     printf(" %ld symbol%s read\n", nsyms, nsyms == 1 ? "" : "s");
  286.     return;
  287. }
  288.  
  289. #define Ofs(n) ((int)&(((TSS *)0)->n))
  290.  
  291. struct regs_t {
  292.     char *name;
  293.     int size;
  294.     int ofs;
  295. };
  296.  
  297. struct regs_t regs[] =
  298. {
  299.  
  300.     {"%eip", 4, Ofs(tss_eip)},
  301.     {"%eflags", 4, Ofs(tss_eflags)},
  302.     {"%eax", 4, Ofs(tss_eax)},
  303.     {"%ebx", 4, Ofs(tss_ebx)},
  304.     {"%ecx", 4, Ofs(tss_ecx)},
  305.     {"%edx", 4, Ofs(tss_edx)},
  306.     {"%esp", 4, Ofs(tss_esp)},
  307.     {"%ebp", 4, Ofs(tss_ebp)},
  308.     {"%esi", 4, Ofs(tss_esi)},
  309.     {"%edi", 4, Ofs(tss_edi)},
  310.     {"%ax", 2, Ofs(tss_eax)},
  311.     {"%bx", 2, Ofs(tss_ebx)},
  312.     {"%cx", 2, Ofs(tss_ecx)},
  313.     {"%dx", 2, Ofs(tss_edx)},
  314.     {"%ah", 1, Ofs(tss_eax) + 1},
  315.     {"%bh", 1, Ofs(tss_ebx) + 1},
  316.     {"%ch", 1, Ofs(tss_ecx) + 1},
  317.     {"%dh", 1, Ofs(tss_edx) + 1},
  318.     {"%al", 1, Ofs(tss_eax)},
  319.     {"%bl", 1, Ofs(tss_ebx)},
  320.     {"%cl", 1, Ofs(tss_ecx)},
  321.     {"%dl", 1, Ofs(tss_edx)},
  322.     {0, 0, 0}
  323. };
  324.  
  325. int undefined_symbol = 0;
  326.  
  327. word32 __pascal syms_name2val(char *name)
  328. {
  329.     SYMTREE s;
  330.     int cval, idx, sign = 1, i;
  331.     word32 v;
  332.     char *cp;
  333.  
  334.     undefined_symbol = 0;
  335.  
  336.     idx = 0;
  337.     sscanf(name, "%s", name);
  338.  
  339.     if (!name[0])
  340.         return 0;
  341.  
  342.     if (name[0] == '-') {
  343.         sign = -1;
  344.         name++;
  345.     } else if (name[0] == '+') {
  346.         name++;
  347.     }
  348.     if (isdigit(name[0])) {
  349.         if (sign == -1)
  350.             return -strtol(name, 0, 16);
  351.         return strtol(name, 0, 16);
  352.     }
  353.     cp = strpbrk(name, "+-");
  354.     idx = cp ? (cp - name) : strlen(name);
  355.  
  356.     if (name[0] == '%') {        /* register */
  357.         for (i = 0; regs[i].name; i++)
  358.             if (!strncmp(name, regs[i].name, idx)) {
  359.                 switch (regs[i].size) {
  360.                 case 1:
  361.                     v = *(word8 *) ((word8 *) tss_ptr + regs[i].ofs);
  362.                     break;
  363.                 case 2:
  364.                     v = *(word16 *) ((word8 *) tss_ptr + regs[i].ofs);
  365.                     break;
  366.                 case 4:
  367.                     v = *(word32 *) ((word8 *) tss_ptr + regs[i].ofs);
  368.                     break;
  369.                 }
  370.                 return v + syms_name2val(name + idx);
  371.             }
  372.     }
  373.     for (i = 0; i < idx; i++)
  374.         if (name[i] == '#') {
  375.             FILENODE f;
  376.             LINENODE l;
  377.             int lnum;
  378.             sscanf(name + i + 1, "%d", &lnum);
  379.             for (f.me = file_list; f.me; f.me = f.next) {
  380.                 symsget(f.me, &f, sizeof(f));
  381.                 symsget(f.me + sizeof(f), tmps, f.name_len);
  382.                 if (!strncmp(name, tmps, i) && !tmps[i]) {
  383.                     for (l.me = f.line_list; l.me; l.me = l.next) {
  384.                         symsget(l.me, &l, sizeof(l));
  385.                         if (l.num == lnum)
  386.                             return l.addr + syms_name2val(name + idx);
  387.                     }
  388.                     printf("undefined line number %.*s\n", idx, name);
  389.                     undefined_symbol = 1;
  390.                     return 0;
  391.                 }
  392.             }
  393.             printf("Undefined file name %.*s\n", i, name);
  394.             undefined_symbol = 1;
  395.             return 0;
  396.         }
  397.     s.me = symtree_root;
  398.     while (s.me) {
  399.         symsget(s.me, &s, sizeof(s));
  400.         symsget(s.me + sizeof(s), tmps, s.name_len);
  401.         cval = strncmp(name, tmps, idx);
  402.         if (!cval && tmps[idx])
  403.             cval = -1;
  404.         if (!cval)
  405.             return s.val * sign + syms_name2val(name + idx);
  406.         else if (cval < 0)
  407.             s.me = s.nleft;
  408.         else
  409.             s.me = s.nright;
  410.     }
  411.     s.me = symtree_root;
  412.     while (s.me) {
  413.         symsget(s.me, &s, sizeof(s));
  414.         symsget(s.me + sizeof(s), tmps, s.name_len);
  415.         cval = (tmps[0] == '_') ? strncmp(name, tmps + 1, idx) : ('_' - tmps[0]);
  416.         if (!cval && tmps[idx + 1])
  417.             cval = -1;
  418.         if (!cval)
  419.             return s.val * sign + syms_name2val(name + idx);
  420.         else if (cval < 0)
  421.             s.me = s.nleft;
  422.         else
  423.             s.me = s.nright;
  424.     }
  425.     printf("Undefined symbol %.*s\n", idx, name);
  426.     undefined_symbol = 1;
  427.     return 0;
  428. }
  429.  
  430. static char noname_buf[11];
  431.  
  432. char *__pascal syms_val2name(word32 val, word32 * delta)
  433. {
  434.     SYMTREE s, lasts;
  435.  
  436.     if (delta)
  437.         *delta = 0;
  438.     lasts.me = 0;
  439.     s.me = symtree_root;
  440.     while (s.me) {
  441.         symsget(s.me, &s, sizeof(s));
  442.         if (s.val <= val)
  443.             lasts.me = s.me;
  444.         if (val == s.val) {
  445.             while (s.vdown)
  446.                 symsget(s.vdown, &s, sizeof(s));
  447.             symsget(s.me + sizeof(s), tmps2, s.name_len);
  448.             return tmps2;
  449.         } else if (val < s.val)
  450.             s.me = s.vleft;
  451.         else
  452.             s.me = s.vright;
  453.     }
  454.     if (lasts.me) {
  455.         symsget(lasts.me, &lasts, sizeof(lasts));
  456.         while (lasts.vdown)
  457.             symsget(lasts.vdown, &lasts, sizeof(lasts));
  458.         symsget(lasts.me + sizeof(lasts), tmps2, lasts.name_len);
  459.         if (!strcmp(tmps2, "_etext"))
  460.             goto noname;
  461.         if (!strcmp(tmps2, "_end"))
  462.             goto noname;
  463.         if (delta)
  464.             *delta = val - lasts.val;
  465.         return tmps2;
  466.     }
  467.   noname:
  468.     sprintf(noname_buf, "%#lx", val);
  469.     return noname_buf;
  470. }
  471.  
  472. char *__pascal syms_val2line(word32 val, int *lineret, int exact)
  473. {
  474.     FILENODE filen;
  475.     LINENODE linen, closest;
  476.     closest.me = 0;
  477.     for (filen.me = file_list; filen.me; filen.me = filen.next) {
  478.         symsget(filen.me, &filen, sizeof(filen));
  479.         if ((val <= filen.last_addr) && (val >= filen.first_addr)) {
  480.             for (linen.me = filen.line_list; linen.me; linen.me = linen.next) {
  481.                 symsget(linen.me, &linen, sizeof(linen));
  482.                 if (val == linen.addr) {
  483.                     *lineret = (int)linen.num;
  484.                     symsget(filen.me + sizeof(filen), tmps2, filen.name_len);
  485.                     return tmps2;
  486.                 }
  487.                 if (val > linen.addr) {
  488.                     if (!closest.me)
  489.                         closest.me = linen.me;
  490.                     else if (closest.addr < linen.addr)
  491.                         closest.me = linen.me;
  492.                 }
  493.             }
  494.             if (closest.me && !exact) {
  495.                 symsget(closest.me, &closest, sizeof(closest));
  496.                 *lineret = (int)closest.num;
  497.                 symsget(filen.me + sizeof(filen), tmps2, filen.name_len);
  498.                 return tmps2;
  499.             }
  500.         }
  501.     }
  502.     return 0;
  503. }
  504.  
  505. static char __fastcall type2char(int type)
  506. {
  507.     switch (type) {
  508.     case N_TEXT:
  509.         return 't';
  510.     case N_TEXT | N_EXT:
  511.         return 'T';
  512.     case N_DATA:
  513.         return 'd';
  514.     case N_DATA | N_EXT:
  515.         return 'D';
  516.     case N_BSS:
  517.         return 'b';
  518.     case N_BSS | N_EXT:
  519.         return 'B';
  520.     default:
  521.         return ' ';
  522.     }
  523. }
  524.  
  525. static int linecnt, quit_list;
  526.  
  527. static void __pascal syms_listwild2(word32 s_pos, char *pattern)
  528. {
  529.     SYMTREE s;
  530.     char *name;
  531.     int lnum;
  532.     s.me = s_pos;
  533.     if (!s.me || quit_list)
  534.         return;
  535.     symsget(s.me, &s, sizeof(s));
  536.     syms_listwild2(s.vleft, pattern);
  537.     if (quit_list)
  538.         return;
  539.     symsget(s.me + sizeof(s), tmps, s.name_len);
  540.     if (wild(pattern, tmps)) {
  541.         if (++linecnt > 20) {
  542.             printf("--- More ---");
  543.             switch (getch()) {
  544.             case ' ':
  545.                 linecnt = 0;
  546.                 break;
  547.             case 13:
  548.                 linecnt--;
  549.                 break;
  550.             case 'q':
  551.                 quit_list = 1;
  552.                 return;
  553.             }
  554.             printf("\r            \r");
  555.         }
  556.         printf("%#08lx %c %s", s.val, type2char((int)s.type), tmps);
  557.         name = syms_val2line(s.val, &lnum, 0);
  558.         if (name)
  559.             printf(", line %d of %s", lnum, name);
  560.         mputchar('\n');
  561.     }
  562.     syms_listwild2(s.vdown, pattern);
  563.     if (quit_list)
  564.         return;
  565.     syms_listwild2(s.vright, pattern);
  566. }
  567.  
  568. void __fastcall syms_listwild(char *pattern)
  569. {
  570.     quit_list = linecnt = 0;
  571.     syms_listwild2(symtree_root, pattern);
  572. }
  573.  
  574. #endif
  575.