ack/mach/vax4/ce/output.c
1988-09-15 09:49:22 +00:00

208 lines
4.4 KiB
C

#include <system.h>
#include <em.h>
#include <out.h>
#include "mach.h"
#include "back.h"
#include "data.h"
extern File *out_file;
/* This program converts an ACK a.out format to A BSD4.1 a.out.
* It is written for the a.out's generated by a code expander. So be
* carefull it is not very powerfull.
*/
#include <a.out.h>
struct exec u_header;
struct relocation_info u_reloc;
struct nlist u_name;
long ntext, ndata, nrelo, nchar, base_address();
int trsize=0, drsize=0;
output()
{
register int i;
init_unixheader();
putbuf( (char *) &u_header, 32);
putbuf( (char *) text_area, ntext);
putbuf( (char *) data_area, ndata);
for (i = 0; i < nrelo; i++) {
if ( ( reloc_info[i].or_sect-S_MIN) == SEGTXT) {
convert_reloc( &reloc_info[i], &u_reloc);
putbuf((char *) &u_reloc, 8);
}
}
for (i = 0; i < nrelo; i++) {
if (( reloc_info[i].or_sect-S_MIN) != SEGTXT) {
convert_reloc( &reloc_info[i], &u_reloc);
putbuf((char *) &u_reloc, 8);
}
}
for (i = 0; i < nname ; i++) { /* The segment names can be omitted */
convert_name( &symbol_table[i], &u_name);
putbuf((char *) &u_name, 12);
}
/* print( "size string_area %d\n", nchar); */
put_stringtablesize( nchar + 4);
putbuf((char *) string_area, nchar);
}
init_unixheader()
{
register int i;
for ( i = 0; i < (relo - reloc_info); i++)
if ( ( reloc_info[ i].or_sect - S_MIN) == SEGTXT)
trsize++;
else
drsize++;
ntext = text - text_area;
ndata = data - data_area;
nchar = string - string_area;
nrelo = relo - reloc_info;
u_header.a_magic = OMAGIC;
u_header.a_text = ntext;
u_header.a_data = ndata;
u_header.a_bss = nbss;
u_header.a_syms = nname * 12;
u_header.a_entry = 0;
u_header.a_trsize = trsize * 8;
u_header.a_drsize = drsize * 8;
/* 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);
*/
}
convert_reloc( a_relo, u_relo)
struct outrelo *a_relo;
struct relocation_info *u_relo;
{
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 = convert_length( (a_relo->or_type) & RELSZ);
if ( symbol_table[ a_relo->or_nami].on_valu == -1)
u_relo->r_extern = 1;
else
u_relo->r_extern = 0;
if ( symbol_table[ a_relo->or_nami].on_valu != -1) {
switch ( (symbol_table[ a_relo->or_nami].on_type & S_TYP) - S_MIN) {
case SEGTXT : u_relo->r_symbolnum = N_TEXT;
break;
case SEGCON : u_relo->r_symbolnum = N_DATA;
break;
case SEGBSS : u_relo->r_symbolnum = N_BSS;
break;
default : fprint( STDERR,
"convert_relo(): bad segment %d\n",
(symbol_table[ a_relo->or_nami].on_type & S_TYP) - S_MIN);
}
}
}
int convert_length( length)
int length;
{
if ( length & RELO1)
return( 0);
else if ( length & RELO2)
return( 1);
else if ( length & RELO4)
return( 2);
else
fprint( STDERR, "convert_length(): size is impossible %d\n",
length);
}
#define n_mptr n_un.n_name
#define n_str n_un.n_strx
convert_name( a_name, u_name)
struct outname *a_name;
struct nlist *u_name;
{
/* print( "naam is %s\n", a_name->on_foff + string_area); */
u_name->n_str = a_name->on_foff + 4;
fill_type( &(u_name->n_type), &(a_name->on_type), a_name->on_valu);
u_name->n_other = '\0';
u_name->n_desc = 0;
if ( a_name->on_valu != -1)
u_name->n_value = a_name->on_valu +
base_address( ( a_name->on_type & S_TYP) - S_MIN);
else
u_name->n_value = 0;
}
fill_type( u_type, a_type, valu)
unsigned char *u_type;
ushort *a_type;
long valu;
{
int sect;
*u_type = '\0';
*u_type |= ( *a_type & S_EXT) ? N_EXT : N_UNDF;
if ( valu != -1) {
sect = ( *a_type & S_TYP ) - S_MIN;
switch ( sect) {
case SEGTXT: *u_type |= N_TEXT;
break;
case SEGCON : *u_type |= N_DATA;
break;
case SEGBSS : *u_type |= N_BSS;
break;
default: fprint(STDERR,
"fill_type() : bad section %d\n", sect);
}
}
}
long base_address( seg)
int seg;
{
switch ( seg) {
case SEGTXT : return( 0);
break;
case SEGCON : return( text - text_area);
break;
case SEGBSS : return( text - text_area + data - data_area);
break;
default : fprint( STDERR,
"base_adres() : bad section %d\n", seg);
}
}
put_stringtablesize( n)
int n;
{
putbuf( (char *)&n, 4);
}
putbuf(buf,n)
char *buf;
long n;
{
sys_write( out_file, buf, n);
}