outdbg.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494
  1. /* ----------------------------------------------------------------------- *
  2. *
  3. * Copyright 1996-2018 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. * outdbg.c output routines for the Netwide Assembler to produce
  35. * a debugging trace
  36. */
  37. #include "compiler.h"
  38. #include <stdio.h>
  39. #include <stdlib.h>
  40. #include <string.h>
  41. #include <ctype.h>
  42. #include <errno.h>
  43. #include "nasm.h"
  44. #include "nasmlib.h"
  45. #include "outform.h"
  46. #include "outlib.h"
  47. #include "insns.h"
  48. #ifdef OF_DBG
  49. struct Section {
  50. struct Section *next;
  51. int32_t number;
  52. char *name;
  53. } *dbgsect;
  54. static unsigned long dbg_max_data_dump = 128;
  55. static bool section_labels = true;
  56. static bool subsections_via_symbols = false;
  57. static int32_t init_seg;
  58. const struct ofmt of_dbg;
  59. static void dbg_init(void)
  60. {
  61. dbgsect = NULL;
  62. fprintf(ofile, "NASM Output format debug dump\n");
  63. fprintf(ofile, "input file = %s\n", inname);
  64. fprintf(ofile, "output file = %s\n", outname);
  65. init_seg = seg_alloc();
  66. }
  67. static void dbg_reset(void)
  68. {
  69. fprintf(ofile, "*** pass reset: pass0 = %d, passn = %"PRId64"\n",
  70. pass0, passn);
  71. }
  72. static void dbg_cleanup(void)
  73. {
  74. dfmt->cleanup();
  75. while (dbgsect) {
  76. struct Section *tmp = dbgsect;
  77. dbgsect = dbgsect->next;
  78. nasm_free(tmp->name);
  79. nasm_free(tmp);
  80. }
  81. }
  82. static int32_t dbg_add_section(char *name, int pass, int *bits,
  83. const char *whatwecallit)
  84. {
  85. int seg;
  86. /*
  87. * We must have an initial default: let's make it 16.
  88. */
  89. if (!name)
  90. *bits = 16;
  91. if (!name) {
  92. fprintf(ofile, "section_name on init: returning %d\n", init_seg);
  93. seg = init_seg;
  94. } else {
  95. int n = strcspn(name, " \t");
  96. char *sname = nasm_strndup(name, n);
  97. char *tail = nasm_skip_spaces(name+n);
  98. struct Section *s;
  99. seg = NO_SEG;
  100. for (s = dbgsect; s; s = s->next)
  101. if (!strcmp(s->name, sname))
  102. seg = s->number;
  103. if (seg == NO_SEG) {
  104. s = nasm_malloc(sizeof(*s));
  105. s->name = sname;
  106. s->number = seg = seg_alloc();
  107. s->next = dbgsect;
  108. dbgsect = s;
  109. fprintf(ofile, "%s %s (%s) pass %d: returning %d\n",
  110. whatwecallit, name, tail, pass, seg);
  111. if (section_labels)
  112. backend_label(s->name, s->number + 1, 0);
  113. }
  114. }
  115. return seg;
  116. }
  117. static int32_t dbg_section_names(char *name, int pass, int *bits)
  118. {
  119. return dbg_add_section(name, pass, bits, "section_names");
  120. }
  121. static int32_t dbg_herelabel(const char *name, enum label_type type,
  122. int32_t oldseg, int32_t *subsection,
  123. bool *copyoffset)
  124. {
  125. int32_t newseg = oldseg;
  126. if (subsections_via_symbols && type != LBL_LOCAL) {
  127. newseg = *subsection;
  128. if (newseg == NO_SEG) {
  129. newseg = *subsection = seg_alloc();
  130. *copyoffset = true; /* Minic MachO for now */
  131. }
  132. }
  133. fprintf(ofile, "herelabel %s type %d (seg %08x) -> %08x\n",
  134. name, type, oldseg, newseg);
  135. return newseg;
  136. }
  137. static void dbg_deflabel(char *name, int32_t segment, int64_t offset,
  138. int is_global, char *special)
  139. {
  140. fprintf(ofile, "deflabel %s := %08"PRIx32":%016"PRIx64" %s (%d)%s%s\n",
  141. name, segment, offset,
  142. is_global == 2 ? "common" : is_global ? "global" : "local",
  143. is_global, special ? ": " : "", special);
  144. }
  145. static const char *out_type(enum out_type type)
  146. {
  147. static const char *out_types[] = {
  148. "rawdata",
  149. "reserve",
  150. "zerodata",
  151. "address",
  152. "reladdr",
  153. "segment"
  154. };
  155. static char invalid_buf[64];
  156. if (type >= sizeof(out_types)/sizeof(out_types[0])) {
  157. sprintf(invalid_buf, "[invalid type %d]", type);
  158. return invalid_buf;
  159. }
  160. return out_types[type];
  161. }
  162. static const char *out_sign(enum out_sign sign)
  163. {
  164. static const char *out_signs[] = {
  165. "wrap",
  166. "signed",
  167. "unsigned"
  168. };
  169. static char invalid_buf[64];
  170. if (sign >= sizeof(out_signs)/sizeof(out_signs[0])) {
  171. sprintf(invalid_buf, "[invalid sign %d]", sign);
  172. return invalid_buf;
  173. }
  174. return out_signs[sign];
  175. }
  176. static void dbg_out(const struct out_data *data)
  177. {
  178. fprintf(ofile,
  179. "out to %"PRIx32":%"PRIx64" %s %s bits %d insoffs %d/%d "
  180. "size %"PRIu64,
  181. data->segment, data->offset,
  182. out_type(data->type), out_sign(data->sign),
  183. data->bits, data->insoffs, data->inslen, data->size);
  184. if (data->itemp) {
  185. fprintf(ofile, " ins %s(%d)",
  186. nasm_insn_names[data->itemp->opcode], data->itemp->operands);
  187. } else {
  188. fprintf(ofile, " no ins (plain data)");
  189. }
  190. if (data->type == OUT_ADDRESS || data->type == OUT_RELADDR ||
  191. data->type == OUT_SEGMENT) {
  192. fprintf(ofile, " target %"PRIx32":%"PRIx64,
  193. data->tsegment, data->toffset);
  194. if (data->twrt != NO_SEG)
  195. fprintf(ofile, " wrt %"PRIx32, data->twrt);
  196. }
  197. if (data->type == OUT_RELADDR)
  198. fprintf(ofile, " relbase %"PRIx64, data->relbase);
  199. putc('\n', ofile);
  200. if (data->type == OUT_RAWDATA) {
  201. if ((size_t)data->size != data->size) {
  202. fprintf(ofile, " data: <error: impossible size>\n");
  203. } else if (!data->data) {
  204. fprintf(ofile, " data: <error: null pointer>\n");
  205. } else if (dbg_max_data_dump != -1UL &&
  206. data->size > dbg_max_data_dump) {
  207. fprintf(ofile, " data: <%"PRIu64" bytes>\n", data->size);
  208. } else {
  209. size_t i, j;
  210. const uint8_t *bytes = data->data;
  211. for (i = 0; i < data->size; i += 16) {
  212. fprintf(ofile, " data:");
  213. for (j = 0; j < 16; j++) {
  214. if (i+j >= data->size)
  215. fprintf(ofile, " ");
  216. else
  217. fprintf(ofile, "%c%02x",
  218. (j == 8) ? '-' : ' ', bytes[i+j]);
  219. }
  220. fprintf(ofile," ");
  221. for (j = 0; j < 16; j++) {
  222. if (i+j >= data->size) {
  223. putc(' ', ofile);
  224. } else {
  225. if (bytes[i+j] >= 32 && bytes[i+j] <= 126)
  226. putc(bytes[i+j], ofile);
  227. else
  228. putc('.', ofile);
  229. }
  230. }
  231. putc('\n', ofile);
  232. }
  233. }
  234. }
  235. /* This is probably the only place were we'll call this this way... */
  236. nasm_do_legacy_output(data);
  237. }
  238. static void dbg_legacy_out(int32_t segto, const void *data,
  239. enum out_type type, uint64_t size,
  240. int32_t segment, int32_t wrt)
  241. {
  242. int32_t ldata;
  243. if (type == OUT_ADDRESS)
  244. fprintf(ofile, " legacy: out to %"PRIx32", len = %d: ",
  245. segto, (int)abs((int)size));
  246. else
  247. fprintf(ofile, " legacy: out to %"PRIx32", len = %"PRId64" (0x%"PRIx64"): ",
  248. segto, (int64_t)size, size);
  249. switch (type) {
  250. case OUT_RESERVE:
  251. fprintf(ofile, "reserved.\n");
  252. break;
  253. case OUT_RAWDATA:
  254. fprintf(ofile, "rawdata\n"); /* Already have a data dump */
  255. break;
  256. case OUT_ADDRESS:
  257. ldata = *(int64_t *)data;
  258. fprintf(ofile, "addr %08"PRIx32" (seg %08"PRIx32", wrt %08"PRIx32")\n",
  259. ldata, segment, wrt);
  260. break;
  261. case OUT_REL1ADR:
  262. fprintf(ofile, "rel1adr %02"PRIx8" (seg %08"PRIx32")\n",
  263. (uint8_t)*(int64_t *)data, segment);
  264. break;
  265. case OUT_REL2ADR:
  266. fprintf(ofile, "rel2adr %04"PRIx16" (seg %08"PRIx32")\n",
  267. (uint16_t)*(int64_t *)data, segment);
  268. break;
  269. case OUT_REL4ADR:
  270. fprintf(ofile, "rel4adr %08"PRIx32" (seg %08"PRIx32")\n",
  271. (uint32_t)*(int64_t *)data,
  272. segment);
  273. break;
  274. case OUT_REL8ADR:
  275. fprintf(ofile, "rel8adr %016"PRIx64" (seg %08"PRIx32")\n",
  276. (uint64_t)*(int64_t *)data, segment);
  277. break;
  278. default:
  279. fprintf(ofile, "unknown\n");
  280. break;
  281. }
  282. }
  283. static void dbg_sectalign(int32_t seg, unsigned int value)
  284. {
  285. fprintf(ofile, "set alignment (%d) for segment (%u)\n",
  286. seg, value);
  287. }
  288. static int32_t dbg_segbase(int32_t segment)
  289. {
  290. return segment;
  291. }
  292. static enum directive_result
  293. dbg_directive(enum directive directive, char *value, int pass)
  294. {
  295. switch (directive) {
  296. /*
  297. * The .obj GROUP directive is nontrivial to emulate in a macro.
  298. * It effectively creates a "pseudo-section" containing the first
  299. * space-separated argument; the rest we ignore.
  300. */
  301. case D_GROUP:
  302. {
  303. int dummy;
  304. dbg_add_section(value, pass, &dummy, "directive:group");
  305. break;
  306. }
  307. default:
  308. break;
  309. }
  310. fprintf(ofile, "directive [%s] value [%s] (pass %d)\n",
  311. directive_dname(directive), value, pass);
  312. return DIRR_OK;
  313. }
  314. static enum directive_result
  315. dbg_pragma(const struct pragma *pragma);
  316. static const struct pragma_facility dbg_pragma_list[] = {
  317. { NULL, dbg_pragma }
  318. };
  319. static enum directive_result
  320. dbg_pragma(const struct pragma *pragma)
  321. {
  322. fprintf(ofile, "pragma %s(%s) %s[%s] %s\n",
  323. pragma->facility_name,
  324. pragma->facility->name ? pragma->facility->name : "<default>",
  325. pragma->opname, directive_dname(pragma->opcode),
  326. pragma->tail);
  327. if (pragma->facility == &dbg_pragma_list[0]) {
  328. switch (pragma->opcode) {
  329. case D_MAXDUMP:
  330. if (!nasm_stricmp(pragma->tail, "unlimited")) {
  331. dbg_max_data_dump = -1UL;
  332. } else {
  333. char *ep;
  334. unsigned long arg;
  335. errno = 0;
  336. arg = strtoul(pragma->tail, &ep, 0);
  337. if (errno || *nasm_skip_spaces(ep)) {
  338. nasm_error(ERR_WARNING | WARN_BAD_PRAGMA | ERR_PASS2,
  339. "invalid %%pragma dbg maxdump argument");
  340. return DIRR_ERROR;
  341. } else {
  342. dbg_max_data_dump = arg;
  343. }
  344. }
  345. break;
  346. case D_NOSECLABELS:
  347. section_labels = false;
  348. break;
  349. case D_SUBSECTIONS_VIA_SYMBOLS:
  350. subsections_via_symbols = true;
  351. break;
  352. default:
  353. break;
  354. }
  355. }
  356. return DIRR_OK;
  357. }
  358. static const char * const types[] = {
  359. "unknown", "label", "byte", "word", "dword", "float", "qword", "tbyte"
  360. };
  361. static void dbgdbg_init(void)
  362. {
  363. fprintf(ofile, " With debug info\n");
  364. }
  365. static void dbgdbg_cleanup(void)
  366. {
  367. }
  368. static void dbgdbg_linnum(const char *lnfname, int32_t lineno, int32_t segto)
  369. {
  370. fprintf(ofile, "dbglinenum %s(%"PRId32") segment %"PRIx32"\n",
  371. lnfname, lineno, segto);
  372. }
  373. static void dbgdbg_deflabel(char *name, int32_t segment,
  374. int64_t offset, int is_global, char *special)
  375. {
  376. fprintf(ofile, "dbglabel %s := %08"PRIx32":%016"PRIx64" %s (%d)%s%s\n",
  377. name,
  378. segment, offset,
  379. is_global == 2 ? "common" : is_global ? "global" : "local",
  380. is_global, special ? ": " : "", special);
  381. }
  382. static void dbgdbg_define(const char *type, const char *params)
  383. {
  384. fprintf(ofile, "dbgdirective [%s] value [%s]\n", type, params);
  385. }
  386. static void dbgdbg_output(int output_type, void *param)
  387. {
  388. (void)output_type;
  389. (void)param;
  390. }
  391. static void dbgdbg_typevalue(int32_t type)
  392. {
  393. fprintf(ofile, "new type: %s(%"PRIX32")\n",
  394. types[TYM_TYPE(type) >> 3], TYM_ELEMENTS(type));
  395. }
  396. static const struct pragma_facility dbgdbg_pragma_list[] = {
  397. { "dbgdbg", dbg_pragma },
  398. { NULL, dbg_pragma } /* Won't trigger, "debug" is a reserved ns */
  399. };
  400. static const struct dfmt debug_debug_form = {
  401. "Trace of all info passed to debug stage",
  402. "debug",
  403. dbgdbg_init,
  404. dbgdbg_linnum,
  405. dbgdbg_deflabel,
  406. dbgdbg_define,
  407. dbgdbg_typevalue,
  408. dbgdbg_output,
  409. dbgdbg_cleanup,
  410. dbgdbg_pragma_list
  411. };
  412. static const struct dfmt * const debug_debug_arr[3] = {
  413. &debug_debug_form,
  414. &null_debug_form,
  415. NULL
  416. };
  417. extern macros_t dbg_stdmac[];
  418. const struct ofmt of_dbg = {
  419. "Trace of all info passed to output stage",
  420. "dbg",
  421. ".dbg",
  422. OFMT_TEXT,
  423. 64,
  424. debug_debug_arr,
  425. &debug_debug_form,
  426. dbg_stdmac,
  427. dbg_init,
  428. dbg_reset,
  429. dbg_out,
  430. dbg_legacy_out,
  431. dbg_deflabel,
  432. dbg_section_names,
  433. dbg_herelabel,
  434. dbg_sectalign,
  435. dbg_segbase,
  436. dbg_directive,
  437. dbg_cleanup,
  438. dbg_pragma_list
  439. };
  440. #endif /* OF_DBG */