stabs-dbgfmt.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511
  1. /*
  2. * Stabs debugging format
  3. *
  4. * Copyright (C) 2003-2007 Michael Urman
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
  16. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  17. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  18. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
  19. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  20. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  21. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  22. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  23. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  24. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  25. * POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. #include <util.h>
  28. #include <libyasm.h>
  29. typedef enum {
  30. N_UNDF = 0x00, /* Undefined */
  31. N_GSYM = 0x20, /* Global symbol */
  32. N_FNAME = 0x22, /* Function name (BSD Fortran) */
  33. N_FUN = 0x24, /* Function name or Text segment variable */
  34. N_STSYM = 0x26, /* Data segment file-scope variable */
  35. N_LCSYM = 0x28, /* BSS segment file-scope variable */
  36. N_MAIN = 0x2a, /* Name of main routine */
  37. N_ROSYM = 0x2c, /* Variable in .rodata section */
  38. N_PC = 0x30, /* Global symbol (Pascal) */
  39. N_SYMS = 0x32, /* Number of symbols (Ultrix V4.0) */
  40. N_NOMAP = 0x34, /* No DST map */
  41. N_OBJ = 0x38, /* Object file (Solaris2) */
  42. N_OPT = 0x3c, /* Debugger options (Solaris2) */
  43. N_RSYM = 0x40, /* Register variable */
  44. N_M2C = 0x42, /* Modula-2 compilation unit */
  45. N_SLINE = 0x44, /* Line numbers in .text segment */
  46. N_DSLINE = 0x46, /* Line numbers in .data segment */
  47. N_BSLINE = 0x48, /* Line numbers in .bss segment */
  48. N_BROWS = 0x48, /* Source code .cb file's path */
  49. N_DEFD = 0x4a, /* GNU Modula-2 definition module dependency */
  50. N_FLINE = 0x4c, /* Function start/body/end line numbers (Solaris2) */
  51. N_EHDECL = 0x50, /* GNU C++ exception variable */
  52. N_MOD2 = 0x50, /* Modula2 info for imc (Ultrix V4.0) */
  53. N_CATCH = 0x54, /* GNU C++ catch clause */
  54. N_SSYM = 0x60, /* Structure or union element */
  55. N_ENDM = 0x62, /* Last stab for module (Solaris2) */
  56. N_SO = 0x64, /* Path and name of source files */
  57. N_LSYM = 0x80, /* Stack variable */
  58. N_BINCL = 0x84, /* Beginning of include file */
  59. N_SOL = 0x84, /* Name of include file */
  60. N_PSYM = 0xa0, /* Parameter variable */
  61. N_EINCL = 0xa2, /* End of include file */
  62. N_ENTRY = 0xa4, /* Alternate entry point */
  63. N_LBRAC = 0xc0, /* Beginning of lexical block */
  64. N_EXCL = 0xc2, /* Placeholder for a deleted include file */
  65. N_SCOPE = 0xc4, /* Modula 2 scope info (Sun) */
  66. N_RBRAC = 0xe0, /* End of lexical block */
  67. N_BCOMM = 0xe2, /* Begin named common block */
  68. N_ECOMM = 0xe4, /* End named common block */
  69. N_ECOML = 0xe8, /* Member of common block */
  70. N_WITH = 0xea, /* Pascal with statement: type,,0,0,offset (Solaris2) */
  71. N_NBTEXT = 0xf0, /* Gould non-base registers */
  72. N_NBDATA = 0xf2, /* Gould non-base registers */
  73. N_NBBSS = 0xf4, /* Gould non-base registers */
  74. N_NBSTS = 0xf6, /* Gould non-base registers */
  75. N_NBLCS = 0xf8 /* Gould non-base registers */
  76. } stabs_stab_type;
  77. typedef struct yasm_dbgfmt_stabs {
  78. yasm_dbgfmt_base dbgfmt; /* base structure */
  79. } yasm_dbgfmt_stabs;
  80. typedef struct {
  81. unsigned long lastline; /* track line and file of bytecodes */
  82. unsigned long curline;
  83. const char *lastfile;
  84. const char *curfile;
  85. unsigned int stablen; /* size of a stab for current machine */
  86. unsigned long stabcount; /* count stored stabs; doesn't include first */
  87. yasm_section *stab; /* sections to which stabs, stabstrs appended */
  88. yasm_section *stabstr;
  89. yasm_bytecode *basebc; /* base bytecode from which to track SLINEs */
  90. yasm_object *object;
  91. yasm_linemap *linemap;
  92. yasm_errwarns *errwarns;
  93. } stabs_info;
  94. typedef struct {
  95. /*@null@*/ yasm_bytecode *bcstr; /* bytecode in stabstr for string */
  96. stabs_stab_type type; /* stab type: N_* */
  97. unsigned char other; /* unused, but stored here anyway */
  98. unsigned short desc; /* description element of a stab */
  99. /*@null@*/ yasm_symrec *symvalue; /* value element needing relocation */
  100. /*@null@*/yasm_bytecode *bcvalue; /* relocated stab's bytecode */
  101. unsigned long value; /* fallthrough value if above NULL */
  102. } stabs_stab;
  103. /* Bytecode callback function prototypes */
  104. static void stabs_bc_str_destroy(void *contents);
  105. static void stabs_bc_str_print(const void *contents, FILE *f, int
  106. indent_level);
  107. static int stabs_bc_str_calc_len
  108. (yasm_bytecode *bc, yasm_bc_add_span_func add_span, void *add_span_data);
  109. static int stabs_bc_str_tobytes
  110. (yasm_bytecode *bc, unsigned char **bufp, unsigned char *bufstart, void *d,
  111. yasm_output_value_func output_value,
  112. /*@null@*/ yasm_output_reloc_func output_reloc);
  113. static void stabs_bc_stab_destroy(void *contents);
  114. static void stabs_bc_stab_print(const void *contents, FILE *f, int
  115. indent_level);
  116. static int stabs_bc_stab_calc_len
  117. (yasm_bytecode *bc, yasm_bc_add_span_func add_span, void *add_span_data);
  118. static int stabs_bc_stab_tobytes
  119. (yasm_bytecode *bc, unsigned char **bufp, unsigned char *bufstart, void *d,
  120. yasm_output_value_func output_value,
  121. /*@null@*/ yasm_output_reloc_func output_reloc);
  122. /* Bytecode callback structures */
  123. static const yasm_bytecode_callback stabs_bc_str_callback = {
  124. stabs_bc_str_destroy,
  125. stabs_bc_str_print,
  126. yasm_bc_finalize_common,
  127. NULL,
  128. stabs_bc_str_calc_len,
  129. yasm_bc_expand_common,
  130. stabs_bc_str_tobytes,
  131. 0
  132. };
  133. static const yasm_bytecode_callback stabs_bc_stab_callback = {
  134. stabs_bc_stab_destroy,
  135. stabs_bc_stab_print,
  136. yasm_bc_finalize_common,
  137. NULL,
  138. stabs_bc_stab_calc_len,
  139. yasm_bc_expand_common,
  140. stabs_bc_stab_tobytes,
  141. 0
  142. };
  143. yasm_dbgfmt_module yasm_stabs_LTX_dbgfmt;
  144. static /*@null@*/ /*@only@*/ yasm_dbgfmt *
  145. stabs_dbgfmt_create(yasm_object *object)
  146. {
  147. yasm_dbgfmt_stabs *dbgfmt_stabs = yasm_xmalloc(sizeof(yasm_dbgfmt_stabs));
  148. dbgfmt_stabs->dbgfmt.module = &yasm_stabs_LTX_dbgfmt;
  149. return (yasm_dbgfmt *)dbgfmt_stabs;
  150. }
  151. static void
  152. stabs_dbgfmt_destroy(/*@only@*/ yasm_dbgfmt *dbgfmt)
  153. {
  154. yasm_xfree(dbgfmt);
  155. }
  156. /* Create and add a new strtab-style string bytecode to a section, updating
  157. * offset on insertion; no optimization necessary */
  158. /* Copies the string, so you must still free yours as normal */
  159. static yasm_bytecode *
  160. stabs_dbgfmt_append_bcstr(yasm_section *sect, const char *str)
  161. {
  162. yasm_bytecode *bc;
  163. bc = yasm_bc_create_common(&stabs_bc_str_callback, yasm__xstrdup(str), 0);
  164. bc->len = (unsigned long)(strlen(str)+1);
  165. bc->offset = yasm_bc_next_offset(yasm_section_bcs_last(sect));
  166. yasm_section_bcs_append(sect, bc);
  167. return bc;
  168. }
  169. /* Create and add a new stab bytecode to a section, updating offset on
  170. * insertion; no optimization necessary. */
  171. /* Requires a string bytecode, or NULL, for its string entry */
  172. static stabs_stab *
  173. stabs_dbgfmt_append_stab(stabs_info *info, yasm_section *sect,
  174. /*@null@*/ yasm_bytecode *bcstr, stabs_stab_type type,
  175. unsigned long desc, /*@null@*/ yasm_symrec *symvalue,
  176. /*@null@*/ yasm_bytecode *bcvalue, unsigned long value)
  177. {
  178. yasm_bytecode *bc;
  179. stabs_stab *stab = yasm_xmalloc(sizeof(stabs_stab));
  180. stab->other = 0;
  181. stab->bcstr = bcstr;
  182. stab->type = type;
  183. stab->desc = (unsigned short)desc;
  184. stab->symvalue = symvalue;
  185. stab->bcvalue = bcvalue;
  186. stab->value = value;
  187. bc = yasm_bc_create_common(&stabs_bc_stab_callback, stab,
  188. bcvalue ? bcvalue->line : 0);
  189. bc->len = info->stablen;
  190. bc->offset = yasm_bc_next_offset(yasm_section_bcs_last(sect));
  191. yasm_section_bcs_append(sect, bc);
  192. info->stabcount++;
  193. return stab;
  194. }
  195. static void
  196. stabs_dbgfmt_generate_n_fun(stabs_info *info, yasm_bytecode *bc)
  197. {
  198. /* check all syms at this bc for potential function syms */
  199. int bcsym;
  200. for (bcsym=0; bc->symrecs && bc->symrecs[bcsym]; bcsym++)
  201. {
  202. char *str;
  203. yasm_symrec *sym = bc->symrecs[bcsym];
  204. const char *name = yasm_symrec_get_name(sym);
  205. /* best guess algorithm - ignore labels containing a . or $ */
  206. if (strchr(name, '.') || strchr(name, '$'))
  207. continue;
  208. /* if a function, update basebc, and output a funcname:F1 stab */
  209. info->basebc = bc;
  210. str = yasm_xmalloc(strlen(name)+4);
  211. strcpy(str, name);
  212. strcat(str, ":F1");
  213. stabs_dbgfmt_append_stab(info, info->stab,
  214. stabs_dbgfmt_append_bcstr(info->stabstr, str),
  215. N_FUN, 0, sym, info->basebc, 0);
  216. yasm_xfree(str);
  217. break;
  218. }
  219. }
  220. static int
  221. stabs_dbgfmt_generate_bcs(yasm_bytecode *bc, void *d)
  222. {
  223. stabs_info *info = (stabs_info *)d;
  224. yasm_linemap_lookup(info->linemap, bc->line, &info->curfile,
  225. &info->curline);
  226. /* check for new function */
  227. stabs_dbgfmt_generate_n_fun(info, bc);
  228. if (info->lastfile != info->curfile) {
  229. info->lastline = 0; /* new file, so line changes */
  230. /*stabs_dbgfmt_append_stab(info, info->stab,
  231. stabs_dbgfmt_append_bcstr(info->stabstr, info->curfile),
  232. N_SOL, 0, NULL, bc, 0);*/
  233. }
  234. /* output new line stabs if there's a basebc (known function) */
  235. if (info->basebc != NULL && info->curline != info->lastline) {
  236. info->lastline = bc->line;
  237. stabs_dbgfmt_append_stab(info, info->stab, NULL, N_SLINE,
  238. info->curline, NULL, NULL,
  239. bc->offset - info->basebc->offset);
  240. }
  241. info->lastline = info->curline;
  242. info->lastfile = info->curfile;
  243. return 0;
  244. }
  245. static int
  246. stabs_dbgfmt_generate_sections(yasm_section *sect, /*@null@*/ void *d)
  247. {
  248. stabs_info *info = (stabs_info *)d;
  249. const char *sectname=yasm_section_get_name(sect);
  250. /* each section has a different base symbol */
  251. info->basebc = NULL;
  252. /* handle first (pseudo) bc separately */
  253. stabs_dbgfmt_generate_n_fun(d, yasm_section_bcs_first(sect));
  254. yasm_section_bcs_traverse(sect, info->errwarns, d,
  255. stabs_dbgfmt_generate_bcs);
  256. if (yasm__strcasecmp(sectname, ".text")==0) {
  257. /* Close out last function by appending a null SO stab after last bc */
  258. yasm_bytecode *bc = yasm_section_bcs_last(sect);
  259. yasm_symrec *sym =
  260. yasm_symtab_define_label(info->object->symtab, ".n_so", bc, 1,
  261. bc->line);
  262. stabs_dbgfmt_append_stab(info, info->stab, 0, N_SO, 0, sym, bc, 0);
  263. }
  264. return 1;
  265. }
  266. static void
  267. stabs_dbgfmt_generate(yasm_object *object, yasm_linemap *linemap,
  268. yasm_errwarns *errwarns)
  269. {
  270. stabs_info info;
  271. int new;
  272. yasm_bytecode *dbgbc;
  273. stabs_stab *stab;
  274. yasm_bytecode *filebc, *laststr, *firstbc;
  275. yasm_symrec *firstsym;
  276. yasm_section *stext;
  277. /* Stablen is determined by arch/machine */
  278. if (yasm__strcasecmp(yasm_arch_keyword(object->arch), "x86") == 0) {
  279. info.stablen = 12;
  280. }
  281. else /* unknown machine; generate nothing */
  282. return;
  283. info.object = object;
  284. info.linemap = linemap;
  285. info.errwarns = errwarns;
  286. info.lastline = 0;
  287. info.stabcount = 0;
  288. info.stab = yasm_object_get_general(object, ".stab", 4, 0, 0, &new, 0);
  289. if (!new) {
  290. yasm_bytecode *last = yasm_section_bcs_last(info.stab);
  291. if (last == NULL) {
  292. yasm_error_set(YASM_ERROR_GENERAL,
  293. N_("stabs debugging conflicts with user-defined section .stab"));
  294. yasm_errwarn_propagate(errwarns,
  295. yasm_section_bcs_first(info.stab)->line);
  296. } else {
  297. yasm_warn_set(YASM_WARN_GENERAL,
  298. N_("stabs debugging overrides empty section .stab"));
  299. yasm_errwarn_propagate(errwarns, 0);
  300. }
  301. }
  302. info.stabstr =
  303. yasm_object_get_general(object, ".stabstr", 1, 0, 0, &new, 0);
  304. if (!new) {
  305. yasm_bytecode *last = yasm_section_bcs_last(info.stabstr);
  306. if (last == NULL) {
  307. yasm_error_set(YASM_ERROR_GENERAL,
  308. N_("stabs debugging conflicts with user-defined section .stabstr"));
  309. yasm_errwarn_propagate(errwarns,
  310. yasm_section_bcs_first(info.stab)->line);
  311. } else {
  312. yasm_warn_set(YASM_WARN_GENERAL,
  313. N_("stabs debugging overrides empty section .stabstr"));
  314. yasm_errwarn_propagate(errwarns, 0);
  315. }
  316. }
  317. /* initial pseudo-stab */
  318. stab = yasm_xmalloc(sizeof(stabs_stab));
  319. dbgbc = yasm_bc_create_common(&stabs_bc_stab_callback, stab, 0);
  320. dbgbc->len = info.stablen;
  321. dbgbc->offset = 0;
  322. yasm_section_bcs_append(info.stab, dbgbc);
  323. /* initial strtab bytecodes */
  324. stabs_dbgfmt_append_bcstr(info.stabstr, "");
  325. filebc = stabs_dbgfmt_append_bcstr(info.stabstr, object->src_filename);
  326. stext = yasm_object_find_general(object, ".text");
  327. firstsym = yasm_symtab_use(object->symtab, ".text", 0);
  328. firstbc = yasm_section_bcs_first(stext);
  329. /* N_SO file stab */
  330. stabs_dbgfmt_append_stab(&info, info.stab, filebc, N_SO, 0,
  331. firstsym, firstbc, 0);
  332. yasm_object_sections_traverse(object, (void *)&info,
  333. stabs_dbgfmt_generate_sections);
  334. /* fill initial pseudo-stab's fields */
  335. laststr = yasm_section_bcs_last(info.stabstr);
  336. if (laststr == NULL)
  337. yasm_internal_error(".stabstr has no entries");
  338. stab->bcvalue = NULL;
  339. stab->symvalue = NULL;
  340. stab->value = yasm_bc_next_offset(laststr);
  341. stab->bcstr = filebc;
  342. stab->type = N_UNDF;
  343. stab->other = 0;
  344. if (info.stabcount > 0xffff) {
  345. yasm_warn_set(YASM_WARN_GENERAL, N_("over 65535 stabs"));
  346. yasm_errwarn_propagate(errwarns, 0);
  347. stab->desc = 0xffff;
  348. } else
  349. stab->desc = (unsigned short)info.stabcount;
  350. }
  351. static int
  352. stabs_bc_stab_tobytes(yasm_bytecode *bc, unsigned char **bufp,
  353. unsigned char *bufstart, void *d,
  354. yasm_output_value_func output_value,
  355. yasm_output_reloc_func output_reloc)
  356. {
  357. /* This entire function, essentially the core of rendering stabs to a file,
  358. * needs to become endian aware. Size appears not to be an issue, as known
  359. * 64-bit systems use truncated values in 32-bit fields. */
  360. const stabs_stab *stab = (const stabs_stab *)bc->contents;
  361. unsigned char *buf = *bufp;
  362. YASM_WRITE_32_L(buf, stab->bcstr ? stab->bcstr->offset : 0);
  363. YASM_WRITE_8(buf, stab->type);
  364. YASM_WRITE_8(buf, stab->other);
  365. YASM_WRITE_16_L(buf, stab->desc);
  366. if (stab->symvalue != NULL) {
  367. bc->offset += 8;
  368. output_reloc(stab->symvalue, bc, buf, 4, 32, 0, d);
  369. bc->offset -= 8;
  370. buf += 4;
  371. }
  372. else if (stab->bcvalue != NULL) {
  373. YASM_WRITE_32_L(buf, stab->bcvalue->offset);
  374. }
  375. else {
  376. YASM_WRITE_32_L(buf, stab->value);
  377. }
  378. *bufp = buf;
  379. return 0;
  380. }
  381. static int
  382. stabs_bc_str_tobytes(yasm_bytecode *bc, unsigned char **bufp,
  383. unsigned char *bufstart, void *d,
  384. yasm_output_value_func output_value,
  385. yasm_output_reloc_func output_reloc)
  386. {
  387. const char *str = (const char *)bc->contents;
  388. unsigned char *buf = *bufp;
  389. strcpy((char *)buf, str);
  390. buf += strlen(str)+1;
  391. *bufp = buf;
  392. return 0;
  393. }
  394. static void
  395. stabs_bc_stab_destroy(void *contents)
  396. {
  397. yasm_xfree(contents);
  398. }
  399. static void
  400. stabs_bc_str_destroy(void *contents)
  401. {
  402. yasm_xfree(contents);
  403. }
  404. static void
  405. stabs_bc_stab_print(const void *contents, FILE *f, int indent_level)
  406. {
  407. const stabs_stab *stab = (const stabs_stab *)contents;
  408. const char *str = "";
  409. fprintf(f, "%*s.stabs \"%s\", 0x%x, 0x%x, 0x%x, 0x%lx\n",
  410. indent_level, "", str, stab->type, stab->other, stab->desc,
  411. stab->bcvalue ? stab->bcvalue->offset : stab->value);
  412. }
  413. static void
  414. stabs_bc_str_print(const void *contents, FILE *f, int indent_level)
  415. {
  416. fprintf(f, "%*s\"%s\"\n", indent_level, "", (const char *)contents);
  417. }
  418. static int
  419. stabs_bc_stab_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
  420. void *add_span_data)
  421. {
  422. yasm_internal_error(N_("tried to resolve a stabs stab bytecode"));
  423. /*@notreached@*/
  424. return 0;
  425. }
  426. static int
  427. stabs_bc_str_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
  428. void *add_span_data)
  429. {
  430. yasm_internal_error(N_("tried to resolve a stabs str bytecode"));
  431. /*@notreached@*/
  432. return 0;
  433. }
  434. /* Define dbgfmt structure -- see dbgfmt.h for details */
  435. yasm_dbgfmt_module yasm_stabs_LTX_dbgfmt = {
  436. "Stabs debugging format",
  437. "stabs",
  438. NULL, /* no directives */
  439. stabs_dbgfmt_create,
  440. stabs_dbgfmt_destroy,
  441. stabs_dbgfmt_generate
  442. };