cv.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606
  1. /* $Id$ */
  2. /*
  3. * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
  4. * See the copyright notice in the ACK home directory, in the file "Copyright".
  5. *
  6. */
  7. /*
  8. * Convert ACK a.out file to VAX Berkeley Unix object format.
  9. */
  10. #include <stdlib.h>
  11. #include <stdio.h>
  12. #include <out.h>
  13. #include <assert.h>
  14. long lseek();
  15. #define OMAGIC 0407 /* old-fashioned */
  16. #define NMAGIC 0410 /* text write protexted */
  17. #define ZMAGIC 0413 /* demand paging */
  18. struct bhdr {
  19. long magic;
  20. long tsize;
  21. long dsize;
  22. long bsize;
  23. long ssize;
  24. long entry;
  25. long rtsize;
  26. long rdsize;
  27. };
  28. struct machrelo {
  29. long address;
  30. long relodata;
  31. };
  32. #define setpcrel(X,f) (X |= (f<<7))
  33. #define setsymbolnum(X,n) (X = (X & 0377) | ((long)n << 8))
  34. #define setextern(X,f) (X |= (f << 4))
  35. #define setlength(X,l) (X = (X & ~0x60)|((long) l << 5))
  36. struct sym {
  37. long name;
  38. char type;
  39. char other;
  40. short desc;
  41. long value;
  42. };
  43. #define N_UNDF 0
  44. #define N_ABS 02
  45. #define N_TEXT 04
  46. #define N_DATA 06
  47. #define N_BSS 010
  48. #define N_EXT 01
  49. #define N_FN 0x1f
  50. /*
  51. * Header and section table of new format object file.
  52. */
  53. struct outhead outhead;
  54. struct outsect outsect[S_MAX];
  55. char *output_file;
  56. int outputfile_created;
  57. long magic;
  58. int rom_in_data;
  59. char *program ;
  60. char flag ;
  61. /* Output file definitions and such */
  62. struct bhdr bh;
  63. #define ENTRY 0x0
  64. #define TOT_HDRSIZE (sizeof(struct bhdr))
  65. #define TEXTSG 0
  66. #define ROMSG 1
  67. #define DATASG 2
  68. #define BSSSG 3
  69. #define LSECT BSSSG+1
  70. #define NSECT LSECT+1
  71. int output;
  72. int unresolved;
  73. int nflag;
  74. long textsize ;
  75. long datasize ;
  76. long bsssize;
  77. long align(a,b)
  78. long a,b;
  79. {
  80. a += b - 1;
  81. return a - a % b;
  82. }
  83. int
  84. follows(pa, pb)
  85. register struct outsect *pa, *pb;
  86. {
  87. /* return 1 if pa follows pb */
  88. return pa->os_base == align(pb->os_base+pb->os_size, pa->os_lign);
  89. }
  90. main(argc, argv)
  91. int argc;
  92. char *argv[];
  93. {
  94. register int nsect;
  95. program= argv[0] ;
  96. while ( argc>1 && argv[1][0]=='-' ) {
  97. flag=argv[1][1] ;
  98. if (flag == 'u') unresolved++;
  99. else if (flag == 'n') nflag = 1;
  100. argc-- ; argv++ ;
  101. }
  102. switch (argc) {
  103. case 3: if ((output = creat(argv[2], 0644)) < 0 ||
  104. (close(output), output = open(argv[2],2)) < 0)
  105. fatal("Can't write %s.\n", argv[2]);
  106. output_file = argv[2];
  107. outputfile_created = 1;
  108. if (! rd_open(argv[1]))
  109. fatal("Can't read %s.\n", argv[1]);
  110. break;
  111. default:fatal("Usage: %s [-u] [-n] <ACK object> <Vax object>.\n", program);
  112. }
  113. rd_ohead(&outhead);
  114. if (BADMAGIC(outhead))
  115. fatal("Not an ack object file.\n");
  116. if (outhead.oh_flags & HF_LINK) {
  117. if (! unresolved) {
  118. fprintf(stderr,"Warning: contains unresolved references.\n");
  119. }
  120. unresolved++;
  121. }
  122. else if (outhead.oh_nrelo > 0 && !unresolved)
  123. fprintf(stderr, "Warning: relocation information present.\n");
  124. if ( outhead.oh_nsect!=LSECT && outhead.oh_nsect!=NSECT )
  125. fatal("Input file must have %d sections, not %ld\n",
  126. NSECT,outhead.oh_nsect) ;
  127. rd_sect(outsect, outhead.oh_nsect);
  128. /* A few checks */
  129. if ( outsect[BSSSG].os_flen != 0 )
  130. fatal("bss space contains initialized data\n") ;
  131. if ( !unresolved) {
  132. if (! follows(&outsect[BSSSG], &outsect[DATASG]))
  133. fatal("bss segment must follow data segment\n") ;
  134. if (! follows(&outsect[ROMSG],&outsect[TEXTSG]))
  135. fatal("rom segment must follow text\n") ;
  136. if (! follows(&outsect[DATASG], &outsect[ROMSG]))
  137. fatal("data segment must follow rom\n") ;
  138. }
  139. outsect[TEXTSG].os_size = outsect[ROMSG].os_base - outsect[TEXTSG].os_base;
  140. outsect[ROMSG].os_size = outsect[DATASG].os_base - outsect[ROMSG].os_base;
  141. outsect[DATASG].os_size = outsect[BSSSG].os_base - outsect[DATASG].os_base;
  142. if ( outsect[ROMSG].os_lign == 0x400 ) {
  143. /* 410/413 file with ROMSG in data space */
  144. rom_in_data = 1;
  145. magic= NMAGIC ;
  146. textsize= outsect[TEXTSG].os_size;
  147. datasize= outsect[ROMSG].os_size + outsect[DATASG].os_size ;
  148. } else
  149. if ( outsect[DATASG].os_lign == 0x400 ) {
  150. /* 410/413 file with ROMSG in instruction space */
  151. rom_in_data = 0;
  152. magic= NMAGIC ;
  153. textsize= outsect[TEXTSG].os_size + outsect[ROMSG].os_size ;
  154. datasize= outsect[DATASG].os_size ;
  155. } else {
  156. /* Plain 407 file */
  157. rom_in_data = 0;
  158. magic= OMAGIC ;
  159. textsize= outsect[TEXTSG].os_size + outsect[ROMSG].os_size ;
  160. datasize = outsect[DATASG].os_size;
  161. }
  162. bsssize = outsect[BSSSG].os_size;
  163. if (nflag && magic != NMAGIC) {
  164. fatal("illegal alignments.\n");
  165. }
  166. if (magic == NMAGIC && ! nflag) {
  167. if (datasize & 0x3ff) {
  168. int diff = 0x400 - (datasize & 0x3ff);
  169. if (bsssize >= diff) bsssize -= diff;
  170. else bsssize = 0;
  171. outsect[DATASG].os_size += diff;
  172. datasize += diff;
  173. }
  174. magic = ZMAGIC;
  175. }
  176. if ( outhead.oh_nsect==NSECT ) {
  177. if (! follows(&outsect[LSECT],&outsect[BSSSG]))
  178. fatal("end segment must follow bss\n") ;
  179. if ( outsect[LSECT].os_size != 0 )
  180. fatal("end segment must be empty\n") ;
  181. }
  182. if (magic != OMAGIC && unresolved) {
  183. fatal("unresolved references with wrong magic number\n");
  184. }
  185. if (outsect[TEXTSG].os_base != ENTRY) {
  186. fatal("Illegal entry point.\n");
  187. }
  188. bh.magic = magic;
  189. bh.tsize = textsize;
  190. bh.bsize = bsssize;
  191. bh.dsize = datasize;
  192. bh.rtsize = 0;
  193. bh.rdsize = 0;
  194. bh.entry = ENTRY;
  195. /* Action at last */
  196. if (magic == ZMAGIC) {
  197. lseek(output,(long) 0x400, 0);
  198. }
  199. else lseek(output,(long) TOT_HDRSIZE,0);
  200. emits(&outsect[TEXTSG]) ;
  201. emits(&outsect[ROMSG]) ;
  202. emits(&outsect[DATASG]) ;
  203. if (unresolved) emit_relo();
  204. emit_symtab();
  205. bh.ssize = outhead.oh_nname * sizeof(struct sym);
  206. lseek(output,0L,0);
  207. cvlong(&(bh.magic));
  208. cvlong(&(bh.tsize));
  209. cvlong(&(bh.dsize));
  210. cvlong(&(bh.bsize));
  211. cvlong(&(bh.ssize));
  212. cvlong(&(bh.entry));
  213. cvlong(&(bh.rtsize));
  214. cvlong(&(bh.rdsize));
  215. writef(&bh, 1, (long) TOT_HDRSIZE);
  216. if ( outputfile_created && !unresolved ) chmod(argv[2],0755);
  217. exit(0);
  218. }
  219. writef(addr,sz,cnt)
  220. char *addr;
  221. long cnt;
  222. {
  223. cnt *= sz;
  224. while (cnt) {
  225. int i = cnt >= 0x4000 ? 0x4000 : cnt;
  226. cnt -= i;
  227. if (write(output, addr, i) < i) {
  228. fatal("write error\n");
  229. }
  230. addr += i;
  231. }
  232. }
  233. /*
  234. * Transfer the emitted byted from one file to another.
  235. */
  236. emits(section) struct outsect *section ; {
  237. char *p;
  238. char *calloc(), *malloc();
  239. long sz = section->os_flen;
  240. rd_outsect(section - outsect);
  241. while (sz) {
  242. unsigned int i = (sz >= 0x4000 ? 0x4000 : sz);
  243. if (!(p = malloc(i))) {
  244. fatal("No memory.\n");
  245. }
  246. rd_emit(p, i);
  247. if (write(output, p, i) < i) {
  248. fatal("write error.\n");
  249. }
  250. free(p);
  251. sz -= i;
  252. }
  253. sz = section->os_size - section->os_flen;
  254. if (sz) {
  255. if (!(p = calloc(0x4000, 1))) {
  256. fatal("No memory.\n");
  257. }
  258. while (sz) {
  259. unsigned int i = (sz >= 0x4000 ? 0x4000 : sz);
  260. if (write(output, p, i) < i) {
  261. fatal("write error.\n");
  262. }
  263. sz -= i;
  264. }
  265. free(p);
  266. }
  267. }
  268. struct outname *ACKnames;
  269. emit_relo()
  270. {
  271. struct outrelo *ACKrelo;
  272. struct machrelo *MACHtrelo,*MACHdrelo;
  273. register struct outrelo *ap;
  274. register struct machrelo *mtp, *mdp;
  275. unsigned int cnt = outhead.oh_nrelo;
  276. ACKrelo = (struct outrelo *) calloc(cnt, sizeof(struct outrelo));
  277. MACHtrelo = (struct machrelo *) calloc(cnt, sizeof(struct machrelo));
  278. MACHdrelo = (struct machrelo *) calloc(cnt, sizeof(struct machrelo));
  279. ACKnames = (struct outname *) calloc(outhead.oh_nname, sizeof(struct outname));
  280. if (!(ap = ACKrelo) || !(mtp = MACHtrelo) || !(mdp = MACHdrelo) ||
  281. !ACKnames) {
  282. fatal("No memory.\n");
  283. }
  284. rd_relo(ACKrelo, cnt);
  285. rd_name(ACKnames, outhead.oh_nname);
  286. while (cnt-- != 0) {
  287. register struct machrelo *mp;
  288. if (ap->or_sect - S_MIN <= ROMSG) mp = mtp++;
  289. else mp = mdp++;
  290. setlength(mp->relodata,(ap->or_type&RELSZ) >> 1);
  291. setpcrel(mp->relodata,(ap->or_type&RELPC != 0));
  292. mp->address = ap->or_addr;
  293. if (ap->or_sect == ROMSG+S_MIN) {
  294. mp->address += outsect[TEXTSG].os_size;
  295. }
  296. if (ap->or_nami < outhead.oh_nname) {
  297. if (ACKnames[ap->or_nami].on_type & S_EXT) {
  298. setsymbolnum(mp->relodata, ap->or_nami);
  299. setextern(mp->relodata,1);
  300. }
  301. else {
  302. patch(ap, &ACKnames[ap->or_nami], mp);
  303. }
  304. }
  305. else {
  306. setsymbolnum(mp->relodata, N_ABS);
  307. }
  308. cvlong(&(mp->address));
  309. cvlong(&(mp->relodata));
  310. ap++;
  311. }
  312. bh.rtsize = (char *) mtp - (char *) MACHtrelo;
  313. bh.rdsize = (char *) mdp - (char *) MACHdrelo;
  314. writef(MACHtrelo, 1, bh.rtsize);
  315. writef(MACHdrelo, 1, bh.rdsize);
  316. free(ACKrelo);
  317. free(MACHtrelo);
  318. free(MACHdrelo);
  319. }
  320. long
  321. get(sz)
  322. {
  323. char buf[10];
  324. long l = 0;
  325. register char *p = buf + sz;
  326. read(output,buf,sz);
  327. while (sz--) {
  328. l = (l << 8) | (*--p & 0377);
  329. }
  330. return l;
  331. }
  332. put(l,sz)
  333. long l;
  334. {
  335. char buf[10];
  336. register char *p = buf;
  337. *p++ = l;
  338. *p++ = l >> 8;
  339. *p++ = l >> 16;
  340. *p++ = l >> 24;
  341. p -= sz;
  342. if (write(output, p, sz) < sz) {
  343. fatal("write error.\n");
  344. }
  345. }
  346. patch(ap, an, mp)
  347. register struct outrelo *ap;
  348. register struct outname *an;
  349. register struct machrelo *mp;
  350. {
  351. int whichsect = (an->on_type & S_TYP) - S_MIN;
  352. long correction = 0;
  353. long where = TOT_HDRSIZE+ap->or_addr;
  354. long X;
  355. long here;
  356. int sz;
  357. if (!(an->on_type & S_SCT)) {
  358. fprintf(stderr,"funny on_type %x\n", an->on_type);
  359. }
  360. switch(whichsect) {
  361. case TEXTSG:
  362. setsymbolnum(mp->relodata,N_TEXT);
  363. return;
  364. case DATASG:
  365. correction = outsect[ROMSG].os_size + outsect[TEXTSG].os_size;
  366. setsymbolnum(mp->relodata,N_DATA);
  367. break;
  368. case ROMSG:
  369. correction = outsect[TEXTSG].os_size;
  370. setsymbolnum(mp->relodata,N_TEXT);
  371. break;
  372. case BSSSG:
  373. correction = outsect[ROMSG].os_size + outsect[TEXTSG].os_size+
  374. outsect[DATASG].os_size;
  375. setsymbolnum(mp->relodata,N_BSS);
  376. break;
  377. default:
  378. assert(0);
  379. }
  380. switch(ap->or_sect - S_MIN) {
  381. case DATASG:
  382. where += outsect[ROMSG].os_size;
  383. case ROMSG:
  384. where += outsect[TEXTSG].os_size;
  385. case TEXTSG:
  386. break;
  387. default:
  388. assert(0);
  389. }
  390. here = lseek(output, 0L, 1);
  391. lseek(output, where, 0);
  392. sz = ap->or_type & RELSZ;
  393. X = get(sz) + correction;
  394. lseek(output, where, 0);
  395. put(X,sz);
  396. lseek(output, here, 0);
  397. }
  398. cvlong(l)
  399. long *l;
  400. {
  401. long x = *l;
  402. char *p = (char *) l;
  403. *p++ = x;
  404. *p++ = x >> 8;
  405. *p++ = x >> 16;
  406. *p++ = x >> 24;
  407. }
  408. cvshort(s)
  409. short *s;
  410. {
  411. int x = *s;
  412. char *p = (char *) s;
  413. *p++ = x;
  414. *p = x >> 8;
  415. }
  416. int
  417. is_rest_local(A, i)
  418. register int i;
  419. register struct outname *A;
  420. {
  421. while (i--) {
  422. if (A->on_type & S_EXT) return 0;
  423. A++;
  424. }
  425. return 1;
  426. }
  427. emit_symtab()
  428. {
  429. register unsigned short i = outhead.oh_nname;
  430. register struct outname *A;
  431. struct sym *MACHnames;
  432. register struct sym *M;
  433. extern char *malloc(), *calloc();
  434. char *chars;
  435. long offX = OFF_CHAR(outhead) - 4;
  436. if (!(A = ACKnames)) {
  437. if (!(A = (struct outname *)
  438. calloc(i, sizeof(struct outname)))) {
  439. fatal("No memory.\n");
  440. }
  441. rd_name(A, outhead.oh_nname);
  442. }
  443. if (!(M = (struct sym *) calloc(i, sizeof(struct sym)))) {
  444. fatal("No memory.\n");
  445. }
  446. MACHnames = M;
  447. ACKnames = A;
  448. for (; i; i--, A++) {
  449. M->value = A->on_valu;
  450. M->desc = A->on_desc;
  451. if ((A->on_type & S_SCT) ||
  452. (A->on_type & S_ETC) == S_FIL) {
  453. static int rest_local;
  454. if (! unresolved || rest_local || (rest_local = is_rest_local(A, i))) {
  455. outhead.oh_nname--;
  456. continue;
  457. }
  458. }
  459. if (A->on_type & S_STB) {
  460. M->type = A->on_type >> 8;
  461. }
  462. else if (A->on_type & S_COM) {
  463. M->type = N_UNDF | N_EXT;
  464. }
  465. else switch(A->on_type & S_TYP) {
  466. case S_UND:
  467. switch(A->on_type & S_ETC) {
  468. default:
  469. M->type = N_UNDF;
  470. break;
  471. case S_MOD:
  472. M->type = N_FN;
  473. break;
  474. case S_LIN:
  475. M->type = N_ABS;
  476. break;
  477. }
  478. break;
  479. case S_ABS:
  480. M->type = N_ABS;
  481. break;
  482. case S_MIN + TEXTSG:
  483. M->type = N_TEXT;
  484. break;
  485. case S_MIN + ROMSG:
  486. if (unresolved) {
  487. M->value += outsect[TEXTSG].os_size;
  488. }
  489. M->type = (rom_in_data ? N_DATA : N_TEXT);
  490. break;
  491. case S_MIN + DATASG:
  492. if (unresolved) {
  493. M->value += outsect[TEXTSG].os_size +
  494. outsect[ROMSG].os_size;
  495. }
  496. M->type = N_DATA;
  497. break;
  498. case S_MIN + BSSSG:
  499. if (unresolved) {
  500. M->value += outsect[TEXTSG].os_size +
  501. outsect[ROMSG].os_size +
  502. outsect[DATASG].os_size;
  503. }
  504. M->type = N_BSS;
  505. break;
  506. case S_MIN + LSECT:
  507. M->type = N_BSS;
  508. break;
  509. default:
  510. fprintf(stderr,"warning: unknown s_type: %d\n",
  511. A->on_type & S_TYP);
  512. }
  513. if (A->on_type & S_EXT) M->type |= N_EXT;
  514. M->name = A->on_foff;
  515. M++;
  516. }
  517. M = MACHnames;
  518. for (i = outhead.oh_nname; i; i--, M++) {
  519. if (M->name) {
  520. M->name -= offX;
  521. }
  522. else M->name = outhead.oh_nchar + 3; /* pointer to nullbyte */
  523. cvlong(&(M->name));
  524. cvlong(&(M->value));
  525. cvshort(&(M->desc));
  526. }
  527. writef(MACHnames, sizeof(struct sym), (long) outhead.oh_nname);
  528. free(MACHnames);
  529. free(ACKnames);
  530. if ((unsigned) outhead.oh_nchar != outhead.oh_nchar ||
  531. !( chars = malloc((unsigned) outhead.oh_nchar))) {
  532. fatal("No memory\n.");
  533. }
  534. put(outhead.oh_nchar+4,4);
  535. rd_string(chars,outhead.oh_nchar);
  536. writef(chars, 1, outhead.oh_nchar);
  537. free(chars);
  538. }
  539. /* VARARGS1 */
  540. fatal(s, a1, a2)
  541. char *s;
  542. {
  543. fprintf(stderr,"%s: ",program) ;
  544. fprintf(stderr, s, a1, a2);
  545. if (outputfile_created)
  546. unlink(output_file);
  547. exit(-1);
  548. }
  549. rd_fatal() { fatal("read error.\n"); }