outas86.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639
  1. /* ----------------------------------------------------------------------- *
  2. *
  3. * Copyright 1996-2017 The NASM Authors - All Rights Reserved
  4. * See the file AUTHORS included with the NASM distribution for
  5. * the specific copyright holders.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following
  9. * conditions are met:
  10. *
  11. * * Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * * Redistributions in binary form must reproduce the above
  14. * copyright notice, this list of conditions and the following
  15. * disclaimer in the documentation and/or other materials provided
  16. * with the distribution.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
  19. * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  20. * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  21. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  22. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  23. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  25. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  26. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  27. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  28. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  29. * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  30. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31. *
  32. * ----------------------------------------------------------------------- */
  33. /*
  34. * outas86.c output routines for the Netwide Assembler to produce
  35. * Linux as86 (bin86-0.3) object files
  36. */
  37. #include "compiler.h"
  38. #include <stdio.h>
  39. #include <stdlib.h>
  40. #include <string.h>
  41. #include <ctype.h>
  42. #include "nasm.h"
  43. #include "nasmlib.h"
  44. #include "error.h"
  45. #include "saa.h"
  46. #include "raa.h"
  47. #include "outform.h"
  48. #include "outlib.h"
  49. #ifdef OF_AS86
  50. struct Piece {
  51. struct Piece *next;
  52. int type; /* 0 = absolute, 1 = seg, 2 = sym */
  53. int32_t offset; /* relative offset */
  54. int number; /* symbol/segment number (4=bss) */
  55. int32_t bytes; /* size of reloc or of absolute data */
  56. bool relative; /* relative address? */
  57. };
  58. struct Symbol {
  59. int32_t strpos; /* string table position of name */
  60. int flags; /* symbol flags */
  61. int segment; /* 4=bss at this point */
  62. int32_t value; /* address, or COMMON variable size */
  63. };
  64. /*
  65. * Section IDs - used in Piece.number and Symbol.segment.
  66. */
  67. #define SECT_TEXT 0 /* text section */
  68. #define SECT_DATA 3 /* data section */
  69. #define SECT_BSS 4 /* bss section */
  70. /*
  71. * Flags used in Symbol.flags.
  72. */
  73. #define SYM_ENTRY (1<<8)
  74. #define SYM_EXPORT (1<<7)
  75. #define SYM_IMPORT (1<<6)
  76. #define SYM_ABSOLUTE (1<<4)
  77. struct Section {
  78. struct SAA *data;
  79. uint32_t datalen, size, len;
  80. int32_t index;
  81. struct Piece *head, *last, **tail;
  82. };
  83. static struct Section stext, sdata;
  84. static uint32_t bsslen;
  85. static int32_t bssindex;
  86. static struct SAA *syms;
  87. static uint32_t nsyms;
  88. static struct RAA *bsym;
  89. static struct SAA *strs;
  90. static size_t strslen;
  91. static int as86_reloc_size;
  92. static void as86_write(void);
  93. static void as86_write_section(struct Section *, int);
  94. static size_t as86_add_string(const char *name);
  95. static void as86_sect_write(struct Section *, const uint8_t *,
  96. uint32_t);
  97. static void as86_init(void)
  98. {
  99. stext.data = saa_init(1L);
  100. stext.datalen = 0L;
  101. stext.head = stext.last = NULL;
  102. stext.tail = &stext.head;
  103. sdata.data = saa_init(1L);
  104. sdata.datalen = 0L;
  105. sdata.head = sdata.last = NULL;
  106. sdata.tail = &sdata.head;
  107. bsslen =
  108. stext.len = stext.datalen = stext.size =
  109. sdata.len = sdata.datalen = sdata.size = 0;
  110. stext.index = seg_alloc();
  111. sdata.index = seg_alloc();
  112. bssindex = seg_alloc();
  113. syms = saa_init((int32_t)sizeof(struct Symbol));
  114. nsyms = 0;
  115. bsym = raa_init();
  116. strs = saa_init(1L);
  117. strslen = 0;
  118. /* as86 module name = input file minus extension */
  119. as86_add_string(filename_set_extension(inname, ""));
  120. }
  121. static void as86_cleanup(void)
  122. {
  123. struct Piece *p;
  124. as86_write();
  125. saa_free(stext.data);
  126. while (stext.head) {
  127. p = stext.head;
  128. stext.head = stext.head->next;
  129. nasm_free(p);
  130. }
  131. saa_free(sdata.data);
  132. while (sdata.head) {
  133. p = sdata.head;
  134. sdata.head = sdata.head->next;
  135. nasm_free(p);
  136. }
  137. saa_free(syms);
  138. raa_free(bsym);
  139. saa_free(strs);
  140. }
  141. static int32_t as86_section_names(char *name, int pass, int *bits)
  142. {
  143. (void)pass;
  144. /*
  145. * Default is 16 bits.
  146. */
  147. if (!name) {
  148. *bits = 16;
  149. return stext.index;
  150. }
  151. if (!strcmp(name, ".text"))
  152. return stext.index;
  153. else if (!strcmp(name, ".data"))
  154. return sdata.index;
  155. else if (!strcmp(name, ".bss"))
  156. return bssindex;
  157. else
  158. return NO_SEG;
  159. }
  160. static size_t as86_add_string(const char *name)
  161. {
  162. size_t pos = strslen;
  163. size_t length = strlen(name);
  164. saa_wbytes(strs, name, length + 1);
  165. strslen += 1 + length;
  166. return pos;
  167. }
  168. static void as86_deflabel(char *name, int32_t segment, int64_t offset,
  169. int is_global, char *special)
  170. {
  171. bool is_start = false;
  172. struct Symbol *sym;
  173. if (special)
  174. nasm_error(ERR_NONFATAL, "as86 format does not support any"
  175. " special symbol types");
  176. if (name[0] == '.' && name[1] == '.' && name[2] != '@') {
  177. if (strcmp(name, "..start")) {
  178. nasm_error(ERR_NONFATAL, "unrecognised special symbol `%s'", name);
  179. return;
  180. } else {
  181. is_start = true;
  182. }
  183. }
  184. sym = saa_wstruct(syms);
  185. sym->strpos = as86_add_string(name);
  186. sym->flags = 0;
  187. if (is_start)
  188. sym->flags = SYM_ENTRY;
  189. if (segment == NO_SEG)
  190. sym->flags |= SYM_ABSOLUTE, sym->segment = 0;
  191. else if (segment == stext.index)
  192. sym->segment = SECT_TEXT;
  193. else if (segment == sdata.index)
  194. sym->segment = SECT_DATA;
  195. else if (segment == bssindex)
  196. sym->segment = SECT_BSS;
  197. else {
  198. sym->flags |= SYM_IMPORT;
  199. sym->segment = 15;
  200. }
  201. if (is_global == 2)
  202. sym->segment = 3; /* already have IMPORT */
  203. if (is_global && !(sym->flags & SYM_IMPORT))
  204. sym->flags |= SYM_EXPORT;
  205. sym->value = offset;
  206. /*
  207. * define the references from external-symbol segment numbers
  208. * to these symbol records.
  209. */
  210. if (segment != NO_SEG && segment != stext.index &&
  211. segment != sdata.index && segment != bssindex)
  212. bsym = raa_write(bsym, segment, nsyms);
  213. nsyms++;
  214. }
  215. static void as86_add_piece(struct Section *sect, int type, int32_t offset,
  216. int32_t segment, int32_t bytes, int relative)
  217. {
  218. struct Piece *p;
  219. sect->len += bytes;
  220. if (type == 0 && sect->last && sect->last->type == 0) {
  221. sect->last->bytes += bytes;
  222. return;
  223. }
  224. p = sect->last = *sect->tail = nasm_malloc(sizeof(struct Piece));
  225. sect->tail = &p->next;
  226. p->next = NULL;
  227. p->type = type;
  228. p->offset = offset;
  229. p->bytes = bytes;
  230. p->relative = relative;
  231. if (type == 1 && segment == stext.index)
  232. p->number = SECT_TEXT;
  233. else if (type == 1 && segment == sdata.index)
  234. p->number = SECT_DATA;
  235. else if (type == 1 && segment == bssindex)
  236. p->number = SECT_BSS;
  237. else if (type == 1)
  238. p->number = raa_read(bsym, segment), p->type = 2;
  239. }
  240. static void as86_out(int32_t segto, const void *data,
  241. enum out_type type, uint64_t size,
  242. int32_t segment, int32_t wrt)
  243. {
  244. struct Section *s;
  245. int32_t offset;
  246. uint8_t mydata[4], *p;
  247. if (wrt != NO_SEG) {
  248. wrt = NO_SEG; /* continue to do _something_ */
  249. nasm_error(ERR_NONFATAL, "WRT not supported by as86 output format");
  250. }
  251. /*
  252. * handle absolute-assembly (structure definitions)
  253. */
  254. if (segto == NO_SEG) {
  255. if (type != OUT_RESERVE)
  256. nasm_error(ERR_NONFATAL, "attempt to assemble code in [ABSOLUTE]"
  257. " space");
  258. return;
  259. }
  260. if (segto == stext.index)
  261. s = &stext;
  262. else if (segto == sdata.index)
  263. s = &sdata;
  264. else if (segto == bssindex)
  265. s = NULL;
  266. else {
  267. nasm_error(ERR_WARNING, "attempt to assemble code in"
  268. " segment %d: defaulting to `.text'", segto);
  269. s = &stext;
  270. }
  271. if (!s && type != OUT_RESERVE) {
  272. nasm_error(ERR_WARNING, "attempt to initialize memory in the"
  273. " BSS section: ignored");
  274. bsslen += realsize(type, size);
  275. return;
  276. }
  277. memset(mydata, 0, sizeof(mydata));
  278. if (type == OUT_RESERVE) {
  279. if (s) {
  280. nasm_error(ERR_WARNING, "uninitialized space declared in"
  281. " %s section: zeroing",
  282. (segto == stext.index ? "code" : "data"));
  283. as86_sect_write(s, NULL, size);
  284. as86_add_piece(s, 0, 0L, 0L, size, 0);
  285. } else
  286. bsslen += size;
  287. } else if (type == OUT_RAWDATA) {
  288. if (segment != NO_SEG)
  289. nasm_panic(0, "OUT_RAWDATA with other than NO_SEG");
  290. as86_sect_write(s, data, size);
  291. as86_add_piece(s, 0, 0L, 0L, size, 0);
  292. } else if (type == OUT_ADDRESS) {
  293. int asize = abs((int)size);
  294. if (segment != NO_SEG) {
  295. if (segment % 2) {
  296. nasm_error(ERR_NONFATAL, "as86 format does not support"
  297. " segment base references");
  298. } else {
  299. offset = *(int64_t *)data;
  300. as86_add_piece(s, 1, offset, segment, asize, 0);
  301. }
  302. } else {
  303. p = mydata;
  304. WRITELONG(p, *(int64_t *)data);
  305. as86_sect_write(s, data, asize);
  306. as86_add_piece(s, 0, 0L, 0L, asize, 0);
  307. }
  308. } else if (type == OUT_REL2ADR) {
  309. if (segment == segto)
  310. nasm_panic(0, "intra-segment OUT_REL2ADR");
  311. if (segment != NO_SEG) {
  312. if (segment % 2) {
  313. nasm_error(ERR_NONFATAL, "as86 format does not support"
  314. " segment base references");
  315. } else {
  316. offset = *(int64_t *)data;
  317. as86_add_piece(s, 1, offset - size + 2, segment, 2L,
  318. 1);
  319. }
  320. }
  321. } else if (type == OUT_REL4ADR) {
  322. if (segment == segto)
  323. nasm_panic(0, "intra-segment OUT_REL4ADR");
  324. if (segment != NO_SEG) {
  325. if (segment % 2) {
  326. nasm_error(ERR_NONFATAL, "as86 format does not support"
  327. " segment base references");
  328. } else {
  329. offset = *(int64_t *)data;
  330. as86_add_piece(s, 1, offset - size + 4, segment, 4L,
  331. 1);
  332. }
  333. }
  334. }
  335. }
  336. static void as86_write(void)
  337. {
  338. uint32_t i;
  339. int32_t symlen, seglen, segsize;
  340. /*
  341. * First, go through the symbol records working out how big
  342. * each will be. Also fix up BSS references at this time, and
  343. * set the flags words up completely.
  344. */
  345. symlen = 0;
  346. saa_rewind(syms);
  347. for (i = 0; i < nsyms; i++) {
  348. struct Symbol *sym = saa_rstruct(syms);
  349. if (sym->segment == SECT_BSS)
  350. sym->segment = SECT_DATA, sym->value += sdata.len;
  351. sym->flags |= sym->segment;
  352. if (sym->value == 0)
  353. sym->flags |= 0 << 14, symlen += 4;
  354. else if (sym->value >= 0 && sym->value <= 255)
  355. sym->flags |= 1 << 14, symlen += 5;
  356. else if (sym->value >= 0 && sym->value <= 65535L)
  357. sym->flags |= 2 << 14, symlen += 6;
  358. else
  359. sym->flags |= 3 << 14, symlen += 8;
  360. }
  361. /*
  362. * Now do the same for the segments, and get the segment size
  363. * descriptor word at the same time.
  364. */
  365. seglen = segsize = 0;
  366. if ((uint32_t)stext.len > 65535L)
  367. segsize |= 0x03000000L, seglen += 4;
  368. else
  369. segsize |= 0x02000000L, seglen += 2;
  370. if ((uint32_t)sdata.len > 65535L)
  371. segsize |= 0xC0000000L, seglen += 4;
  372. else
  373. segsize |= 0x80000000L, seglen += 2;
  374. /*
  375. * Emit the as86 header.
  376. */
  377. fwriteint32_t(0x000186A3L, ofile);
  378. fputc(0x2A, ofile);
  379. fwriteint32_t(27 + symlen + seglen + strslen, ofile); /* header length */
  380. fwriteint32_t(stext.len + sdata.len + bsslen, ofile);
  381. fwriteint16_t(strslen, ofile);
  382. fwriteint16_t(0, ofile); /* class = revision = 0 */
  383. fwriteint32_t(0x55555555L, ofile); /* segment max sizes: always this */
  384. fwriteint32_t(segsize, ofile); /* segment size descriptors */
  385. if (segsize & 0x01000000L)
  386. fwriteint32_t(stext.len, ofile);
  387. else
  388. fwriteint16_t(stext.len, ofile);
  389. if (segsize & 0x40000000L)
  390. fwriteint32_t(sdata.len + bsslen, ofile);
  391. else
  392. fwriteint16_t(sdata.len + bsslen, ofile);
  393. fwriteint16_t(nsyms, ofile);
  394. /*
  395. * Write the symbol table.
  396. */
  397. saa_rewind(syms);
  398. for (i = 0; i < nsyms; i++) {
  399. struct Symbol *sym = saa_rstruct(syms);
  400. fwriteint16_t(sym->strpos, ofile);
  401. fwriteint16_t(sym->flags, ofile);
  402. switch (sym->flags & (3 << 14)) {
  403. case 0 << 14:
  404. break;
  405. case 1 << 14:
  406. fputc(sym->value, ofile);
  407. break;
  408. case 2 << 14:
  409. fwriteint16_t(sym->value, ofile);
  410. break;
  411. case 3 << 14:
  412. fwriteint32_t(sym->value, ofile);
  413. break;
  414. }
  415. }
  416. /*
  417. * Write out the string table.
  418. */
  419. saa_fpwrite(strs, ofile);
  420. /*
  421. * Write the program text.
  422. */
  423. as86_reloc_size = -1;
  424. as86_write_section(&stext, SECT_TEXT);
  425. as86_write_section(&sdata, SECT_DATA);
  426. /*
  427. * Append the BSS section to the .data section
  428. */
  429. if (bsslen > 65535L) {
  430. fputc(0x13, ofile);
  431. fwriteint32_t(bsslen, ofile);
  432. } else if (bsslen > 255) {
  433. fputc(0x12, ofile);
  434. fwriteint16_t(bsslen, ofile);
  435. } else if (bsslen) {
  436. fputc(0x11, ofile);
  437. fputc(bsslen, ofile);
  438. }
  439. fputc(0, ofile); /* termination */
  440. }
  441. static void as86_set_rsize(int size)
  442. {
  443. if (as86_reloc_size != size) {
  444. switch (as86_reloc_size = size) {
  445. case 1:
  446. fputc(0x01, ofile);
  447. break;
  448. case 2:
  449. fputc(0x02, ofile);
  450. break;
  451. case 4:
  452. fputc(0x03, ofile);
  453. break;
  454. default:
  455. nasm_panic(0, "bizarre relocation size %d", size);
  456. break;
  457. }
  458. }
  459. }
  460. static void as86_write_section(struct Section *sect, int index)
  461. {
  462. struct Piece *p;
  463. uint32_t s;
  464. int32_t length;
  465. fputc(0x20 + index, ofile); /* select the right section */
  466. saa_rewind(sect->data);
  467. for (p = sect->head; p; p = p->next)
  468. switch (p->type) {
  469. case 0:
  470. /*
  471. * Absolute data. Emit it in chunks of at most 64
  472. * bytes.
  473. */
  474. length = p->bytes;
  475. do {
  476. char buf[64];
  477. int32_t tmplen = (length > 64 ? 64 : length);
  478. fputc(0x40 | (tmplen & 0x3F), ofile);
  479. saa_rnbytes(sect->data, buf, tmplen);
  480. nasm_write(buf, tmplen, ofile);
  481. length -= tmplen;
  482. } while (length > 0);
  483. break;
  484. case 1:
  485. /*
  486. * A segment-type relocation. First fix up the BSS.
  487. */
  488. if (p->number == SECT_BSS)
  489. p->number = SECT_DATA, p->offset += sdata.len;
  490. as86_set_rsize(p->bytes);
  491. fputc(0x80 | (p->relative ? 0x20 : 0) | p->number, ofile);
  492. if (as86_reloc_size == 2)
  493. fwriteint16_t(p->offset, ofile);
  494. else
  495. fwriteint32_t(p->offset, ofile);
  496. break;
  497. case 2:
  498. /*
  499. * A symbol-type relocation.
  500. */
  501. as86_set_rsize(p->bytes);
  502. s = p->offset;
  503. if (s > 65535L)
  504. s = 3;
  505. else if (s > 255)
  506. s = 2;
  507. else if (s > 0)
  508. s = 1;
  509. else
  510. s = 0;
  511. fputc(0xC0 |
  512. (p->relative ? 0x20 : 0) |
  513. (p->number > 255 ? 0x04 : 0) | s, ofile);
  514. if (p->number > 255)
  515. fwriteint16_t(p->number, ofile);
  516. else
  517. fputc(p->number, ofile);
  518. switch (s) {
  519. case 0:
  520. break;
  521. case 1:
  522. fputc(p->offset, ofile);
  523. break;
  524. case 2:
  525. fwriteint16_t(p->offset, ofile);
  526. break;
  527. case 3:
  528. fwriteint32_t(p->offset, ofile);
  529. break;
  530. }
  531. break;
  532. }
  533. }
  534. static void as86_sect_write(struct Section *sect,
  535. const uint8_t *data, uint32_t len)
  536. {
  537. saa_wbytes(sect->data, data, len);
  538. sect->datalen += len;
  539. }
  540. static int32_t as86_segbase(int32_t segment)
  541. {
  542. return segment;
  543. }
  544. extern macros_t as86_stdmac[];
  545. const struct ofmt of_as86 = {
  546. "Linux as86 (bin86 version 0.3) object files",
  547. "as86",
  548. ".o",
  549. 0,
  550. 32,
  551. null_debug_arr,
  552. &null_debug_form,
  553. as86_stdmac,
  554. as86_init,
  555. null_reset,
  556. nasm_do_legacy_output,
  557. as86_out,
  558. as86_deflabel,
  559. as86_section_names,
  560. NULL,
  561. null_sectalign,
  562. as86_segbase,
  563. null_directive,
  564. as86_cleanup,
  565. NULL /* pragma list */
  566. };
  567. #endif /* OF_AS86 */