208 lines
4.4 KiB
C
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);
|
|
}
|