cv.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605
  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. #include <stdlib.h>
  15. long lseek();
  16. #define OMAGIC 0407 /* old-fashioned */
  17. #define NMAGIC 0410 /* text write protexted */
  18. #define ZMAGIC 0413 /* demand paging */
  19. struct bhdr {
  20. long magic;
  21. long tsize;
  22. long dsize;
  23. long bsize;
  24. long ssize;
  25. long entry;
  26. long rtsize;
  27. long rdsize;
  28. };
  29. struct machrelo {
  30. long address;
  31. long relodata;
  32. };
  33. #define setpcrel(X,f) (X |= (f<<7))
  34. #define setsymbolnum(X,n) (X = (X & 0377) | ((long)n << 8))
  35. #define setextern(X,f) (X |= (f << 4))
  36. #define setlength(X,l) (X = (X & ~0x60)|((long) l << 5))
  37. struct sym {
  38. long name;
  39. char type;
  40. char other;
  41. short desc;
  42. long value;
  43. };
  44. #define N_UNDF 0
  45. #define N_ABS 02
  46. #define N_TEXT 04
  47. #define N_DATA 06
  48. #define N_BSS 010
  49. #define N_EXT 01
  50. #define N_FN 0x1f
  51. /*
  52. * Header and section table of new format object file.
  53. */
  54. struct outhead outhead;
  55. struct outsect outsect[S_MAX];
  56. char *output_file;
  57. int outputfile_created;
  58. long magic;
  59. int rom_in_data;
  60. char *program ;
  61. char flag ;
  62. /* Output file definitions and such */
  63. struct bhdr bh;
  64. #define ENTRY 0x0
  65. #define TOT_HDRSIZE (sizeof(struct bhdr))
  66. #define TEXTSG 0
  67. #define ROMSG 1
  68. #define DATASG 2
  69. #define BSSSG 3
  70. #define LSECT BSSSG+1
  71. #define NSECT LSECT+1
  72. int output;
  73. int unresolved;
  74. int nflag;
  75. long textsize ;
  76. long datasize ;
  77. long bsssize;
  78. long align(a,b)
  79. long a,b;
  80. {
  81. a += b - 1;
  82. return a - a % b;
  83. }
  84. int
  85. follows(pa, pb)
  86. register struct outsect *pa, *pb;
  87. {
  88. /* return 1 if pa follows pb */
  89. return pa->os_base == align(pb->os_base+pb->os_size, pa->os_lign);
  90. }
  91. main(argc, argv)
  92. int argc;
  93. char *argv[];
  94. {
  95. register int nsect;
  96. program= argv[0] ;
  97. while ( argc>1 && argv[1][0]=='-' ) {
  98. flag=argv[1][1] ;
  99. if (flag == 'u') unresolved++;
  100. else if (flag == 'n') nflag = 1;
  101. argc-- ; argv++ ;
  102. }
  103. switch (argc) {
  104. case 3: if ((output = creat(argv[2], 0644)) < 0 ||
  105. (close(output), output = open(argv[2],2)) < 0)
  106. fatal("Can't write %s.\n", argv[2]);
  107. output_file = argv[2];
  108. outputfile_created = 1;
  109. if (! rd_open(argv[1]))
  110. fatal("Can't read %s.\n", argv[1]);
  111. break;
  112. default:fatal("Usage: %s [-u] [-n] <ACK object> <Vax object>.\n", program);
  113. }
  114. rd_ohead(&outhead);
  115. if (BADMAGIC(outhead))
  116. fatal("Not an ack object file.\n");
  117. if (outhead.oh_flags & HF_LINK) {
  118. if (! unresolved) {
  119. fprintf(stderr,"Warning: contains unresolved references.\n");
  120. }
  121. unresolved++;
  122. }
  123. else if (outhead.oh_nrelo > 0 && !unresolved)
  124. fprintf(stderr, "Warning: relocation information present.\n");
  125. if ( outhead.oh_nsect!=LSECT && outhead.oh_nsect!=NSECT )
  126. fatal("Input file must have %d sections, not %ld\n",
  127. NSECT,outhead.oh_nsect) ;
  128. rd_sect(outsect, outhead.oh_nsect);
  129. /* A few checks */
  130. if ( outsect[BSSSG].os_flen != 0 )
  131. fatal("bss space contains initialized data\n") ;
  132. if ( !unresolved) {
  133. if (! follows(&outsect[BSSSG], &outsect[DATASG]))
  134. fatal("bss segment must follow data segment\n") ;
  135. if (! follows(&outsect[ROMSG],&outsect[TEXTSG]))
  136. fatal("rom segment must follow text\n") ;
  137. if (! follows(&outsect[DATASG], &outsect[ROMSG]))
  138. fatal("data segment must follow rom\n") ;
  139. }
  140. outsect[TEXTSG].os_size = outsect[ROMSG].os_base - outsect[TEXTSG].os_base;
  141. outsect[ROMSG].os_size = outsect[DATASG].os_base - outsect[ROMSG].os_base;
  142. outsect[DATASG].os_size = outsect[BSSSG].os_base - outsect[DATASG].os_base;
  143. if ( outsect[ROMSG].os_lign == 0x400 ) {
  144. /* 410/413 file with ROMSG in data space */
  145. rom_in_data = 1;
  146. magic= NMAGIC ;
  147. textsize= outsect[TEXTSG].os_size;
  148. datasize= outsect[ROMSG].os_size + outsect[DATASG].os_size ;
  149. } else
  150. if ( outsect[DATASG].os_lign == 0x400 ) {
  151. /* 410/413 file with ROMSG in instruction space */
  152. rom_in_data = 0;
  153. magic= NMAGIC ;
  154. textsize= outsect[TEXTSG].os_size + outsect[ROMSG].os_size ;
  155. datasize= outsect[DATASG].os_size ;
  156. } else {
  157. /* Plain 407 file */
  158. rom_in_data = 0;
  159. magic= OMAGIC ;
  160. textsize= outsect[TEXTSG].os_size + outsect[ROMSG].os_size ;
  161. datasize = outsect[DATASG].os_size;
  162. }
  163. bsssize = outsect[BSSSG].os_size;
  164. if (nflag && magic != NMAGIC) {
  165. fatal("illegal alignments.\n");
  166. }
  167. if (magic == NMAGIC && ! nflag) {
  168. if (datasize & 0x3ff) {
  169. int diff = 0x400 - (datasize & 0x3ff);
  170. if (bsssize >= diff) bsssize -= diff;
  171. else bsssize = 0;
  172. outsect[DATASG].os_size += diff;
  173. datasize += diff;
  174. }
  175. magic = ZMAGIC;
  176. }
  177. if ( outhead.oh_nsect==NSECT ) {
  178. if (! follows(&outsect[LSECT],&outsect[BSSSG]))
  179. fatal("end segment must follow bss\n") ;
  180. if ( outsect[LSECT].os_size != 0 )
  181. fatal("end segment must be empty\n") ;
  182. }
  183. if (magic != OMAGIC && unresolved) {
  184. fatal("unresolved references with wrong magic number\n");
  185. }
  186. if (outsect[TEXTSG].os_base != ENTRY) {
  187. fatal("Illegal entry point.\n");
  188. }
  189. bh.magic = magic;
  190. bh.tsize = textsize;
  191. bh.bsize = bsssize;
  192. bh.dsize = datasize;
  193. bh.rtsize = 0;
  194. bh.rdsize = 0;
  195. bh.entry = ENTRY;
  196. /* Action at last */
  197. if (magic == ZMAGIC) {
  198. lseek(output,(long) 0x400, 0);
  199. }
  200. else lseek(output,(long) TOT_HDRSIZE,0);
  201. emits(&outsect[TEXTSG]) ;
  202. emits(&outsect[ROMSG]) ;
  203. emits(&outsect[DATASG]) ;
  204. if (unresolved) emit_relo();
  205. emit_symtab();
  206. bh.ssize = outhead.oh_nname * sizeof(struct sym);
  207. lseek(output,0L,0);
  208. cvlong(&(bh.magic));
  209. cvlong(&(bh.tsize));
  210. cvlong(&(bh.dsize));
  211. cvlong(&(bh.bsize));
  212. cvlong(&(bh.ssize));
  213. cvlong(&(bh.entry));
  214. cvlong(&(bh.rtsize));
  215. cvlong(&(bh.rdsize));
  216. writef(&bh, 1, (long) TOT_HDRSIZE);
  217. if ( outputfile_created && !unresolved ) chmod(argv[2],0755);
  218. exit(0);
  219. }
  220. writef(addr,sz,cnt)
  221. char *addr;
  222. long cnt;
  223. {
  224. cnt *= sz;
  225. while (cnt) {
  226. int i = cnt >= 0x4000 ? 0x4000 : cnt;
  227. cnt -= i;
  228. if (write(output, addr, i) < i) {
  229. fatal("write error\n");
  230. }
  231. addr += i;
  232. }
  233. }
  234. /*
  235. * Transfer the emitted byted from one file to another.
  236. */
  237. emits(section) struct outsect *section ; {
  238. char *p;
  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. char *chars;
  434. long offX = OFF_CHAR(outhead) - 4;
  435. if (!(A = ACKnames)) {
  436. if (!(A = (struct outname *)
  437. calloc(i, sizeof(struct outname)))) {
  438. fatal("No memory.\n");
  439. }
  440. rd_name(A, outhead.oh_nname);
  441. }
  442. if (!(M = (struct sym *) calloc(i, sizeof(struct sym)))) {
  443. fatal("No memory.\n");
  444. }
  445. MACHnames = M;
  446. ACKnames = A;
  447. for (; i; i--, A++) {
  448. M->value = A->on_valu;
  449. M->desc = A->on_desc;
  450. if ((A->on_type & S_SCT) ||
  451. (A->on_type & S_ETC) == S_FIL) {
  452. static int rest_local;
  453. if (! unresolved || rest_local || (rest_local = is_rest_local(A, i))) {
  454. outhead.oh_nname--;
  455. continue;
  456. }
  457. }
  458. if (A->on_type & S_STB) {
  459. M->type = A->on_type >> 8;
  460. }
  461. else if (A->on_type & S_COM) {
  462. M->type = N_UNDF | N_EXT;
  463. }
  464. else switch(A->on_type & S_TYP) {
  465. case S_UND:
  466. switch(A->on_type & S_ETC) {
  467. default:
  468. M->type = N_UNDF;
  469. break;
  470. case S_MOD:
  471. M->type = N_FN;
  472. break;
  473. case S_LIN:
  474. M->type = N_ABS;
  475. break;
  476. }
  477. break;
  478. case S_ABS:
  479. M->type = N_ABS;
  480. break;
  481. case S_MIN + TEXTSG:
  482. M->type = N_TEXT;
  483. break;
  484. case S_MIN + ROMSG:
  485. if (unresolved) {
  486. M->value += outsect[TEXTSG].os_size;
  487. }
  488. M->type = (rom_in_data ? N_DATA : N_TEXT);
  489. break;
  490. case S_MIN + DATASG:
  491. if (unresolved) {
  492. M->value += outsect[TEXTSG].os_size +
  493. outsect[ROMSG].os_size;
  494. }
  495. M->type = N_DATA;
  496. break;
  497. case S_MIN + BSSSG:
  498. if (unresolved) {
  499. M->value += outsect[TEXTSG].os_size +
  500. outsect[ROMSG].os_size +
  501. outsect[DATASG].os_size;
  502. }
  503. M->type = N_BSS;
  504. break;
  505. case S_MIN + LSECT:
  506. M->type = N_BSS;
  507. break;
  508. default:
  509. fprintf(stderr,"warning: unknown s_type: %d\n",
  510. A->on_type & S_TYP);
  511. }
  512. if (A->on_type & S_EXT) M->type |= N_EXT;
  513. M->name = A->on_foff;
  514. M++;
  515. }
  516. M = MACHnames;
  517. for (i = outhead.oh_nname; i; i--, M++) {
  518. if (M->name) {
  519. M->name -= offX;
  520. }
  521. else M->name = outhead.oh_nchar + 3; /* pointer to nullbyte */
  522. cvlong(&(M->name));
  523. cvlong(&(M->value));
  524. cvshort(&(M->desc));
  525. }
  526. writef(MACHnames, sizeof(struct sym), (long) outhead.oh_nname);
  527. free(MACHnames);
  528. free(ACKnames);
  529. if ((unsigned) outhead.oh_nchar != outhead.oh_nchar ||
  530. !( chars = malloc((unsigned) outhead.oh_nchar))) {
  531. fatal("No memory\n.");
  532. }
  533. put(outhead.oh_nchar+4,4);
  534. rd_string(chars,outhead.oh_nchar);
  535. writef(chars, 1, outhead.oh_nchar);
  536. free(chars);
  537. }
  538. /* VARARGS1 */
  539. fatal(s, a1, a2)
  540. char *s;
  541. {
  542. fprintf(stderr,"%s: ",program) ;
  543. fprintf(stderr, s, a1, a2);
  544. if (outputfile_created)
  545. unlink(output_file);
  546. exit(-1);
  547. }
  548. rd_fatal() { fatal("read error.\n"); }