189 lines
4.1 KiB
C
189 lines
4.1 KiB
C
#include <system.h>
|
|
#include <alloc.h>
|
|
#include <out.h>
|
|
#include "mach.h"
|
|
#include "back.h"
|
|
|
|
static reduce_name_table();
|
|
static convert_outname();
|
|
|
|
static int nrelo;
|
|
|
|
output_back()
|
|
/* Dump the tables.
|
|
* Notice : entries in the symbol_table are converted.
|
|
*/
|
|
|
|
{
|
|
struct outhead header;
|
|
struct outsect sect;
|
|
long ntext = text - text_area,
|
|
ndata = data - data_area,
|
|
nchar;
|
|
|
|
nrelo = relo - reloc_info;
|
|
|
|
reduce_name_table();
|
|
|
|
nchar = string - string_area;
|
|
header.oh_magic = O_MAGIC;
|
|
header.oh_stamp = 0;
|
|
header.oh_flags = HF_LINK;
|
|
header.oh_nsect = 4;
|
|
header.oh_nrelo = nrelo;
|
|
header.oh_nname = nname;
|
|
header.oh_nemit = ntext + ndata;
|
|
header.oh_nchar = nchar;
|
|
|
|
wr_ohead( &header);
|
|
|
|
sect.os_base = 20;
|
|
sect.os_size = ntext;
|
|
sect.os_foff = OFF_EMIT( header);
|
|
sect.os_flen = ntext;
|
|
sect.os_lign = 1;
|
|
|
|
wr_sect( §, 1);
|
|
|
|
sect.os_base = 20 + ntext;
|
|
sect.os_size = 0;
|
|
sect.os_foff = OFF_EMIT( header) + ntext;
|
|
sect.os_flen = 0;
|
|
sect.os_lign = 1;
|
|
|
|
wr_sect( §, 1);
|
|
|
|
sect.os_base = 20 + ntext;
|
|
sect.os_size = ndata;
|
|
sect.os_foff = OFF_EMIT( header) + ntext;
|
|
sect.os_flen = ndata;
|
|
sect.os_lign = 1;
|
|
|
|
wr_sect( §, 1);
|
|
|
|
sect.os_base = 20 + ntext + ndata;
|
|
sect.os_size = nbss;
|
|
sect.os_foff = OFF_EMIT( header) + ntext + ndata;
|
|
sect.os_flen = 0;
|
|
sect.os_lign = 1;
|
|
|
|
wr_sect( §, 1);
|
|
|
|
wr_outsect( 0);
|
|
wr_emit( text_area, ntext);
|
|
wr_outsect( 2);
|
|
wr_emit( data_area, ndata);
|
|
|
|
wr_relo( reloc_info, nrelo);
|
|
|
|
convert_outname( &header);
|
|
wr_name( symbol_table, nname);
|
|
|
|
wr_string( 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 struct outrelo *rp = reloc_info;
|
|
register struct outname *np;
|
|
register int i;
|
|
char *new_str;
|
|
register char *p, *q;
|
|
|
|
*diff_index++ = 0;
|
|
for (i = 0; i < nrelo; i++) {
|
|
if (symbol_table[rp->or_nami].on_valu == -1 ||
|
|
(symbol_table[rp->or_nami].on_type & S_COM)) {
|
|
symbol_table[rp->or_nami].on_type |= S_NEEDED;
|
|
}
|
|
rp++;
|
|
}
|
|
|
|
for (i = 0, np = symbol_table; i < nname; i++, np++) {
|
|
diff_index[i] = diff_index[i-1];
|
|
if (removable(np)) {
|
|
diff_index[i]++;
|
|
}
|
|
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 = reloc_info;
|
|
for (i = 0; i < nrelo; i++) {
|
|
symbol_table[rp->or_nami].on_type &= ~S_NEEDED;
|
|
rp->or_nami -= diff_index[rp->or_nami];
|
|
rp++;
|
|
}
|
|
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));
|
|
for (i = 0, np = symbol_table; i < nname; 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;
|
|
for (i = 0, np = symbol_table; i < nname; i++, np++) {
|
|
if ((np->on_type & S_TYP) == S_CRS) {
|
|
/* replace by reference to string */
|
|
np->on_valu = symbol_table[(int) np->on_valu].on_foff;
|
|
}
|
|
}
|
|
}
|
|
|
|
wr_fatal()
|
|
{
|
|
fprint( STDERR, "write failed\n");
|
|
sys_stop(S_ABORT);
|
|
}
|
|
|
|
|
|
static
|
|
convert_outname( header)
|
|
struct outhead *header;
|
|
{
|
|
int i;
|
|
register struct outname *np;
|
|
register long l = OFF_CHAR(*header);
|
|
|
|
for (i = 0, np = symbol_table; i < nname; i++, np++) {
|
|
np->on_foff += l;
|
|
if ((np->on_type & S_TYP) == S_CRS) {
|
|
np->on_valu += l;
|
|
}
|
|
}
|
|
}
|