rdoff.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622
  1. /* ----------------------------------------------------------------------- *
  2. *
  3. * Copyright 1996-2014 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. * rdoff.c library of routines for manipulating rdoff files
  35. */
  36. /* TODO: The functions in this module assume they are running
  37. * on a little-endian machine. This should be fixed to
  38. * make it portable.
  39. */
  40. #include "compiler.h"
  41. #include <stdio.h>
  42. #include <stdlib.h>
  43. #include <string.h>
  44. #include <errno.h>
  45. #include "rdfutils.h"
  46. /*
  47. * Comment this out to allow the module to read & write header record types
  48. * that it isn't aware of. With this defined, unrecognised header records
  49. * will generate error number 8, reported as 'unknown extended header record'.
  50. */
  51. #define STRICT_ERRORS
  52. /* ========================================================================
  53. * Code for memory buffers (for delayed writing of header until we know
  54. * how int32_t it is).
  55. * ======================================================================== */
  56. static memorybuffer *newmembuf(void)
  57. {
  58. memorybuffer *t;
  59. t = nasm_malloc(sizeof(memorybuffer));
  60. if (!t)
  61. return NULL;
  62. t->length = 0;
  63. t->next = NULL;
  64. return t;
  65. }
  66. static void membufwrite(memorybuffer * const b, void *data, int bytes)
  67. {
  68. uint16_t w;
  69. int32_t l;
  70. char *c;
  71. if (b->next) { /* memory buffer full - use next buffer */
  72. membufwrite(b->next, data, bytes);
  73. return;
  74. }
  75. if ((bytes < 0 && b->length - bytes > BUF_BLOCK_LEN)
  76. || (bytes > 0 && b->length + bytes > BUF_BLOCK_LEN)) {
  77. /* buffer full and no next allocated... allocate and initialise next
  78. * buffer */
  79. b->next = newmembuf();
  80. membufwrite(b->next, data, bytes);
  81. return;
  82. }
  83. switch (bytes) {
  84. case -4: /* convert to little-endian */
  85. l = *(int32_t *)data;
  86. b->buffer[b->length++] = l & 0xFF;
  87. l >>= 8;
  88. b->buffer[b->length++] = l & 0xFF;
  89. l >>= 8;
  90. b->buffer[b->length++] = l & 0xFF;
  91. l >>= 8;
  92. b->buffer[b->length++] = l & 0xFF;
  93. break;
  94. case -2:
  95. w = *(uint16_t *) data;
  96. b->buffer[b->length++] = w & 0xFF;
  97. w >>= 8;
  98. b->buffer[b->length++] = w & 0xFF;
  99. break;
  100. default:
  101. c = data;
  102. while (bytes--)
  103. b->buffer[b->length++] = *c++;
  104. break;
  105. }
  106. }
  107. static void membufdump(memorybuffer * b, FILE * fp)
  108. {
  109. if (!b)
  110. return;
  111. nasm_write(b->buffer, b->length, fp);
  112. membufdump(b->next, fp);
  113. }
  114. static int membuflength(memorybuffer * b)
  115. {
  116. if (!b)
  117. return 0;
  118. return b->length + membuflength(b->next);
  119. }
  120. static void freemembuf(memorybuffer * b)
  121. {
  122. if (!b)
  123. return;
  124. freemembuf(b->next);
  125. nasm_free(b);
  126. }
  127. /* =========================================================================
  128. General purpose routines and variables used by the library functions
  129. ========================================================================= */
  130. /*
  131. * translateint32_t() and translateint16_t()
  132. *
  133. * translate from little endian to local representation
  134. */
  135. int32_t translateint32_t(int32_t in)
  136. {
  137. int32_t r;
  138. uint8_t *i;
  139. i = (uint8_t *)&in;
  140. r = i[3];
  141. r = (r << 8) + i[2];
  142. r = (r << 8) + i[1];
  143. r = (r << 8) + *i;
  144. return r;
  145. }
  146. uint16_t translateint16_t(uint16_t in)
  147. {
  148. uint16_t r;
  149. uint8_t *i;
  150. i = (uint8_t *)&in;
  151. r = (i[1] << 8) + i[0];
  152. return r;
  153. }
  154. /* Segment types */
  155. static char *knownsegtypes[8] = {
  156. "NULL", "text", "data", "object comment",
  157. "linked comment", "loader comment",
  158. "symbolic debug", "line number debug"
  159. };
  160. /* Get a textual string describing the segment type */
  161. char *translatesegmenttype(uint16_t type)
  162. {
  163. if (type < 8)
  164. return knownsegtypes[type];
  165. if (type < 0x0020)
  166. return "reserved";
  167. if (type < 0x1000)
  168. return "reserved - Moscow";
  169. if (type < 0x8000)
  170. return "reserved - system dependant";
  171. if (type < 0xFFFF)
  172. return "reserved - other";
  173. if (type == 0xFFFF)
  174. return "invalid type code";
  175. return "type code out of range";
  176. }
  177. /* This signature is written to the start of RDOFF files */
  178. const char *RDOFFId = RDOFF2_SIGNATURE;
  179. /* Error messages. Must correspond to the codes defined in rdoff.h */
  180. const char *rdf_errors[11] = {
  181. /* 0 */ "no error occurred",
  182. /* 1 */ "could not open file",
  183. /* 2 */ "invalid file format",
  184. /* 3 */ "error reading file",
  185. /* 4 */ "unknown error",
  186. /* 5 */ "header not read",
  187. /* 6 */ "out of memory",
  188. /* 7 */ "RDOFF v1 not supported",
  189. /* 8 */ "unknown extended header record",
  190. /* 9 */ "header record of known type but unknown length",
  191. /* 10 */ "no such segment"
  192. };
  193. int rdf_errno = 0;
  194. /* ========================================================================
  195. * Hook for nasm_error() to work
  196. * ======================================================================== */
  197. static void rdoff_verror(int severity, const char *fmt, va_list val)
  198. {
  199. vfprintf(stderr, fmt, val);
  200. if ((severity & ERR_MASK) >= ERR_FATAL)
  201. exit(1);
  202. }
  203. void rdoff_init(void)
  204. {
  205. nasm_set_verror(rdoff_verror);
  206. }
  207. /* ========================================================================
  208. The library functions
  209. ======================================================================== */
  210. int rdfopen(rdffile * f, const char *name)
  211. {
  212. FILE *fp;
  213. fp = fopen(name, "rb");
  214. if (!fp)
  215. return rdf_errno = RDF_ERR_OPEN;
  216. return rdfopenhere(f, fp, NULL, name);
  217. }
  218. int rdfopenhere(rdffile * f, FILE * fp, int *refcount, const char *name)
  219. {
  220. char buf[8];
  221. int32_t initpos;
  222. int32_t l;
  223. uint16_t s;
  224. if (translateint32_t(0x01020304) != 0x01020304) {
  225. /* fix this to be portable! */
  226. fputs("*** this program requires a little endian machine\n",
  227. stderr);
  228. fprintf(stderr, "01020304h = %08"PRIx32"h\n", translateint32_t(0x01020304));
  229. exit(3);
  230. }
  231. f->fp = fp;
  232. initpos = ftell(fp);
  233. /* read header */
  234. if (fread(buf, 1, 6, f->fp) != 6) {
  235. fclose(f->fp);
  236. return rdf_errno = RDF_ERR_READ;
  237. }
  238. buf[6] = 0;
  239. if (strcmp(buf, RDOFFId)) {
  240. fclose(f->fp);
  241. if (!strcmp(buf, "RDOFF1"))
  242. return rdf_errno = RDF_ERR_VER;
  243. return rdf_errno = RDF_ERR_FORMAT;
  244. }
  245. if (fread(&l, 1, 4, f->fp) != 4
  246. || fread(&f->header_len, 1, 4, f->fp) != 4) {
  247. fclose(f->fp);
  248. return rdf_errno = RDF_ERR_READ;
  249. }
  250. f->header_ofs = ftell(f->fp);
  251. f->eof_offset = f->header_ofs + translateint32_t(l) - 4;
  252. if (fseek(f->fp, f->header_len, SEEK_CUR)) {
  253. fclose(f->fp);
  254. return rdf_errno = RDF_ERR_FORMAT; /* seek past end of file...? */
  255. }
  256. if (fread(&s, 1, 2, f->fp) != 2) {
  257. fclose(f->fp);
  258. return rdf_errno = RDF_ERR_READ;
  259. }
  260. f->nsegs = 0;
  261. while (s != 0) {
  262. f->seg[f->nsegs].type = s;
  263. if (fread(&f->seg[f->nsegs].number, 1, 2, f->fp) != 2 ||
  264. fread(&f->seg[f->nsegs].reserved, 1, 2, f->fp) != 2 ||
  265. fread(&f->seg[f->nsegs].length, 1, 4, f->fp) != 4) {
  266. fclose(f->fp);
  267. return rdf_errno = RDF_ERR_READ;
  268. }
  269. f->seg[f->nsegs].offset = ftell(f->fp);
  270. if (fseek(f->fp, f->seg[f->nsegs].length, SEEK_CUR)) {
  271. fclose(f->fp);
  272. return rdf_errno = RDF_ERR_FORMAT;
  273. }
  274. f->nsegs++;
  275. if (fread(&s, 1, 2, f->fp) != 2) {
  276. fclose(f->fp);
  277. return rdf_errno = RDF_ERR_READ;
  278. }
  279. }
  280. if (f->eof_offset != ftell(f->fp) + 8) { /* +8 = skip null segment header */
  281. fprintf(stderr, "warning: eof_offset [%"PRId32"] and actual eof offset "
  282. "[%ld] don't match\n", f->eof_offset, ftell(f->fp) + 8);
  283. }
  284. fseek(f->fp, initpos, SEEK_SET);
  285. f->header_loc = NULL;
  286. f->name = nasm_strdup(name);
  287. f->refcount = refcount;
  288. if (refcount)
  289. (*refcount)++;
  290. return RDF_OK;
  291. }
  292. int rdfclose(rdffile * f)
  293. {
  294. if (!f->refcount || !--(*f->refcount)) {
  295. fclose(f->fp);
  296. f->fp = NULL;
  297. }
  298. nasm_free(f->name);
  299. return 0;
  300. }
  301. /*
  302. * Print the message for last error (from rdf_errno)
  303. */
  304. void rdfperror(const char *app, const char *name)
  305. {
  306. fprintf(stderr, "%s:%s: %s\n", app, name, rdf_errors[rdf_errno]);
  307. if (rdf_errno == RDF_ERR_OPEN || rdf_errno == RDF_ERR_READ) {
  308. perror(app);
  309. }
  310. }
  311. /*
  312. * Find the segment by its number.
  313. * Returns segment array index, or -1 if segment with such number was not found.
  314. */
  315. int rdffindsegment(rdffile * f, int segno)
  316. {
  317. int i;
  318. for (i = 0; i < f->nsegs; i++)
  319. if (f->seg[i].number == segno)
  320. return i;
  321. return -1;
  322. }
  323. /*
  324. * Load the segment. Returns status.
  325. */
  326. int rdfloadseg(rdffile * f, int segment, void *buffer)
  327. {
  328. int32_t fpos;
  329. size_t slen;
  330. switch (segment) {
  331. case RDOFF_HEADER:
  332. fpos = f->header_ofs;
  333. slen = f->header_len;
  334. f->header_loc = (uint8_t *) buffer;
  335. f->header_fp = 0;
  336. break;
  337. default:
  338. if (segment < f->nsegs) {
  339. fpos = f->seg[segment].offset;
  340. slen = f->seg[segment].length;
  341. f->seg[segment].data = (uint8_t *) buffer;
  342. } else {
  343. return rdf_errno = RDF_ERR_SEGMENT;
  344. }
  345. }
  346. if (fseek(f->fp, fpos, SEEK_SET))
  347. return rdf_errno = RDF_ERR_UNKNOWN;
  348. if (fread(buffer, 1, slen, f->fp) != slen)
  349. return rdf_errno = RDF_ERR_READ;
  350. return RDF_OK;
  351. }
  352. /* Macros for reading integers from header in memory */
  353. #define RI8(v) v = f->header_loc[f->header_fp++]
  354. #define RI16(v) { v = (f->header_loc[f->header_fp] + \
  355. (f->header_loc[f->header_fp+1] << 8)); \
  356. f->header_fp += 2; }
  357. #define RI32(v) { v = (f->header_loc[f->header_fp] + \
  358. (f->header_loc[f->header_fp+1] << 8) + \
  359. (f->header_loc[f->header_fp+2] << 16) + \
  360. (f->header_loc[f->header_fp+3] << 24)); \
  361. f->header_fp += 4; }
  362. #define RS(str,max) { for(i=0;i<max;i++){\
  363. RI8(str[i]); if (!str[i]) break;} str[i]=0; }
  364. /*
  365. * Read a header record.
  366. * Returns the address of record, or NULL in case of error.
  367. */
  368. rdfheaderrec *rdfgetheaderrec(rdffile * f)
  369. {
  370. static rdfheaderrec r;
  371. int i;
  372. if (!f->header_loc) {
  373. rdf_errno = RDF_ERR_HEADER;
  374. return NULL;
  375. }
  376. if (f->header_fp >= f->header_len)
  377. return 0;
  378. RI8(r.type);
  379. RI8(r.g.reclen);
  380. switch (r.type) {
  381. case RDFREC_RELOC: /* Relocation record */
  382. case RDFREC_SEGRELOC:
  383. if (r.r.reclen != 8) {
  384. rdf_errno = RDF_ERR_RECLEN;
  385. return NULL;
  386. }
  387. RI8(r.r.segment);
  388. RI32(r.r.offset);
  389. RI8(r.r.length);
  390. RI16(r.r.refseg);
  391. break;
  392. case RDFREC_IMPORT: /* Imported symbol record */
  393. case RDFREC_FARIMPORT:
  394. RI8(r.i.flags);
  395. RI16(r.i.segment);
  396. RS(r.i.label, EXIM_LABEL_MAX);
  397. break;
  398. case RDFREC_GLOBAL: /* Exported symbol record */
  399. RI8(r.e.flags);
  400. RI8(r.e.segment);
  401. RI32(r.e.offset);
  402. RS(r.e.label, EXIM_LABEL_MAX);
  403. break;
  404. case RDFREC_DLL: /* DLL record */
  405. RS(r.d.libname, MODLIB_NAME_MAX);
  406. break;
  407. case RDFREC_BSS: /* BSS reservation record */
  408. if (r.r.reclen != 4) {
  409. rdf_errno = RDF_ERR_RECLEN;
  410. return NULL;
  411. }
  412. RI32(r.b.amount);
  413. break;
  414. case RDFREC_MODNAME: /* Module name record */
  415. RS(r.m.modname, MODLIB_NAME_MAX);
  416. break;
  417. case RDFREC_COMMON: /* Common variable */
  418. RI16(r.c.segment);
  419. RI32(r.c.size);
  420. RI16(r.c.align);
  421. RS(r.c.label, EXIM_LABEL_MAX);
  422. break;
  423. default:
  424. #ifdef STRICT_ERRORS
  425. rdf_errno = RDF_ERR_RECTYPE; /* unknown header record */
  426. return NULL;
  427. #else
  428. for (i = 0; i < r.g.reclen; i++)
  429. RI8(r.g.data[i]);
  430. #endif
  431. }
  432. return &r;
  433. }
  434. /*
  435. * Rewind to the beginning of the file
  436. */
  437. void rdfheaderrewind(rdffile * f)
  438. {
  439. f->header_fp = 0;
  440. }
  441. rdf_headerbuf *rdfnewheader(void)
  442. {
  443. rdf_headerbuf *hb = nasm_malloc(sizeof(rdf_headerbuf));
  444. if (hb == NULL)
  445. return NULL;
  446. hb->buf = newmembuf();
  447. hb->nsegments = 0;
  448. hb->seglength = 0;
  449. return hb;
  450. }
  451. int rdfaddheader(rdf_headerbuf * h, rdfheaderrec * r)
  452. {
  453. #ifndef STRICT_ERRORS
  454. int i;
  455. #endif
  456. membufwrite(h->buf, &r->type, 1);
  457. membufwrite(h->buf, &r->g.reclen, 1);
  458. switch (r->type) {
  459. case RDFREC_GENERIC: /* generic */
  460. membufwrite(h->buf, &r->g.data, r->g.reclen);
  461. break;
  462. case RDFREC_RELOC:
  463. case RDFREC_SEGRELOC:
  464. membufwrite(h->buf, &r->r.segment, 1);
  465. membufwrite(h->buf, &r->r.offset, -4);
  466. membufwrite(h->buf, &r->r.length, 1);
  467. membufwrite(h->buf, &r->r.refseg, -2); /* 9 bytes written */
  468. break;
  469. case RDFREC_IMPORT: /* import */
  470. case RDFREC_FARIMPORT:
  471. membufwrite(h->buf, &r->i.flags, 1);
  472. membufwrite(h->buf, &r->i.segment, -2);
  473. membufwrite(h->buf, &r->i.label, strlen(r->i.label) + 1);
  474. break;
  475. case RDFREC_GLOBAL: /* export */
  476. membufwrite(h->buf, &r->e.flags, 1);
  477. membufwrite(h->buf, &r->e.segment, 1);
  478. membufwrite(h->buf, &r->e.offset, -4);
  479. membufwrite(h->buf, &r->e.label, strlen(r->e.label) + 1);
  480. break;
  481. case RDFREC_DLL: /* DLL */
  482. membufwrite(h->buf, &r->d.libname, strlen(r->d.libname) + 1);
  483. break;
  484. case RDFREC_BSS: /* BSS */
  485. membufwrite(h->buf, &r->b.amount, -4);
  486. break;
  487. case RDFREC_MODNAME: /* Module name */
  488. membufwrite(h->buf, &r->m.modname, strlen(r->m.modname) + 1);
  489. break;
  490. default:
  491. #ifdef STRICT_ERRORS
  492. return rdf_errno = RDF_ERR_RECTYPE;
  493. #else
  494. for (i = 0; i < r->g.reclen; i++)
  495. membufwrite(h->buf, r->g.data[i], 1);
  496. #endif
  497. }
  498. return 0;
  499. }
  500. int rdfaddsegment(rdf_headerbuf * h, int32_t seglength)
  501. {
  502. h->nsegments++;
  503. h->seglength += seglength;
  504. return 0;
  505. }
  506. int rdfwriteheader(FILE * fp, rdf_headerbuf * h)
  507. {
  508. int32_t l, l2;
  509. nasm_write(RDOFFId, strlen(RDOFFId), fp);
  510. l = membuflength(h->buf);
  511. l2 = l + 14 + 10 * h->nsegments + h->seglength;
  512. fwriteint32_t(l, fp);
  513. fwriteint32_t(l2, fp);
  514. membufdump(h->buf, fp);
  515. return 0; /* no error handling in here... CHANGE THIS! */
  516. }
  517. void rdfdoneheader(rdf_headerbuf * h)
  518. {
  519. freemembuf(h->buf);
  520. nasm_free(h);
  521. }