cv.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  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 ST-Minix object format.
  9. */
  10. #include <stdlib.h>
  11. #include <stdio.h>
  12. #include <out.h>
  13. #include <assert.h>
  14. #include <stdlib.h>
  15. struct outhead outhead;
  16. struct outsect outsect[S_MAX];
  17. #define TEXTSG 0
  18. #define ROMSG 1
  19. #define DATASG 2
  20. #define BSSSG 3
  21. #define LSECT BSSSG+1
  22. #define NSECT LSECT+1
  23. char *output_file;
  24. int outputfile_created;
  25. char *program ;
  26. /* Output file definitions and such */
  27. int output;
  28. int unresolved;
  29. long textsize ;
  30. long datasize ;
  31. long bsssize;
  32. char *chmemstr;
  33. minixhead()
  34. {
  35. long mh[8];
  36. long stack;
  37. long chmem();
  38. int i;
  39. mh[0] = 0x04100301L;
  40. mh[1] = 0x00000020L;
  41. mh[2] = textsize;
  42. mh[3] = datasize;
  43. mh[4] = bsssize;
  44. mh[5] = 0;
  45. stack = 0x00010000L - (mh[3] + mh[4]);
  46. if ((mh[0] & 0x00200000L) == 0) /* not SEPARATE */
  47. stack -= mh[2];
  48. while (stack < 0)
  49. stack += 0x00010000L;
  50. if (chmemstr)
  51. stack = chmem(chmemstr, stack);
  52. printf("%ld bytes assigned to stack+malloc area\n", stack);
  53. mh[6] = stack + (mh[3] + mh[4]);
  54. if ((mh[0] & 0x00200000L) == 0) /* not SEPARATE */
  55. mh[6] += mh[2];
  56. mh[7] = 0;
  57. for (i = 0; i < 8; i++) {
  58. cvlong(&mh[i]);
  59. }
  60. if (write(output, (char *) mh, sizeof(mh)) != sizeof(mh))
  61. fatal("write error\n");
  62. }
  63. long align(a,b)
  64. long a,b;
  65. {
  66. if (b == 0) return a;
  67. a += b - 1;
  68. return a - a % b;
  69. }
  70. int
  71. follows(pa, pb)
  72. register struct outsect *pa, *pb;
  73. {
  74. /* return 1 if pa follows pb */
  75. return pa->os_base == align(pb->os_base+pb->os_size, pa->os_lign);
  76. }
  77. main(argc, argv)
  78. int argc;
  79. char *argv[];
  80. {
  81. program= argv[0] ;
  82. if (argc > 1) {
  83. switch (argv[1][0]) {
  84. case '-':
  85. case '+':
  86. case '=':
  87. chmemstr = argv[1];
  88. argc--;
  89. argv++;
  90. }
  91. }
  92. switch (argc) {
  93. case 3: if ((output = creat(argv[2], 0644)) < 0)
  94. fatal("Can't write %s.\n", argv[2]);
  95. output_file = argv[2];
  96. outputfile_created = 1;
  97. if (! rd_open(argv[1]))
  98. fatal("Can't read %s.\n", argv[1]);
  99. break;
  100. default:fatal("Usage: %s [+-= amount] <ACK object> <ST-MINIX object>.\n", argv[0]);
  101. }
  102. rd_ohead(&outhead);
  103. if (BADMAGIC(outhead))
  104. fatal("Not an ack object file.\n");
  105. if (outhead.oh_flags & HF_LINK) {
  106. unresolved++;
  107. fatal("Contains unresolved references.\n");
  108. }
  109. if ( outhead.oh_nsect!=LSECT && outhead.oh_nsect!=NSECT )
  110. fatal("Input file must have %d sections, not %ld\n",
  111. NSECT,outhead.oh_nsect) ;
  112. rd_sect(outsect, outhead.oh_nsect);
  113. /* A few checks */
  114. if ( outsect[BSSSG].os_flen != 0 )
  115. fatal("bss space contains initialized data\n") ;
  116. if (! follows(&outsect[BSSSG], &outsect[DATASG]))
  117. fatal("bss segment must follow data segment\n") ;
  118. textsize= (outsect[DATASG].os_base - outsect[TEXTSG].os_base);
  119. if (! follows(&outsect[ROMSG],&outsect[TEXTSG]))
  120. fatal("rom segment must follow text\n") ;
  121. if (! follows(&outsect[DATASG],&outsect[ROMSG]))
  122. fatal("data segment must follow rom\n") ;
  123. outsect[TEXTSG].os_size = outsect[ROMSG].os_base - outsect[TEXTSG].os_base;
  124. outsect[ROMSG].os_size = outsect[DATASG].os_base - outsect[ROMSG].os_base;
  125. outsect[DATASG].os_size = outsect[BSSSG].os_base - outsect[DATASG].os_base;
  126. datasize= outsect[DATASG].os_size ;
  127. bsssize = outsect[BSSSG].os_size;
  128. if ( outhead.oh_nsect==NSECT ) {
  129. if (! follows(&outsect[LSECT],&outsect[BSSSG]))
  130. fatal("end segment must follow bss\n") ;
  131. if ( outsect[LSECT].os_size != 0 )
  132. fatal("end segment must be empty\n") ;
  133. }
  134. minixhead();
  135. emits(&outsect[TEXTSG]) ;
  136. emits(&outsect[ROMSG]) ;
  137. emits(&outsect[DATASG]) ;
  138. emit_relo();
  139. if ( outputfile_created) chmod(argv[2],0755);
  140. return 0;
  141. }
  142. /*
  143. * Transfer the emitted byted from one file to another.
  144. */
  145. emits(section) struct outsect *section ; {
  146. char *p;
  147. long sz = section->os_flen;
  148. rd_outsect(section - outsect);
  149. while (sz) {
  150. unsigned int i = (sz >= 0x4000 ? 0x4000 : sz);
  151. if (!(p = malloc(0x4000))) {
  152. fatal("No memory.\n");
  153. }
  154. rd_emit(p, (long) i);
  155. if (write(output, p, (int)i) < i) {
  156. fatal("write error.\n");
  157. }
  158. free(p);
  159. sz -= i;
  160. }
  161. sz = section->os_size - section->os_flen;
  162. if (sz) {
  163. if (!(p = calloc(0x4000, 1))) {
  164. fatal("No memory.\n");
  165. }
  166. while (sz) {
  167. unsigned int i = (sz >= 0x4000 ? 0x4000 : sz);
  168. if (write(output, p, (int)i) < i) {
  169. fatal("write error.\n");
  170. }
  171. sz -= i;
  172. }
  173. free(p);
  174. }
  175. }
  176. int
  177. compare(a,b)
  178. register struct outrelo *a, *b;
  179. {
  180. if (a->or_sect < b->or_sect) return -1;
  181. if (a->or_sect > b->or_sect) return 1;
  182. if (a->or_addr < b->or_addr) return -1;
  183. if (a->or_addr > b->or_addr) return 1;
  184. return 0;
  185. }
  186. emit_relo()
  187. {
  188. struct outrelo *ACKrelo;
  189. register struct outrelo *ap;
  190. unsigned int cnt = outhead.oh_nrelo;
  191. long last, curr, base;
  192. int sect;
  193. char *bp;
  194. register char *b;
  195. ACKrelo = ap = (struct outrelo *) calloc(cnt, sizeof(struct outrelo));
  196. bp = b = malloc(4 + cnt);
  197. if (!ap || !bp) {
  198. fatal("No memory.\n");
  199. }
  200. rd_relo(ap, cnt);
  201. qsort((char *) ap, (int) cnt, sizeof(struct outrelo), compare);
  202. /*
  203. * read relocation, modify to GEMDOS format, and write.
  204. * Only longs can be relocated.
  205. *
  206. * The GEMDOS format starts with a long L: the offset to the
  207. * beginning of text for the first long to be relocated.
  208. * If L==0 then no relocations have to be made.
  209. *
  210. * The long is followed by zero or more bytes. Each byte B is
  211. * processed separately, in one of the following ways:
  212. *
  213. * B==0:
  214. * end of relocation
  215. * B==1:
  216. * no relocation, but add 254 to the current offset
  217. * B==0bWWWWWWW0:
  218. * B is added to the current offset and the long addressed
  219. * is relocated. Note that 00000010 means 1 word distance.
  220. * B==0bXXXXXXX1:
  221. * illegal
  222. */
  223. last = 0;
  224. curr = 0;
  225. for (sect = S_MIN; sect <= S_MIN+2; sect++) {
  226. base = outsect[sect-S_MIN].os_base;
  227. for (;cnt > 0 && ap->or_sect == sect; ap++, cnt--) {
  228. if (ap->or_type & RELPC ||
  229. ap->or_nami == outhead.oh_nname) {
  230. continue;
  231. }
  232. assert(ap->or_type & RELO4);
  233. curr = base + ap->or_addr;
  234. if (last == 0) {
  235. last = curr;
  236. cvlong(&curr);
  237. *((long *) b) = curr;
  238. b += 4;
  239. }
  240. else {
  241. while (curr - last > 255) {
  242. *b++ = 1;
  243. last += 254;
  244. }
  245. *b++ = curr - last;
  246. last = curr;
  247. }
  248. }
  249. assert(cnt == 0 || ap->or_sect > sect);
  250. }
  251. assert(cnt == 0);
  252. if (cnt = (b - bp)) {
  253. *b++ = '\0';
  254. write(output, bp, (int) cnt+1);
  255. }
  256. else write(output, "\0\0\0", 4);
  257. free((char *) ACKrelo);
  258. free(bp);
  259. }
  260. long
  261. chmem(str, old)
  262. char *str;
  263. long old;
  264. {
  265. register long num, new;
  266. long atol();
  267. num = atol(str+1);
  268. if (num == 0)
  269. fatal("bad chmem amount %s\n", str+1);
  270. switch (str[0]) {
  271. case '-':
  272. new = old - num; break;
  273. case '+':
  274. new = old + num; break;
  275. case '=':
  276. new = num; break;
  277. }
  278. return(new);
  279. }
  280. cvlong(l)
  281. long *l;
  282. {
  283. long x = *l;
  284. char *p = (char *) l;
  285. *p++ = x >> 24;
  286. *p++ = x >> 16;
  287. *p++ = x >> 8;
  288. *p = x;
  289. }
  290. /* VARARGS1 */
  291. fatal(s, a1, a2)
  292. char *s;
  293. {
  294. fprintf(stderr,"%s: ",program) ;
  295. fprintf(stderr, s, a1, a2);
  296. if (outputfile_created)
  297. unlink(output_file);
  298. exit(-1);
  299. }
  300. rd_fatal() { fatal("read error.\n"); }