194 lines
		
	
	
	
		
			4.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			194 lines
		
	
	
	
		
			4.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* $Header$
 | |
|    Read the symbol table from an ACK a.out format file.
 | |
| */
 | |
| 
 | |
| #include <stb.h>
 | |
| #include <alloc.h>
 | |
| #include <assert.h>
 | |
| 
 | |
| #include "position.h"
 | |
| #include "file.h"
 | |
| #include "symbol.h"
 | |
| #include "idf.h"
 | |
| #include "scope.h"
 | |
| #include "rd.h"
 | |
| 
 | |
| extern char		*strindex();
 | |
| extern struct outname	*DbxString();
 | |
| 
 | |
| int			saw_code = 0;
 | |
| 
 | |
| static char		*AckStrings;	/* ACK a.out string table */
 | |
| static struct outname	*AckNames;	/* ACK a.out symbol table entries */
 | |
| static unsigned int	NAckNames;	/* Number of ACK symbol table entries */
 | |
| static struct outname	*EndAckNames;	/* &AckNames[NAckNames] */
 | |
| 
 | |
| /* Read the symbol table from file 'f', which is supposed to be an
 | |
|    ACK a.out format file. Offer DBX strings to the DBX string parser.
 | |
| */
 | |
| int
 | |
| DbxRead(f)
 | |
|   char	*f;
 | |
| {
 | |
|   struct outhead h;
 | |
|   register struct outname *n;
 | |
|   register struct outname *line_file = 0;
 | |
|   long OffsetStrings;
 | |
|   int had_lbrac = 0;
 | |
| 
 | |
|   /* Open file, read header, and check magic word */
 | |
|   if (! rd_open(f)) {
 | |
|   	fatal("%s: could not open", f);
 | |
|   }
 | |
|   rd_ohead(&h);
 | |
|   if (BADMAGIC(h) && h.oh_magic != O_CONVERTED) {
 | |
|   	fatal("%s: not an object file", f);
 | |
|   }
 | |
| 
 | |
|   /* Allocate space for name table and read it */
 | |
|   AckNames = (struct outname *) 
 | |
|   		Malloc((unsigned)(sizeof(struct outname) * h.oh_nname));
 | |
|   AckStrings = Malloc((unsigned) h.oh_nchar);
 | |
|   rd_name(AckNames, h.oh_nname);
 | |
|   rd_string(AckStrings, h.oh_nchar);
 | |
| 
 | |
|   /* Adjust file offsets in name table to point at strings */
 | |
|   OffsetStrings = OFF_CHAR(h);
 | |
|   NAckNames = h.oh_nname;
 | |
|   EndAckNames = &AckNames[h.oh_nname];
 | |
|   for (n = EndAckNames; --n >= AckNames;) {
 | |
| 	if (n->on_foff) {
 | |
| 		if ((unsigned)(n->on_foff - OffsetStrings) >= h.oh_nchar) {
 | |
| 			fatal("%s: error in object file", f);
 | |
| 		}
 | |
| 		n->on_mptr = AckStrings + (n->on_foff - OffsetStrings);
 | |
| 	}
 | |
| 	else	n->on_mptr = 0;
 | |
|   }
 | |
| 
 | |
|   /* Offer strings to the DBX string parser if they contain a ':'.
 | |
|      Also offer filename-line number information to add_position_addr().
 | |
|      Here, the order may be important.
 | |
|   */
 | |
|   for (n = &AckNames[0]; n < EndAckNames; n++) {
 | |
| 	int tp = n->on_type >> 8;
 | |
| 	register p_symbol sym;
 | |
| 
 | |
| 	if (tp & (S_STB >> 8)) {
 | |
| 		switch(tp) {
 | |
| #ifdef N_BINCL
 | |
| 		case N_BINCL:
 | |
| 			n->on_valu = (long) line_file;
 | |
| 			line_file = n;
 | |
| 			break;
 | |
| 		case N_EINCL:
 | |
| 			if (line_file) {
 | |
| 				line_file = (struct outname *) line_file->on_valu;
 | |
| 			}
 | |
| 			break;
 | |
| #endif
 | |
| 		case N_SO:
 | |
| 			if (n->on_mptr[strlen(n->on_mptr)-1] == '/') {
 | |
| 				/* another N_SO follows ... */
 | |
| 				break;
 | |
| 			}
 | |
| 			while (CurrentScope != PervasiveScope) {
 | |
| 				close_scope();
 | |
| 			}
 | |
| 			saw_code = 0;
 | |
| 			sym = add_file(n->on_mptr);
 | |
| 
 | |
| 			if (! listfile) newfile(sym->sy_idf);
 | |
| 			open_scope(sym, 0);
 | |
| 			sym->sy_file->f_scope = CurrentScope;
 | |
| 			FileScope = CurrentScope;
 | |
| 			clean_tp_tab();
 | |
| 			/* fall through */
 | |
| 		case N_SOL:
 | |
| 			if (! line_file) line_file = n;
 | |
| 			else line_file->on_mptr = n->on_mptr;
 | |
| 			break;
 | |
| 		case N_MAIN:
 | |
| 			newfile(FileScope->sc_definedby->sy_idf);
 | |
| 			break;
 | |
| 		case N_SLINE:
 | |
| 			assert(line_file);
 | |
| 			if (! saw_code && !CurrentScope->sc_bp_opp) {
 | |
| 			    CurrentScope->sc_bp_opp = n->on_valu;
 | |
| 			    if (! CurrentScope->sc_start) {
 | |
| 				CurrentScope->sc_start = n->on_valu;
 | |
| 				if (CurrentScope->sc_has_activation_record) {
 | |
| 					add_scope_addr(CurrentScope);
 | |
| 				}
 | |
| 			    }
 | |
| 			}
 | |
| 			saw_code = 1;
 | |
| 			add_position_addr(line_file->on_mptr, n);
 | |
| 			break;
 | |
| 		case N_LBRAC:	/* block, desc = nesting level */
 | |
| 			if (had_lbrac) {
 | |
| 				open_scope((p_symbol) 0, 0);
 | |
| 				saw_code = 0;
 | |
| 			}
 | |
| 			else {
 | |
| 				register p_scope sc = 
 | |
| 					get_scope_from_addr(n->on_valu);
 | |
| 
 | |
| 				if (!sc || sc->sc_bp_opp) {
 | |
| 					had_lbrac = 1;
 | |
| 				}
 | |
| 				else CurrentScope = sc;
 | |
| 			}
 | |
| 			break;
 | |
| #ifdef N_SCOPE
 | |
| 		case N_SCOPE:
 | |
| 			if (n->on_mptr && strindex(n->on_mptr, ':')) {
 | |
| 				n = DbxString(n);
 | |
| 			}
 | |
| 			break;
 | |
| #endif
 | |
| 		case N_RBRAC:	/* end block, desc = nesting level */
 | |
| 			had_lbrac = 0;
 | |
| 			if (CurrentScope != FileScope) close_scope();
 | |
| 			saw_code = 0;
 | |
| 			break;
 | |
| 		case N_FUN:	/* function, value = address */
 | |
| 		case N_GSYM:	/* global variable */
 | |
| 		case N_STSYM:	/* data, static, value = address */
 | |
| 		case N_LCSYM:	/* bss, static, value = address */
 | |
| 		case N_RSYM:	/* register var, value = reg number */
 | |
| 		case N_SSYM:	/* struct/union el, value = offset */
 | |
| 		case N_PSYM:	/* parameter, value = offset from AP */
 | |
| 		case N_LSYM:	/* local sym, value = offset from FP */
 | |
| 			if (had_lbrac) {
 | |
| 				open_scope((p_symbol) 0, 0);
 | |
| 				saw_code = 0;
 | |
| 				had_lbrac = 0;
 | |
| 			}
 | |
| 			if (n->on_mptr && strindex(n->on_mptr, ':')) {
 | |
| 				n = DbxString(n);
 | |
| 			}
 | |
| 			break;
 | |
| 		default:
 | |
| /*
 | |
| 			if (n->on_mptr && (n->on_type&S_TYP) >= S_MIN) {
 | |
| 				struct idf *id = str2idf(n->on_mptr, 0);
 | |
| 
 | |
| 				sym = new_symbol();
 | |
| 				sym->sy_next = id->id_def;
 | |
| 				id->id_def = sym;
 | |
| 				sym->sy_class = SYMENTRY;
 | |
| 				sym->sy_onam = *n;
 | |
| 				sym->sy_idf = id;
 | |
| 			}
 | |
| */
 | |
| 			break;
 | |
| 		}
 | |
| 	}
 | |
|   }
 | |
|   close_scope();
 | |
|   add_position_addr((char *) 0, (struct outname *) 0);
 | |
|   clean_tp_tab();
 | |
|   rd_close();
 | |
|   return (h.oh_magic == O_CONVERTED);
 | |
| }
 |