output.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. #include <system.h>
  2. #include <em.h>
  3. #include <out.h>
  4. #include "mach.h"
  5. #include "back.h"
  6. /* Unportable code. Written for SUN, meant to be run on a SUN.
  7. */
  8. #ifndef sun
  9. Read above comment ...
  10. #endif
  11. extern File *B_out_file;
  12. #include <a.out.h>
  13. #include <alloc.h>
  14. static struct exec u_header;
  15. static long ntext, ndata, nrelo, nchar;
  16. long B_base_address[SEGBSS+1];
  17. static int trsize=0, drsize=0;
  18. static struct relocation_info *u_reloc;
  19. static reduce_name_table(), putbuf(), put_stringtablesize();
  20. static convert_name(), convert_reloc(), init_unixheader();
  21. output_back()
  22. {
  23. register int i;
  24. register struct nlist *u_name;
  25. register struct outrelo *rp;
  26. /*
  27. * Convert relocation data structures. This also requires
  28. * some re-ordering, as SUN .o format needs has text relocation
  29. * structures in front of the data relocation structures, whereas in
  30. * ACK they can be in any order.
  31. */
  32. nrelo = relo - reloc_info;
  33. u_reloc = (struct relocation_info *)
  34. Malloc((unsigned)nrelo*sizeof(struct relocation_info));
  35. rp = reloc_info;
  36. for (i = nrelo; i > 0; i--, rp++) {
  37. if ( ( rp->or_sect-S_MIN) == SEGTXT &&
  38. convert_reloc( rp, u_reloc)) {
  39. trsize++;
  40. u_reloc++;
  41. }
  42. }
  43. rp = reloc_info;
  44. for (i = nrelo; i > 0; i--, rp++) {
  45. if ( ( rp->or_sect-S_MIN) != SEGTXT &&
  46. convert_reloc( rp, u_reloc)) {
  47. u_reloc++;
  48. drsize++;
  49. }
  50. }
  51. nrelo = trsize + drsize;
  52. u_reloc -= nrelo;
  53. reduce_name_table();
  54. init_unixheader();
  55. putbuf( (char *) &u_header, sizeof(struct exec));
  56. putbuf( (char *) text_area, ntext);
  57. putbuf( (char *) data_area, ndata);
  58. putbuf((char *) u_reloc, sizeof(struct relocation_info)*nrelo);
  59. free(u_reloc);
  60. u_name = (struct nlist *)
  61. Malloc((unsigned)nname * sizeof(struct nlist));
  62. for (i = 0; i < nname ; i++) { /* The segment names can be omitted */
  63. convert_name( &symbol_table[i], u_name++);
  64. }
  65. u_name -= nname;
  66. putbuf((char *) u_name, sizeof(struct nlist)*nname);
  67. free(u_name);
  68. /* print( "size string_area %d\n", nchar); */
  69. put_stringtablesize( nchar + 4);
  70. putbuf((char *) string_area, nchar);
  71. }
  72. static
  73. reduce_name_table()
  74. {
  75. /*
  76. * Reduce the name table size. This is done by first marking
  77. * the name-table entries that are needed for relocation, then
  78. * removing the entries that are compiler-generated and not
  79. * needed for relocation, while remembering how many entries were
  80. * removed at each point, and then updating the relocation info.
  81. * After that, the string table is reduced.
  82. */
  83. #define S_NEEDED S_MOD
  84. #define removable(nm) (!(nm->on_type & (S_NEEDED|S_STB)) && *(nm->on_foff+string_area) == GENLAB)
  85. register int *diff_index =
  86. (int *) Malloc((unsigned)(nname + 1) * sizeof(int));
  87. register int i;
  88. register struct outname *np;
  89. char *new_str;
  90. register char *p, *q;
  91. register struct relocation_info *rp;
  92. *diff_index++ = 0;
  93. rp = u_reloc;
  94. for (i = nrelo; i > 0; i--, rp++) {
  95. if (rp->r_extern) {
  96. symbol_table[rp->r_symbolnum].on_type |= S_NEEDED;
  97. }
  98. }
  99. np = symbol_table;
  100. for (i = 0; i < nname; i++, np++) {
  101. int old_diff_index = diff_index[i-1];
  102. if (removable(np)) {
  103. diff_index[i] = old_diff_index + 1;
  104. }
  105. else {
  106. diff_index[i] = old_diff_index;
  107. }
  108. if ((np->on_type & S_TYP) == S_CRS) {
  109. struct outname *n = &symbol_table[(int) np->on_valu];
  110. if (! (n->on_type & S_COM)) {
  111. np->on_type &= ~S_TYP;
  112. np->on_type |= (n->on_type & S_TYP);
  113. np->on_valu = n->on_valu;
  114. }
  115. }
  116. }
  117. rp = u_reloc;
  118. for (i = nrelo; i > 0; i--, rp++) {
  119. if (rp->r_extern) {
  120. symbol_table[rp->r_symbolnum].on_type &= ~S_NEEDED;
  121. rp->r_symbolnum -= diff_index[rp->r_symbolnum];
  122. }
  123. }
  124. for (i = 0, np = symbol_table; i < nname; i++, np++) {
  125. if ((np->on_type & S_TYP) == S_CRS) {
  126. np->on_valu -= diff_index[(int) np->on_valu];
  127. }
  128. if (diff_index[i] && diff_index[i] == diff_index[i-1]) {
  129. symbol_table[i - diff_index[i]] = *np;
  130. }
  131. }
  132. nname -= diff_index[nname - 1];
  133. free((char *)(diff_index-1));
  134. new_str = q = Malloc((unsigned)(string - string_area));
  135. np = symbol_table;
  136. for (i = nname; i > 0; i--, np++) {
  137. p = np->on_foff + string_area;
  138. np->on_foff = q - new_str;
  139. while (*q++ = *p) p++;
  140. }
  141. free(string_area);
  142. string_area = new_str;
  143. string = q;
  144. }
  145. static
  146. init_unixheader()
  147. {
  148. ntext = text - text_area;
  149. ndata = data - data_area;
  150. nchar = string - string_area;
  151. u_header.a_magic = OMAGIC;
  152. u_header.a_machtype = M_68020;
  153. u_header.a_text = ntext;
  154. u_header.a_data = ndata;
  155. u_header.a_bss = nbss;
  156. u_header.a_syms = nname * sizeof(struct nlist);
  157. u_header.a_entry = 0;
  158. u_header.a_trsize = trsize * sizeof(struct relocation_info);
  159. u_header.a_drsize = drsize * sizeof(struct relocation_info);
  160. /* print( "header %o %d %d %d %d %d %d %d\n",
  161. u_header.a_magic, u_header.a_text, u_header.a_data,
  162. u_header.a_bss, u_header.a_syms, u_header.a_entry,
  163. u_header.a_trsize, u_header.a_drsize);
  164. */
  165. }
  166. static
  167. convert_reloc( a_relo, u_relo)
  168. register struct outrelo *a_relo;
  169. register struct relocation_info *u_relo;
  170. {
  171. int retval = 1;
  172. *(((int *) u_relo)+1) = 0;
  173. u_relo->r_address = a_relo->or_addr;
  174. u_relo->r_symbolnum = a_relo->or_nami;
  175. u_relo->r_pcrel = (a_relo->or_type & RELPC) >> 3;
  176. u_relo->r_length = 2;
  177. if ( symbol_table[ a_relo->or_nami].on_valu == -1 ||
  178. (symbol_table[ a_relo->or_nami].on_type & S_COM))
  179. u_relo->r_extern = 1;
  180. if ( u_relo->r_extern == 0) {
  181. switch ( (symbol_table[ a_relo->or_nami].on_type & S_TYP) - S_MIN) {
  182. case SEGTXT : u_relo->r_symbolnum = N_TEXT;
  183. if (u_relo->r_pcrel &&
  184. (a_relo->or_sect-S_MIN == SEGTXT))
  185. retval = 0;
  186. break;
  187. case SEGCON : u_relo->r_symbolnum = N_DATA;
  188. break;
  189. case SEGBSS : u_relo->r_symbolnum = N_BSS;
  190. break;
  191. /* Shut up; this could actually happen on erroneous input
  192. default : fprint( STDERR,
  193. "convert_relo(): bad segment %d\n",
  194. (symbol_table[ a_relo->or_nami].on_type & S_TYP) - S_MIN);
  195. */
  196. }
  197. }
  198. return retval;
  199. }
  200. #define n_mptr n_un.n_name
  201. #define n_str n_un.n_strx
  202. static
  203. convert_name( a_name, u_name)
  204. register struct outname *a_name;
  205. register struct nlist *u_name;
  206. {
  207. /* print( "naam is %s\n", a_name->on_foff + string_area); */
  208. u_name->n_str = a_name->on_foff + 4;
  209. if (a_name->on_type & S_STB) u_name->n_type = a_name->on_type >> 8;
  210. else u_name->n_type = 0;
  211. if ((a_name->on_type & S_TYP) == S_CRS) {
  212. a_name->on_valu = 0;
  213. a_name->on_type = S_COM;
  214. }
  215. if (a_name->on_valu != -1 && (! (a_name->on_type & S_COM))) {
  216. switch((a_name->on_type & S_TYP) - S_MIN) {
  217. case SEGTXT:
  218. u_name->n_type |= N_TEXT;
  219. break;
  220. case SEGCON:
  221. u_name->n_type |= N_DATA;
  222. break;
  223. case SEGBSS:
  224. u_name->n_type |= N_BSS;
  225. break;
  226. /* Shut up; this could actually happen on erroneous input
  227. default:
  228. fprint(STDERR, "convert_name(): bad section %d\n",
  229. (a_name->on_type & S_TYP) - S_MIN);
  230. break;
  231. */
  232. }
  233. }
  234. if ((a_name->on_type & S_TYP) == S_UND ||
  235. (a_name->on_type & S_EXT)) u_name->n_type |= N_EXT;
  236. u_name->n_other = '\0';
  237. u_name->n_desc = a_name->on_desc;
  238. if (a_name->on_type & S_COM)
  239. u_name->n_value = a_name->on_valu;
  240. else if ( a_name->on_valu != -1)
  241. u_name->n_value = a_name->on_valu +
  242. B_base_address[( a_name->on_type & S_TYP) - S_MIN];
  243. else
  244. u_name->n_value = 0;
  245. }
  246. static
  247. put_stringtablesize( n)
  248. long n;
  249. {
  250. putbuf( (char *)&n, 4L);
  251. }
  252. static
  253. putbuf(buf,n)
  254. char *buf;
  255. long n;
  256. {
  257. sys_write( B_out_file, buf, n);
  258. }