home *** CD-ROM | disk | FTP | other *** search
/ Stars of Shareware: Programmierung / SOURCE.mdf / programm / msdos / c / djgpp / go32 / syms.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-30  |  15.0 KB  |  689 lines

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