123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298 |
- #include <system.h>
- #include <em.h>
- #include <out.h>
- #include "mach.h"
- #include "back.h"
- /* Unportable code. Written for SUN, meant to be run on a SUN.
- */
- #ifndef sun
- Read above comment ...
- #endif
- extern File *B_out_file;
- #include <a.out.h>
- #include <alloc.h>
- static struct exec u_header;
- static long ntext, ndata, nrelo, nchar;
- long B_base_address[SEGBSS+1];
- static int trsize=0, drsize=0;
- static struct relocation_info *u_reloc;
- static reduce_name_table(), putbuf(), put_stringtablesize();
- static convert_name(), convert_reloc(), init_unixheader();
- output_back()
- {
- register int i;
- register struct nlist *u_name;
- register struct outrelo *rp;
- /*
- * Convert relocation data structures. This also requires
- * some re-ordering, as SUN .o format needs has text relocation
- * structures in front of the data relocation structures, whereas in
- * ACK they can be in any order.
- */
- nrelo = relo - reloc_info;
- u_reloc = (struct relocation_info *)
- Malloc((unsigned)nrelo*sizeof(struct relocation_info));
- rp = reloc_info;
- for (i = nrelo; i > 0; i--, rp++) {
- if ( ( rp->or_sect-S_MIN) == SEGTXT &&
- convert_reloc( rp, u_reloc)) {
- trsize++;
- u_reloc++;
- }
- }
- rp = reloc_info;
- for (i = nrelo; i > 0; i--, rp++) {
- if ( ( rp->or_sect-S_MIN) != SEGTXT &&
- convert_reloc( rp, u_reloc)) {
- u_reloc++;
- drsize++;
- }
- }
- nrelo = trsize + drsize;
- u_reloc -= nrelo;
- reduce_name_table();
- init_unixheader();
- putbuf( (char *) &u_header, sizeof(struct exec));
- putbuf( (char *) text_area, ntext);
- putbuf( (char *) data_area, ndata);
- putbuf((char *) u_reloc, sizeof(struct relocation_info)*nrelo);
- free(u_reloc);
-
- u_name = (struct nlist *)
- Malloc((unsigned)nname * sizeof(struct nlist));
- for (i = 0; i < nname ; i++) { /* The segment names can be omitted */
- convert_name( &symbol_table[i], u_name++);
- }
- u_name -= nname;
- putbuf((char *) u_name, sizeof(struct nlist)*nname);
- free(u_name);
- /* print( "size string_area %d\n", nchar); */
- put_stringtablesize( nchar + 4);
- putbuf((char *) string_area, nchar);
- }
- static
- reduce_name_table()
- {
- /*
- * Reduce the name table size. This is done by first marking
- * the name-table entries that are needed for relocation, then
- * removing the entries that are compiler-generated and not
- * needed for relocation, while remembering how many entries were
- * removed at each point, and then updating the relocation info.
- * After that, the string table is reduced.
- */
- #define S_NEEDED S_MOD
- #define removable(nm) (!(nm->on_type & (S_NEEDED|S_STB)) && *(nm->on_foff+string_area) == GENLAB)
- register int *diff_index =
- (int *) Malloc((unsigned)(nname + 1) * sizeof(int));
- register int i;
- register struct outname *np;
- char *new_str;
- register char *p, *q;
- register struct relocation_info *rp;
- *diff_index++ = 0;
- rp = u_reloc;
- for (i = nrelo; i > 0; i--, rp++) {
- if (rp->r_extern) {
- symbol_table[rp->r_symbolnum].on_type |= S_NEEDED;
- }
- }
- np = symbol_table;
- for (i = 0; i < nname; i++, np++) {
- int old_diff_index = diff_index[i-1];
- if (removable(np)) {
- diff_index[i] = old_diff_index + 1;
- }
- else {
- diff_index[i] = old_diff_index;
- }
- if ((np->on_type & S_TYP) == S_CRS) {
- struct outname *n = &symbol_table[(int) np->on_valu];
- if (! (n->on_type & S_COM)) {
- np->on_type &= ~S_TYP;
- np->on_type |= (n->on_type & S_TYP);
- np->on_valu = n->on_valu;
- }
- }
- }
- rp = u_reloc;
- for (i = nrelo; i > 0; i--, rp++) {
- if (rp->r_extern) {
- symbol_table[rp->r_symbolnum].on_type &= ~S_NEEDED;
- rp->r_symbolnum -= diff_index[rp->r_symbolnum];
- }
- }
- for (i = 0, np = symbol_table; i < nname; i++, np++) {
- if ((np->on_type & S_TYP) == S_CRS) {
- np->on_valu -= diff_index[(int) np->on_valu];
- }
- if (diff_index[i] && diff_index[i] == diff_index[i-1]) {
- symbol_table[i - diff_index[i]] = *np;
- }
- }
- nname -= diff_index[nname - 1];
- free((char *)(diff_index-1));
- new_str = q = Malloc((unsigned)(string - string_area));
- np = symbol_table;
- for (i = nname; i > 0; i--, np++) {
- p = np->on_foff + string_area;
- np->on_foff = q - new_str;
- while (*q++ = *p) p++;
- }
- free(string_area);
- string_area = new_str;
- string = q;
- }
- static
- init_unixheader()
- {
- ntext = text - text_area;
- ndata = data - data_area;
- nchar = string - string_area;
- u_header.a_magic = OMAGIC;
- u_header.a_machtype = M_68020;
- u_header.a_text = ntext;
- u_header.a_data = ndata;
- u_header.a_bss = nbss;
- u_header.a_syms = nname * sizeof(struct nlist);
- u_header.a_entry = 0;
- u_header.a_trsize = trsize * sizeof(struct relocation_info);
- u_header.a_drsize = drsize * sizeof(struct relocation_info);
- /* print( "header %o %d %d %d %d %d %d %d\n",
- u_header.a_magic, u_header.a_text, u_header.a_data,
- u_header.a_bss, u_header.a_syms, u_header.a_entry,
- u_header.a_trsize, u_header.a_drsize);
- */
- }
- static
- convert_reloc( a_relo, u_relo)
- register struct outrelo *a_relo;
- register struct relocation_info *u_relo;
- {
- int retval = 1;
- *(((int *) u_relo)+1) = 0;
- u_relo->r_address = a_relo->or_addr;
- u_relo->r_symbolnum = a_relo->or_nami;
- u_relo->r_pcrel = (a_relo->or_type & RELPC) >> 3;
- u_relo->r_length = 2;
- if ( symbol_table[ a_relo->or_nami].on_valu == -1 ||
- (symbol_table[ a_relo->or_nami].on_type & S_COM))
- u_relo->r_extern = 1;
- if ( u_relo->r_extern == 0) {
- switch ( (symbol_table[ a_relo->or_nami].on_type & S_TYP) - S_MIN) {
- case SEGTXT : u_relo->r_symbolnum = N_TEXT;
- if (u_relo->r_pcrel &&
- (a_relo->or_sect-S_MIN == SEGTXT))
- retval = 0;
- break;
- case SEGCON : u_relo->r_symbolnum = N_DATA;
- break;
- case SEGBSS : u_relo->r_symbolnum = N_BSS;
- break;
- /* Shut up; this could actually happen on erroneous input
- default : fprint( STDERR,
- "convert_relo(): bad segment %d\n",
- (symbol_table[ a_relo->or_nami].on_type & S_TYP) - S_MIN);
- */
- }
- }
- return retval;
- }
- #define n_mptr n_un.n_name
- #define n_str n_un.n_strx
- static
- convert_name( a_name, u_name)
- register struct outname *a_name;
- register struct nlist *u_name;
- {
- /* print( "naam is %s\n", a_name->on_foff + string_area); */
- u_name->n_str = a_name->on_foff + 4;
- if (a_name->on_type & S_STB) u_name->n_type = a_name->on_type >> 8;
- else u_name->n_type = 0;
- if ((a_name->on_type & S_TYP) == S_CRS) {
- a_name->on_valu = 0;
- a_name->on_type = S_COM;
- }
- if (a_name->on_valu != -1 && (! (a_name->on_type & S_COM))) {
- switch((a_name->on_type & S_TYP) - S_MIN) {
- case SEGTXT:
- u_name->n_type |= N_TEXT;
- break;
- case SEGCON:
- u_name->n_type |= N_DATA;
- break;
- case SEGBSS:
- u_name->n_type |= N_BSS;
- break;
- /* Shut up; this could actually happen on erroneous input
- default:
- fprint(STDERR, "convert_name(): bad section %d\n",
- (a_name->on_type & S_TYP) - S_MIN);
- break;
- */
- }
- }
- if ((a_name->on_type & S_TYP) == S_UND ||
- (a_name->on_type & S_EXT)) u_name->n_type |= N_EXT;
- u_name->n_other = '\0';
- u_name->n_desc = a_name->on_desc;
- if (a_name->on_type & S_COM)
- u_name->n_value = a_name->on_valu;
- else if ( a_name->on_valu != -1)
- u_name->n_value = a_name->on_valu +
- B_base_address[( a_name->on_type & S_TYP) - S_MIN];
- else
- u_name->n_value = 0;
- }
- static
- put_stringtablesize( n)
- long n;
- {
- putbuf( (char *)&n, 4L);
- }
- static
- putbuf(buf,n)
- char *buf;
- long n;
- {
- sys_write( B_out_file, buf, n);
- }
|