date and time created 83/08/11 20:50:29 by sam
[unix-history] / usr / src / old / dbx / object.c
index 36a732c..7d8e377 100644 (file)
@@ -1,6 +1,6 @@
 /* Copyright (c) 1982 Regents of the University of California */
 
 /* Copyright (c) 1982 Regents of the University of California */
 
-static char sccsid[] = "@(#)object.c 1.7 %G%";
+static char sccsid[] = "@(#)object.c 1.11 %G%";
 
 /*
  * Object code interface, mainly for extraction of symbolic information.
 
 /*
  * Object code interface, mainly for extraction of symbolic information.
@@ -38,10 +38,12 @@ private Language curlang;
 private Symbol curmodule;
 private Symbol curparam;
 private Boolean warned;
 private Symbol curmodule;
 private Symbol curparam;
 private Boolean warned;
+private Symbol curcomm;
+private Symbol commchain;
+private Boolean strip_ = false;
 
 private Filetab *filep;
 private Linetab *linep, *prevlinep;
 
 private Filetab *filep;
 private Linetab *linep, *prevlinep;
-private Address curfaddr;
 
 #define curfilename() (filep-1)->filename
 
 
 #define curfilename() (filep-1)->filename
 
@@ -54,6 +56,8 @@ private Address curfaddr;
 private Symbol curblock;
 private Symbol blkstack[MAXBLKDEPTH];
 private Integer curlevel;
 private Symbol curblock;
 private Symbol blkstack[MAXBLKDEPTH];
 private Integer curlevel;
+private Integer bnum, nesting;
+private Address addrstk[MAXBLKDEPTH];
 
 #define enterblock(b) { \
     blkstack[curlevel] = curblock; \
 
 #define enterblock(b) { \
     blkstack[curlevel] = curblock; \
@@ -125,17 +129,19 @@ String file;
     nlhdr.nsyms = hdr.a_syms / sizeof(nlist);
     nlhdr.nfiles = nlhdr.nsyms;
     nlhdr.nlines = nlhdr.nsyms;
     nlhdr.nsyms = hdr.a_syms / sizeof(nlist);
     nlhdr.nfiles = nlhdr.nsyms;
     nlhdr.nlines = nlhdr.nsyms;
-    lseek(f, (long) N_STROFF(hdr), 0);
-    read(f, &(nlhdr.stringsize), sizeof(nlhdr.stringsize));
-    nlhdr.stringsize -= 4;
-    stringtab = newarr(char, nlhdr.stringsize);
-    read(f, stringtab, nlhdr.stringsize);
-    allocmaps(nlhdr.nfiles, nlhdr.nlines);
-    lseek(f, (long) N_SYMOFF(hdr), 0);
-    readsyms(f);
-    ordfunctab();
-    setnlines();
-    setnfiles();
+    if (nlhdr.nsyms > 0) {
+       lseek(f, (long) N_STROFF(hdr), 0);
+       read(f, &(nlhdr.stringsize), sizeof(nlhdr.stringsize));
+       nlhdr.stringsize -= 4;
+       stringtab = newarr(char, nlhdr.stringsize);
+       read(f, stringtab, nlhdr.stringsize);
+       allocmaps(nlhdr.nfiles, nlhdr.nlines);
+       lseek(f, (long) N_SYMOFF(hdr), 0);
+       readsyms(f);
+       ordfunctab();
+       setnlines();
+       setnfiles();
+    }
     close(f);
 }
 
     close(f);
 }
 
@@ -161,9 +167,28 @@ Fileid f;
        index = np->n_un.n_strx;
        if (index != 0) {
            name = &stringtab[index - 4];
        index = np->n_un.n_strx;
        if (index != 0) {
            name = &stringtab[index - 4];
+           /*
+             *  if the program contains any .f files a trailing _ is stripped
+                    *  from the name on the assumption it was added by the compiler.
+            *  This only affects names that follow the sdb N_SO entry with
+             *  the .f name. 
+             */
+            if (strip_ and name[0] != '\0' ) {
+               register char *p;
+
+               p = name;
+               while (*p != '\0') {
+                   ++p;
+               }
+               --p;
+               if (*p == '-') {
+                   *p = '\0';
+               }
+            }
+
        } else {
            name = nil;
        } else {
            name = nil;
-       }
+       } 
        /*
         * assumptions:
         *      not an N_STAB   ==> name != nil
        /*
         * assumptions:
         *      not an N_STAB   ==> name != nil
@@ -171,6 +196,7 @@ Fileid f;
         *      name[0] != '_'  ==> filename or invisible
         *
         * The "-lg" signals the beginning of global loader symbols.
         *      name[0] != '_'  ==> filename or invisible
         *
         * The "-lg" signals the beginning of global loader symbols.
+         *
         */
        if ((np->n_type&N_STAB) != 0) {
            enter_nl(name, np);
         */
        if ((np->n_type&N_STAB) != 0) {
            enter_nl(name, np);
@@ -193,6 +219,9 @@ Fileid f;
            check_filename(name);
        }
     }
            check_filename(name);
        }
     }
+    if (not afterlg) {
+       panic("not linked for debugging, use \"cc -g ...\"");
+    }
     dispose(namelist);
 }
 
     dispose(namelist);
 }
 
@@ -204,6 +233,7 @@ private initsyms()
 {
     curblock = nil;
     curlevel = 0;
 {
     curblock = nil;
     curlevel = 0;
+    nesting = 0;
     if (progname == nil) {
        progname = strdup(objname);
        if (rindex(progname, '/') != nil) {
     if (progname == nil) {
        progname = strdup(objname);
        if (rindex(progname, '/') != nil) {
@@ -216,14 +246,15 @@ private initsyms()
     program = insert(identname(progname, true));
     program->class = PROG;
     program->symvalue.funcv.beginaddr = 0;
     program = insert(identname(progname, true));
     program->class = PROG;
     program->symvalue.funcv.beginaddr = 0;
+    program->symvalue.funcv.inline = false;
+    newfunc(program, codeloc(program));
     findbeginning(program);
     findbeginning(program);
-    newfunc(program);
     enterblock(program);
     curmodule = program;
     t_boolean = maketype("$boolean", 0L, 1L);
     t_int = maketype("$integer", 0x80000000L, 0x7fffffffL);
     t_char = maketype("$char", 0L, 127L);
     enterblock(program);
     curmodule = program;
     t_boolean = maketype("$boolean", 0L, 1L);
     t_int = maketype("$integer", 0x80000000L, 0x7fffffffL);
     t_char = maketype("$char", 0L, 127L);
-    t_real = maketype("$real", 4L, 0L);
+    t_real = maketype("$real", 8L, 0L);
     t_nil = maketype("$nil", 0L, 0L);
 }
 
     t_nil = maketype("$nil", 0L, 0L);
 }
 
@@ -249,8 +280,8 @@ String name;
 register struct nlist *np;
 {
     register Symbol s;
 register struct nlist *np;
 {
     register Symbol s;
-    String mname, suffix;
     register Name n, nn;
     register Name n, nn;
+    char buf[100];
 
     s = nil;
     if (name == nil) {
 
     s = nil;
     if (name == nil) {
@@ -259,14 +290,44 @@ register struct nlist *np;
        n = identname(name, true);
     }
     switch (np->n_type) {
        n = identname(name, true);
     }
     switch (np->n_type) {
+       /*
+        * Build a symbol for the FORTRAN common area.  All GSYMS that follow
+        * will be chained in a list with the head kept in common.offset, and
+        * the tail in common.chain.
+        */
+       case N_BCOMM:
+           if (curcomm) {
+               curcomm->symvalue.common.chain = commchain;
+           }
+           curcomm = lookup(n);
+           if (curcomm == nil) {
+               curcomm = insert(n);
+               curcomm->class = COMMON;
+               curcomm->block = curblock;
+               curcomm->level = program->level;
+               curcomm->symvalue.common.chain = nil;
+           }
+           commchain = curcomm->symvalue.common.chain;
+           break;
+
+       case N_ECOMM:
+           if (curcomm) {
+               curcomm->symvalue.common.chain = commchain;
+               curcomm = nil;
+           }
+           break;
+
        case N_LBRAC:
        case N_LBRAC:
-           s = symbol_alloc();
-           s->class = PROC;
-           enterblock(s);
+           ++nesting;
+           addrstk[nesting] = (linep - 1)->addr;
            break;
 
        case N_RBRAC:
            break;
 
        case N_RBRAC:
-           exitblock();
+           if (addrstk[nesting] == NOADDR) {
+               exitblock();
+               newfunc(curblock, (linep - 1)->addr);
+           }
+           --nesting;
            break;
 
        case N_SLINE:
            break;
 
        case N_SLINE:
@@ -274,48 +335,10 @@ register struct nlist *np;
            break;
 
        /*
            break;
 
        /*
-        * Compilation unit.  C associates scope with filenames
-        * so we treat them as "modules".  The filename without
-        * the suffix is used for the module name.
-        *
-        * Because there is no explicit "end-of-block" mark in
-        * the object file, we must exit blocks for the current
-        * procedure and module.
+        * Source files.
         */
        case N_SO:
         */
        case N_SO:
-           mname = strdup(ident(n));
-           if (rindex(mname, '/') != nil) {
-               mname = rindex(mname, '/') + 1;
-           }
-           suffix = rindex(mname, '.');
-           curlang = findlanguage(suffix);
-           if (suffix != nil) {
-               *suffix = '\0';
-           }
-           if (curblock->class != PROG) {
-               exitblock();
-               if (curblock->class != PROG) {
-                   exitblock();
-               }
-           }
-           nn = identname(mname, true);
-           if (curmodule == nil or curmodule->name != nn) {
-               s = insert(nn);
-               s->class = MODULE;
-               s->symvalue.funcv.beginaddr = 0;
-               findbeginning(s);
-           } else {
-               s = curmodule;
-           }
-           s->language = curlang;
-           enterblock(s);
-           curmodule = s;
-           if (program->language == nil) {
-               program->language = curlang;
-           }
-           warned = false;
-           enterfile(ident(n), (Address) np->n_value);
-           bzero(typetable, sizeof(typetable));
+           enterSourceModule(n, (Address) np->n_value);
            break;
 
        /*
            break;
 
        /*
@@ -336,16 +359,12 @@ register struct nlist *np;
        case N_PSYM:
        case N_LSYM:
        case N_SSYM:
        case N_PSYM:
        case N_LSYM:
        case N_SSYM:
+       case N_LENG:
            if (index(name, ':') == nil) {
                if (not warned) {
                    warned = true;
            if (index(name, ':') == nil) {
                if (not warned) {
                    warned = true;
-                   /*
-                    * Shouldn't do this if user might be typing.
-                    *
                    warning("old style symbol information found in \"%s\"",
                        curfilename());
                    warning("old style symbol information found in \"%s\"",
                        curfilename());
-                    *
-                    */
                }
            } else {
                entersym(name, np);
                }
            } else {
                entersym(name, np);
@@ -355,18 +374,13 @@ register struct nlist *np;
        case N_PC:
            break;
 
        case N_PC:
            break;
 
-       case N_LENG:
        default:
        default:
-           /*
-            * Should complain out this, obviously the wrong symbol format.
-            *
+           printf("warning:  stab entry unrecognized: ");
            if (name != nil) {
            if (name != nil) {
-               printf("%s, ", name);
+               printf("name %s,", name);
            }
            }
-           printf("ntype %2x, desc %x, value %x\n",
+           printf("ntype %2x, desc %x, value %x'\n",
                np->n_type, np->n_desc, np->n_value);
                np->n_type, np->n_desc, np->n_value);
-            *
-            */
            break;
     }
 }
            break;
     }
 }
@@ -381,13 +395,14 @@ String name;
 register struct nlist *np;
 {
     register Name n;
 register struct nlist *np;
 {
     register Name n;
-    register Symbol t;
+    register Symbol t, u;
 
     if (not streq(name, "end")) {
        n = identname(name, true);
        if ((np->n_type&N_TYPE) == N_TEXT) {
            find(t, n) where
 
     if (not streq(name, "end")) {
        n = identname(name, true);
        if ((np->n_type&N_TYPE) == N_TEXT) {
            find(t, n) where
-               t->level == program->level and isblock(t)
+               t->level == program->level and
+               (t->class == PROC or t->class == FUNC)
            endfind(t);
            if (t == nil) {
                t = insert(n);
            endfind(t);
            if (t == nil) {
                t = insert(n);
@@ -397,27 +412,57 @@ register struct nlist *np;
                t->block = curblock;
                t->level = program->level;
                t->symvalue.funcv.src = false;
                t->block = curblock;
                t->level = program->level;
                t->symvalue.funcv.src = false;
+               t->symvalue.funcv.inline = false;
            }
            t->symvalue.funcv.beginaddr = np->n_value;
            }
            t->symvalue.funcv.beginaddr = np->n_value;
-           newfunc(t);
+           newfunc(t, codeloc(t));
            findbeginning(t);
            findbeginning(t);
-       } else {
+       } else if ((np->n_type&N_TYPE) == N_BSS) {
            find(t, n) where
            find(t, n) where
-               t->class == VAR and t->level == program->level
+               t->class == COMMON
            endfind(t);
            endfind(t);
-           if (t == nil) {
-               t = insert(n);
-               t->language = findlanguage(".s");
-               t->class = VAR;
-               t->type = t_int;
-               t->block = curblock;
-               t->level = program->level;
+           if (t != nil) {
+               u = (Symbol) t->symvalue.common.offset;
+               while (u != nil) {
+                   u->symvalue.offset = u->symvalue.common.offset+np->n_value;
+                   u = u->symvalue.common.chain;
+               }
+            } else {
+               check_var(np, n);
            }
            }
-           t->symvalue.offset = np->n_value;
+        } else {
+           check_var(np, n);
        }
     }
 }
 
        }
     }
 }
 
+/*
+ * Check to see if a namelist entry refers to a variable.
+ * If not, create a variable for the entry.  In any case,
+ * set the offset of the variable according to the value field
+ * in the entry.
+ */
+
+private check_var(np, n)
+struct nlist *np;
+register Name n;
+{
+    register Symbol t;
+
+    find(t, n) where
+       t->class == VAR and t->level == program->level
+    endfind(t);
+    if (t == nil) {
+       t = insert(n);
+       t->language = findlanguage(".s");
+       t->class = VAR;
+       t->type = t_int;
+       t->level = program->level;
+    }
+    t->block = curblock;
+    t->symvalue.offset = np->n_value;
+}
+
 /*
  * Check to see if a local _name is known in the current scope.
  * If not then enter it.
 /*
  * Check to see if a local _name is known in the current scope.
  * If not then enter it.
@@ -442,8 +487,9 @@ register struct nlist *np;
        if ((np->n_type&N_TYPE) == N_TEXT) {
            t->class = FUNC;
            t->symvalue.funcv.src = false;
        if ((np->n_type&N_TYPE) == N_TEXT) {
            t->class = FUNC;
            t->symvalue.funcv.src = false;
+           t->symvalue.funcv.inline = false;
            t->symvalue.funcv.beginaddr = np->n_value;
            t->symvalue.funcv.beginaddr = np->n_value;
-           newfunc(t);
+           newfunc(t, codeloc(t));
            findbeginning(t);
        } else {
            t->class = VAR;
            findbeginning(t);
        } else {
            t->class = VAR;
@@ -488,6 +534,88 @@ String name;
     }
 }
 
     }
 }
 
+/*
+ * Check to see if a symbol is about to be defined within an unnamed block.
+ * If this happens, we create a procedure for the unnamed block, make it
+ * "inline" so that tracebacks don't associate an activation record with it,
+ * and enter it into the function table so that it will be detected
+ * by "whatblock".
+ */
+
+private unnamed_block()
+{
+    register Symbol s;
+    static int bnum = 0;
+    char buf[100];
+
+    ++bnum;
+    sprintf(buf, "$b%d", bnum);
+    s = insert(identname(buf, false));
+    s->class = PROG;
+    s->symvalue.funcv.src = false;
+    s->symvalue.funcv.inline = true;
+    s->symvalue.funcv.beginaddr = addrstk[nesting];
+    enterblock(s);
+    newfunc(s, addrstk[nesting]);
+    addrstk[nesting] = NOADDR;
+}
+
+/*
+ * Compilation unit.  C associates scope with filenames
+ * so we treat them as "modules".  The filename without
+ * the suffix is used for the module name.
+ *
+ * Because there is no explicit "end-of-block" mark in
+ * the object file, we must exit blocks for the current
+ * procedure and module.
+ */
+
+private enterSourceModule(n, addr)
+Name n;
+Address addr;
+{
+    register Symbol s;
+    Name nn;
+    String mname, suffix;
+
+    mname = strdup(ident(n));
+    if (rindex(mname, '/') != nil) {
+       mname = rindex(mname, '/') + 1;
+    }
+    suffix = rindex(mname, '.');
+    curlang = findlanguage(suffix);
+    if (curlang == findlanguage(".f")) {
+       strip_ = true;
+    } 
+    if (suffix != nil) {
+       *suffix = '\0';
+    }
+    if (curblock->class != PROG) {
+       exitblock();
+       if (curblock->class != PROG) {
+           exitblock();
+       }
+    }
+    nn = identname(mname, true);
+    if (curmodule == nil or curmodule->name != nn) {
+       s = insert(nn);
+       s->class = MODULE;
+       s->symvalue.funcv.beginaddr = 0;
+       findbeginning(s);
+    } else {
+       s = curmodule;
+    }
+    s->language = curlang;
+    enterblock(s);
+    curmodule = s;
+    if (program->language == nil) {
+       program->language = curlang;
+    }
+    warned = false;
+    enterfile(ident(n), addr);
+    bzero(typetable, sizeof(typetable));
+}
+
 /*
  * Put an nlist into the symbol table.
  * If it's already there just add the associated information.
 /*
  * Put an nlist into the symbol table.
  * If it's already there just add the associated information.
@@ -541,6 +669,10 @@ struct nlist *np;
        s = insert(n);
     }
 
        s = insert(n);
     }
 
+    if (nesting > 0 and addrstk[nesting] != NOADDR) {
+       unnamed_block();
+    }
+
     /*
      * Default attributes.
      */
     /*
      * Default attributes.
      */
@@ -612,8 +744,9 @@ struct nlist *np;
            curparam = s;
            if (isnew) {
                s->symvalue.funcv.src = false;
            curparam = s;
            if (isnew) {
                s->symvalue.funcv.src = false;
+               s->symvalue.funcv.inline = false;
                s->symvalue.funcv.beginaddr = np->n_value;
                s->symvalue.funcv.beginaddr = np->n_value;
-               newfunc(s);
+               newfunc(s, codeloc(s));
                findbeginning(s);
            }
            break;
                findbeginning(s);
            }
            break;
@@ -627,8 +760,23 @@ struct nlist *np;
            s->block = curmodule;
            break;
 
            s->block = curmodule;
            break;
 
+/*
+ *  keep global BSS variables chained so can resolve when get the start
+ *  of common; keep the list in order so f77 can display all vars in a COMMON
+*/
        case 'V':       /* own variable */
            s->level = 2;
        case 'V':       /* own variable */
            s->level = 2;
+           if (curcomm) {
+             if (commchain != nil) {
+                 commchain->symvalue.common.chain = s;
+             }                   
+             else {
+                 curcomm->symvalue.common.offset = (int) s;
+             }                   
+              commchain = s;
+              s->symvalue.common.offset = np->n_value;
+              s->symvalue.common.chain = nil;
+           }
            break;
 
        case 'r':       /* register variable */
            break;
 
        case 'r':       /* register variable */
@@ -718,14 +866,63 @@ Symbol type;
        }
        t->language = curlang;
        t->level = b;
        }
        t->language = curlang;
        t->level = b;
+       t->block = curblock;
        class = *curchar++;
        switch (class) {
        class = *curchar++;
        switch (class) {
+
            case 'r':
                t->class = RANGE;
                t->type = constype(nil);
                skipchar(curchar, ';');
            case 'r':
                t->class = RANGE;
                t->type = constype(nil);
                skipchar(curchar, ';');
-               t->symvalue.rangev.lower = getint();
+                /* some letters indicate a dynamic bound, ie what follows
+                   is the offset from the fp which contains the bound; this will
+                   need a different encoding when pc a['A'..'Z'] is
+                   added; J is a special flag to handle fortran a(*) bounds
+                */
+               switch(*curchar) {
+                       case 'A':
+                               t->symvalue.rangev.lowertype = R_ARG;
+                               curchar++;
+                               break;
+
+                       case 'T':
+                               t->symvalue.rangev.lowertype = R_TEMP;
+                               curchar++;
+                               break;
+
+                       case 'J': 
+                               t->symvalue.rangev.lowertype = R_ADJUST;
+                               curchar++;
+                               break;
+
+                       default:
+                                t->symvalue.rangev.lowertype = R_CONST;
+                                break;
+
+               }
+               t->symvalue.rangev.lower = getint();
                skipchar(curchar, ';');
                skipchar(curchar, ';');
+               switch(*curchar) {
+                       case 'A':
+                               t->symvalue.rangev.uppertype = R_ARG;
+                               curchar++;
+                               break;
+
+                       case 'T':
+                               t->symvalue.rangev.uppertype = R_TEMP;
+                               curchar++;
+                               break;
+
+                       case 'J': 
+                               t->symvalue.rangev.uppertype = R_ADJUST;
+                               curchar++;
+                               break;
+
+                       default:
+                                t->symvalue.rangev.uppertype = R_CONST;
+                                break;
+
+               }
                t->symvalue.rangev.upper = getint();
                break;
 
                t->symvalue.rangev.upper = getint();
                break;
 
@@ -872,19 +1069,21 @@ Integer nf, nl;
 
 /*
  * Add a file to the file table.
 
 /*
  * Add a file to the file table.
+ *
+ * If the new address is the same as the previous file address
+ * this routine used to not enter the file, but this caused some
+ * problems so it has been removed.  It's not clear that this in
+ * turn may not also cause a problem.
  */
 
 private enterfile(filename, addr)
 String filename;
 Address addr;
 {
  */
 
 private enterfile(filename, addr)
 String filename;
 Address addr;
 {
-    if (addr != curfaddr) {
-       filep->addr = addr;
-       filep->filename = filename;
-       filep->lineindex = linep - linetab;
-       ++filep;
-       curfaddr = addr;
-    }
+    filep->addr = addr;
+    filep->filename = filename;
+    filep->lineindex = linep - linetab;
+    ++filep;
 }
 
 /*
 }
 
 /*