cv-symline.c 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102
  1. /*
  2. * CodeView debugging format - symbol and line information
  3. *
  4. * Copyright (C) 2006-2007 Peter Johnson
  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. * 3. Neither the name of the author nor the names of other contributors
  15. * may be used to endorse or promote products derived from this
  16. * software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
  19. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  20. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  21. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
  22. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  23. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  24. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  25. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  26. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  27. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  28. * POSSIBILITY OF SUCH DAMAGE.
  29. */
  30. #include <util.h>
  31. #include <libyasm.h>
  32. #include "cv-dbgfmt.h"
  33. enum cv8_symheadtype {
  34. CV8_DEBUG_SYMS = 0xF1, /* CV5 symbol information */
  35. CV8_LINE_NUMS = 0xF2, /* line numbers for a section */
  36. CV8_FILE_STRTAB = 0xF3, /* filename string table */
  37. CV8_FILE_INFO = 0xF4 /* source file info */
  38. };
  39. enum cv_symtype {
  40. /* Non-modal Symbols */
  41. CV_S_COMPILE = 0x0001, /* Compile Flag */
  42. CV_S_REGISTER = 0x0002, /* Register */
  43. CV_S_CONSTANT = 0x0003, /* Constant */
  44. CV_S_UDT = 0x0004, /* User-defined Type */
  45. CV_S_SSEARCH = 0x0005, /* Start Search */
  46. CV_S_END = 0x0006, /* End of Block */
  47. CV_S_SKIP = 0x0007, /* Skip Record */
  48. CV_S_OBJNAME = 0x0009, /* Object File Name */
  49. CV_S_ENDARG = 0x000a, /* End of Arguments */
  50. CV_S_COBOLUDT = 0x000b, /* COBOL User-defined Type */
  51. CV_S_MANYREG = 0x000c, /* Many Registers */
  52. CV_S_RETURN = 0x000d, /* Function Return */
  53. CV_S_ENTRYTHIS = 0x000e, /* "this" at Method Entry */
  54. /* Symbols for 16:16 Segmented Architectures */
  55. CV_S_BPREL16 = 0x0100, /* BP Relative 16:16 */
  56. CV_S_LDATA16 = 0x0101, /* Local Data 16:16 */
  57. CV_S_GDATA16 = 0x0102, /* Global Data Symbol 16:16 */
  58. CV_S_PUB16 = 0x0103, /* Public Symbol 16:16 */
  59. CV_S_LPROC16 = 0x0104, /* Local Start 16:16 */
  60. CV_S_GPROC16 = 0x0105, /* Global Start 16:16 */
  61. CV_S_THUNK16 = 0x0106, /* Thunk Start 16:16 */
  62. CV_S_BLOCK16 = 0x0107, /* Block Start 16:16 */
  63. CV_S_WITH16 = 0x0108, /* With Start 16:16 */
  64. CV_S_LABEL16 = 0x0109, /* Code Label 16:16 */
  65. CV_S_CEXMODEL16 = 0x0110, /* Change Execution Model 16:16 */
  66. CV_S_VFTPATH16 = 0x010b, /* Virtual Function Table Path 16:16 */
  67. CV_S_REGREL16 = 0x010c, /* Register Relative 16:16 */
  68. /* Symbols for 16:32 Segmented Architectures */
  69. CV_S_BPREL32 = 0x0200, /* BP Relative 16:32 */
  70. CV_S_LDATA32 = 0x0201, /* Local Data 16:32 */
  71. CV_S_GDATA32 = 0x0202, /* Global Data Symbol 16:32 */
  72. CV_S_PUB32 = 0x0203, /* Public Symbol 16:32 */
  73. CV_S_LPROC32 = 0x0204, /* Local Start 16:32 */
  74. CV_S_GPROC32 = 0x0205, /* Global Start 16:32 */
  75. CV_S_THUNK32 = 0x0206, /* Thunk Start 16:32 */
  76. CV_S_BLOCK32 = 0x0207, /* Block Start 16:32 */
  77. CV_S_WITH32 = 0x0208, /* With Start 16:32 */
  78. CV_S_LABEL32 = 0x0209, /* Code Label 16:32 */
  79. CV_S_CEXMODEL32 = 0x0210, /* Change Execution Model 16:32 */
  80. CV_S_VFTPATH32 = 0x020b, /* Virtual Function Table Path 16:32 */
  81. CV_S_REGREL32 = 0x020c, /* Register Relative 16:32 */
  82. CV_S_LTHREAD32 = 0x020d, /* Local Thread Storage 16:32 */
  83. CV_S_GTHREAD32 = 0x020e, /* Global Thread Storage 16:32 */
  84. /* Symbols for MIPS */
  85. CV_S_LPROCMIPS = 0x0300, /* Local procedure start MIPS */
  86. CV_S_GPROCMIPS = 0x0301, /* Global procedure start MIPS */
  87. /* Symbols for CV8 - strings are 0 terminated rather than length-prefix.
  88. * Incomplete and unofficial.
  89. */
  90. CV8_S_OBJNAME = 0x1101, /* Object File Name */
  91. CV8_S_LABEL32 = 0x1105, /* Code Label 16:32 */
  92. CV8_S_LDATA32 = 0x110c, /* Local Data 16:32 */
  93. CV8_S_GDATA32 = 0x110d, /* Global Data 16:32 */
  94. CV8_S_LPROC32 = 0x1110, /* Local Start 16:32 */
  95. CV8_S_COMPILE = 0x1116 /* Compile Flag */
  96. };
  97. typedef struct cv8_symhead {
  98. enum cv8_symheadtype type;
  99. yasm_bytecode *start_prevbc;
  100. yasm_bytecode *end_prevbc;
  101. int first; /* nonzero if first symhead in section */
  102. } cv8_symhead;
  103. typedef struct cv8_fileinfo {
  104. const cv_filename *fn;
  105. } cv8_fileinfo;
  106. /* Note: each line number group is associated with a file AND a section */
  107. typedef struct cv8_linepair {
  108. unsigned long offset;
  109. unsigned long line;
  110. } cv8_linepair;
  111. /* Decrease linked list overhead a bit doing it this way */
  112. typedef struct cv8_lineset {
  113. STAILQ_ENTRY(cv8_lineset) link;
  114. cv8_linepair pairs[126];
  115. size_t num_pairs;
  116. } cv8_lineset;
  117. /* Note: Due to line number sorting requirements (by section offset it seems)
  118. * one file may need more than one record per section. */
  119. typedef struct cv8_lineinfo {
  120. STAILQ_ENTRY(cv8_lineinfo) link;
  121. const cv_filename *fn; /* filename associated with line numbers */
  122. yasm_section *sect; /* section line numbers are for */
  123. yasm_symrec *sectsym; /* symbol for beginning of sect */
  124. unsigned long num_linenums;
  125. int first_in_sect; /* First lineinfo for this section. */
  126. STAILQ_HEAD(cv8_lineset_head, cv8_lineset) linesets;
  127. } cv8_lineinfo;
  128. /* Symbols use a bit of meta-programming to encode formats: each character
  129. * of format represents the output generated, as follows:
  130. * 'b' : 1 byte value (integer)
  131. * 'h' : 2 byte value (integer)
  132. * 'w' : 4 byte value (integer)
  133. * 'Y' : symrec SECREL+SECTION (pointer)
  134. * 'T' : type index (integer)
  135. * 'S' : length-prefixed string (pointer)
  136. * 'Z' : 0-terminated string (pointer)
  137. */
  138. typedef struct cv_sym {
  139. enum cv_symtype type;
  140. const char *format;
  141. union {
  142. unsigned long i;
  143. void *p;
  144. } args[10];
  145. } cv_sym;
  146. /* Bytecode callback function prototypes */
  147. static void cv8_symhead_bc_destroy(void *contents);
  148. static void cv8_symhead_bc_print(const void *contents, FILE *f,
  149. int indent_level);
  150. static int cv8_symhead_bc_calc_len
  151. (yasm_bytecode *bc, yasm_bc_add_span_func add_span, void *add_span_data);
  152. static int cv8_symhead_bc_tobytes
  153. (yasm_bytecode *bc, unsigned char **bufp, unsigned char *bufstart, void *d,
  154. yasm_output_value_func output_value,
  155. /*@null@*/ yasm_output_reloc_func output_reloc);
  156. static void cv8_fileinfo_bc_destroy(void *contents);
  157. static void cv8_fileinfo_bc_print(const void *contents, FILE *f,
  158. int indent_level);
  159. static int cv8_fileinfo_bc_calc_len
  160. (yasm_bytecode *bc, yasm_bc_add_span_func add_span, void *add_span_data);
  161. static int cv8_fileinfo_bc_tobytes
  162. (yasm_bytecode *bc, unsigned char **bufp, unsigned char *bufstart, void *d,
  163. yasm_output_value_func output_value,
  164. /*@null@*/ yasm_output_reloc_func output_reloc);
  165. static void cv8_lineinfo_bc_destroy(void *contents);
  166. static void cv8_lineinfo_bc_print(const void *contents, FILE *f,
  167. int indent_level);
  168. static int cv8_lineinfo_bc_calc_len
  169. (yasm_bytecode *bc, yasm_bc_add_span_func add_span, void *add_span_data);
  170. static int cv8_lineinfo_bc_tobytes
  171. (yasm_bytecode *bc, unsigned char **bufp, unsigned char *bufstart, void *d,
  172. yasm_output_value_func output_value,
  173. /*@null@*/ yasm_output_reloc_func output_reloc);
  174. static void cv_sym_bc_destroy(void *contents);
  175. static void cv_sym_bc_print(const void *contents, FILE *f, int indent_level);
  176. static int cv_sym_bc_calc_len
  177. (yasm_bytecode *bc, yasm_bc_add_span_func add_span, void *add_span_data);
  178. static int cv_sym_bc_tobytes
  179. (yasm_bytecode *bc, unsigned char **bufp, unsigned char *bufstart, void *d,
  180. yasm_output_value_func output_value,
  181. /*@null@*/ yasm_output_reloc_func output_reloc);
  182. /* Bytecode callback structures */
  183. static const yasm_bytecode_callback cv8_symhead_bc_callback = {
  184. cv8_symhead_bc_destroy,
  185. cv8_symhead_bc_print,
  186. yasm_bc_finalize_common,
  187. NULL,
  188. cv8_symhead_bc_calc_len,
  189. yasm_bc_expand_common,
  190. cv8_symhead_bc_tobytes,
  191. 0
  192. };
  193. static const yasm_bytecode_callback cv8_fileinfo_bc_callback = {
  194. cv8_fileinfo_bc_destroy,
  195. cv8_fileinfo_bc_print,
  196. yasm_bc_finalize_common,
  197. NULL,
  198. cv8_fileinfo_bc_calc_len,
  199. yasm_bc_expand_common,
  200. cv8_fileinfo_bc_tobytes,
  201. 0
  202. };
  203. static const yasm_bytecode_callback cv8_lineinfo_bc_callback = {
  204. cv8_lineinfo_bc_destroy,
  205. cv8_lineinfo_bc_print,
  206. yasm_bc_finalize_common,
  207. NULL,
  208. cv8_lineinfo_bc_calc_len,
  209. yasm_bc_expand_common,
  210. cv8_lineinfo_bc_tobytes,
  211. 0
  212. };
  213. static const yasm_bytecode_callback cv_sym_bc_callback = {
  214. cv_sym_bc_destroy,
  215. cv_sym_bc_print,
  216. yasm_bc_finalize_common,
  217. NULL,
  218. cv_sym_bc_calc_len,
  219. yasm_bc_expand_common,
  220. cv_sym_bc_tobytes,
  221. 0
  222. };
  223. static cv8_symhead *cv8_add_symhead(yasm_section *sect, unsigned long type,
  224. int first);
  225. static void cv8_set_symhead_end(cv8_symhead *head, yasm_bytecode *end_prevbc);
  226. static yasm_bytecode *cv8_add_fileinfo
  227. (yasm_section *sect, const cv_filename *fn);
  228. static unsigned long cv_sym_size(const cv_sym *cvs);
  229. static cv_sym *
  230. cv8_add_sym_objname(yasm_section *sect, /*@keep@*/ char *objname)
  231. {
  232. yasm_bytecode *bc;
  233. cv_sym *cvs = yasm_xmalloc(sizeof(cv_sym));
  234. cvs->type = CV8_S_OBJNAME;
  235. cvs->format = "wZ";
  236. cvs->args[0].i = 0; /* signature (0=asm) */
  237. cvs->args[1].p = objname; /* object filename */
  238. bc = yasm_bc_create_common(&cv_sym_bc_callback, cvs, 0);
  239. bc->len = cv_sym_size(cvs);
  240. yasm_cv__append_bc(sect, bc);
  241. return cvs;
  242. }
  243. static cv_sym *
  244. cv8_add_sym_compile(yasm_object *object, yasm_section *sect,
  245. /*@keep@*/ char *creator)
  246. {
  247. yasm_bytecode *bc;
  248. cv_sym *cvs = yasm_xmalloc(sizeof(cv_sym));
  249. cvs->type = CV8_S_COMPILE;
  250. cvs->format = "wwwwZh";
  251. cvs->args[0].i = 3; /* language (3=Masm) */
  252. /* target processor; 0xD0 = AMD64 */
  253. if (strcmp(yasm_arch_keyword(object->arch), "x86") == 0) {
  254. if (strcmp(yasm_arch_get_machine(object->arch), "amd64") == 0)
  255. cvs->args[1].i = 0xD0;
  256. else
  257. cvs->args[1].i = 0x6; /* 686, FIXME */
  258. } else
  259. cvs->args[1].i = 0; /* XXX: unknown */
  260. cvs->args[2].i = 0; /* flags (assume 0 for now) */
  261. cvs->args[3].i = 0; /* creator version number (assume 0 for now) */
  262. cvs->args[4].p = creator; /* creator string */
  263. cvs->args[5].i = 0; /* no pairs of key/value */
  264. bc = yasm_bc_create_common(&cv_sym_bc_callback, cvs, 0);
  265. bc->len = cv_sym_size(cvs);
  266. yasm_cv__append_bc(sect, bc);
  267. return cvs;
  268. }
  269. static cv_sym *
  270. cv8_add_sym_label(yasm_section *sect, yasm_symrec *sym)
  271. {
  272. yasm_bytecode *bc;
  273. cv_sym *cvs = yasm_xmalloc(sizeof(cv_sym));
  274. cvs->type = CV8_S_LABEL32;
  275. cvs->format = "YbZ";
  276. cvs->args[0].p = sym; /* symrec for label */
  277. cvs->args[1].i = 0; /* flags (assume 0 for now) */
  278. cvs->args[2].p = yasm__xstrdup(yasm_symrec_get_name(sym));
  279. bc = yasm_bc_create_common(&cv_sym_bc_callback, cvs, 0);
  280. bc->len = cv_sym_size(cvs);
  281. yasm_cv__append_bc(sect, bc);
  282. return cvs;
  283. }
  284. static cv_sym *
  285. cv8_add_sym_data(yasm_section *sect, unsigned long type, yasm_symrec *sym,
  286. int is_global)
  287. {
  288. yasm_bytecode *bc;
  289. cv_sym *cvs = yasm_xmalloc(sizeof(cv_sym));
  290. cvs->type = is_global ? CV8_S_GDATA32 : CV8_S_LDATA32;
  291. cvs->format = "wYZ";
  292. cvs->args[0].i = type; /* type index */
  293. cvs->args[1].p = sym; /* symrec for label */
  294. cvs->args[2].p = yasm__xstrdup(yasm_symrec_get_name(sym));
  295. bc = yasm_bc_create_common(&cv_sym_bc_callback, cvs, 0);
  296. bc->len = cv_sym_size(cvs);
  297. yasm_cv__append_bc(sect, bc);
  298. return cvs;
  299. }
  300. static size_t
  301. cv_dbgfmt_add_file(yasm_dbgfmt_cv *dbgfmt_cv, size_t filenum,
  302. const char *filename)
  303. {
  304. char *pathname;
  305. size_t i;
  306. yasm_md5_context context;
  307. FILE *f;
  308. unsigned char *buf;
  309. size_t len;
  310. /* Put the filename into the filename table */
  311. if (filenum == 0) {
  312. /* Look to see if we already have that filename in the table */
  313. for (; filenum<dbgfmt_cv->filenames_size; filenum++) {
  314. if (!dbgfmt_cv->filenames[filenum].filename ||
  315. strcmp(dbgfmt_cv->filenames[filenum].filename, filename) == 0)
  316. break;
  317. }
  318. } else
  319. filenum--; /* array index is 0-based */
  320. /* Realloc table if necessary */
  321. if (filenum >= dbgfmt_cv->filenames_allocated) {
  322. size_t old_allocated = dbgfmt_cv->filenames_allocated;
  323. dbgfmt_cv->filenames_allocated = filenum+32;
  324. dbgfmt_cv->filenames = yasm_xrealloc(dbgfmt_cv->filenames,
  325. sizeof(cv_filename)*dbgfmt_cv->filenames_allocated);
  326. for (i=old_allocated; i<dbgfmt_cv->filenames_allocated; i++) {
  327. dbgfmt_cv->filenames[i].pathname = NULL;
  328. dbgfmt_cv->filenames[i].filename = NULL;
  329. dbgfmt_cv->filenames[i].str_off = 0;
  330. dbgfmt_cv->filenames[i].info_off = 0;
  331. }
  332. }
  333. /* Calculate MD5 checksum of file */
  334. buf = yasm_xmalloc(1024);
  335. yasm_md5_init(&context);
  336. f = fopen(filename, "rb");
  337. if (!f)
  338. yasm__fatal(N_("codeview: could not open source file"));
  339. while ((len = fread(buf, 1, 1024, f)) > 0)
  340. yasm_md5_update(&context, buf, (unsigned long)len);
  341. yasm_md5_final(dbgfmt_cv->filenames[filenum].digest, &context);
  342. fclose(f);
  343. yasm_xfree(buf);
  344. /* Actually save in table */
  345. if (dbgfmt_cv->filenames[filenum].pathname)
  346. yasm_xfree(dbgfmt_cv->filenames[filenum].pathname);
  347. if (dbgfmt_cv->filenames[filenum].filename)
  348. yasm_xfree(dbgfmt_cv->filenames[filenum].filename);
  349. pathname = yasm__abspath(filename);
  350. dbgfmt_cv->filenames[filenum].pathname = pathname;
  351. dbgfmt_cv->filenames[filenum].filename = yasm__xstrdup(filename);
  352. /* Update table size */
  353. if (filenum >= dbgfmt_cv->filenames_size)
  354. dbgfmt_cv->filenames_size = filenum + 1;
  355. return filenum;
  356. }
  357. static yasm_bytecode *
  358. cv_append_str(yasm_section *sect, const char *str)
  359. {
  360. yasm_datavalhead dvs;
  361. yasm_bytecode *bc;
  362. yasm_dvs_initialize(&dvs);
  363. yasm_dvs_append(&dvs, yasm_dv_create_string(yasm__xstrdup(str),
  364. strlen(str)));
  365. bc = yasm_bc_create_data(&dvs, 1, 1, NULL, 0);
  366. yasm_bc_finalize(bc, yasm_cv__append_bc(sect, bc));
  367. yasm_bc_calc_len(bc, NULL, NULL);
  368. return bc;
  369. }
  370. typedef struct cv_line_info {
  371. yasm_section *debug_symline;
  372. yasm_object *object;
  373. yasm_dbgfmt_cv *dbgfmt_cv;
  374. yasm_linemap *linemap;
  375. yasm_errwarns *errwarns;
  376. unsigned int num_lineinfos;
  377. STAILQ_HEAD(cv8_lineinfo_head, cv8_lineinfo) cv8_lineinfos;
  378. /*@null@*/ cv8_lineinfo *cv8_cur_li;
  379. /*@null@*/ cv8_lineset *cv8_cur_ls;
  380. } cv_line_info;
  381. static int
  382. cv_generate_line_bc(yasm_bytecode *bc, /*@null@*/ void *d)
  383. {
  384. cv_line_info *info = (cv_line_info *)d;
  385. yasm_dbgfmt_cv *dbgfmt_cv = info->dbgfmt_cv;
  386. size_t i;
  387. const char *filename;
  388. unsigned long line;
  389. /*@null@*/ yasm_bytecode *nextbc = yasm_bc__next(bc);
  390. yasm_section *sect = yasm_bc_get_section(bc);
  391. if (nextbc && bc->offset == nextbc->offset)
  392. return 0;
  393. yasm_linemap_lookup(info->linemap, bc->line, &filename, &line);
  394. if (!info->cv8_cur_li
  395. || strcmp(filename, info->cv8_cur_li->fn->filename) != 0) {
  396. yasm_bytecode *sectbc;
  397. char symname[8];
  398. int first_in_sect = !info->cv8_cur_li;
  399. /* Find file */
  400. for (i=0; i<dbgfmt_cv->filenames_size; i++) {
  401. if (strcmp(filename, dbgfmt_cv->filenames[i].filename) == 0)
  402. break;
  403. }
  404. if (i >= dbgfmt_cv->filenames_size)
  405. yasm_internal_error(N_("could not find filename in table"));
  406. /* and create new lineinfo structure */
  407. info->cv8_cur_li = yasm_xmalloc(sizeof(cv8_lineinfo));
  408. info->cv8_cur_li->fn = &dbgfmt_cv->filenames[i];
  409. info->cv8_cur_li->sect = sect;
  410. info->cv8_cur_li->first_in_sect = first_in_sect;
  411. sectbc = yasm_section_bcs_first(sect);
  412. if (sectbc->symrecs && sectbc->symrecs[0])
  413. info->cv8_cur_li->sectsym = sectbc->symrecs[0];
  414. else {
  415. sprintf(symname, ".%06u", info->num_lineinfos++);
  416. info->cv8_cur_li->sectsym =
  417. yasm_symtab_define_label(info->object->symtab, symname, sectbc,
  418. 1, 0);
  419. }
  420. info->cv8_cur_li->num_linenums = 0;
  421. STAILQ_INIT(&info->cv8_cur_li->linesets);
  422. STAILQ_INSERT_TAIL(&info->cv8_lineinfos, info->cv8_cur_li, link);
  423. info->cv8_cur_ls = NULL;
  424. }
  425. /* build new lineset if necessary */
  426. if (!info->cv8_cur_ls || info->cv8_cur_ls->num_pairs >= 126) {
  427. info->cv8_cur_ls = yasm_xmalloc(sizeof(cv8_lineset));
  428. info->cv8_cur_ls->num_pairs = 0;
  429. STAILQ_INSERT_TAIL(&info->cv8_cur_li->linesets, info->cv8_cur_ls, link);
  430. }
  431. /* add linepair for this bytecode */
  432. info->cv8_cur_ls->pairs[info->cv8_cur_ls->num_pairs].offset = bc->offset;
  433. info->cv8_cur_ls->pairs[info->cv8_cur_ls->num_pairs].line =
  434. 0x80000000 | line;
  435. info->cv8_cur_ls->num_pairs++;
  436. info->cv8_cur_li->num_linenums++;
  437. return 0;
  438. }
  439. static int
  440. cv_generate_line_section(yasm_section *sect, /*@null@*/ void *d)
  441. {
  442. cv_line_info *info = (cv_line_info *)d;
  443. if (!yasm_section_is_code(sect))
  444. return 0; /* not code, so no line data for this section */
  445. info->cv8_cur_li = NULL;
  446. info->cv8_cur_ls = NULL;
  447. yasm_section_bcs_traverse(sect, info->errwarns, info, cv_generate_line_bc);
  448. return 0;
  449. }
  450. static int
  451. cv_generate_filename(const char *filename, void *d)
  452. {
  453. cv_dbgfmt_add_file((yasm_dbgfmt_cv *)d, 0, filename);
  454. return 0;
  455. }
  456. static int
  457. cv_generate_sym(yasm_symrec *sym, void *d)
  458. {
  459. cv_line_info *info = (cv_line_info *)d;
  460. yasm_bytecode *precbc;
  461. const char *name = yasm_symrec_get_name(sym);
  462. /* only care about labels (for now). Don't put in symbols starting with
  463. * ".", as these are typically internally generated ones (like section
  464. * symbols).
  465. */
  466. if (name[0] == '.' || !yasm_symrec_get_label(sym, &precbc))
  467. return 0;
  468. /* TODO: add data types; until then, just mark everything as UBYTE */
  469. if (yasm_section_is_code(yasm_bc_get_section(precbc)))
  470. cv8_add_sym_label(info->debug_symline, sym);
  471. else
  472. cv8_add_sym_data(info->debug_symline, 0x20, sym,
  473. yasm_symrec_get_visibility(sym) & YASM_SYM_GLOBAL?1:0);
  474. return 0;
  475. }
  476. yasm_section *
  477. yasm_cv__generate_symline(yasm_object *object, yasm_linemap *linemap,
  478. yasm_errwarns *errwarns)
  479. {
  480. yasm_dbgfmt_cv *dbgfmt_cv = (yasm_dbgfmt_cv *)object->dbgfmt;
  481. cv_line_info info;
  482. int new;
  483. size_t i;
  484. cv8_symhead *head;
  485. cv8_lineinfo *li;
  486. yasm_bytecode *bc;
  487. unsigned long off;
  488. /* Generate filenames based on linemap */
  489. yasm_linemap_traverse_filenames(linemap, dbgfmt_cv,
  490. cv_generate_filename);
  491. info.object = object;
  492. info.dbgfmt_cv = dbgfmt_cv;
  493. info.linemap = linemap;
  494. info.errwarns = errwarns;
  495. info.debug_symline =
  496. yasm_object_get_general(object, ".debug$S", 1, 0, 0, &new, 0);
  497. info.num_lineinfos = 0;
  498. STAILQ_INIT(&info.cv8_lineinfos);
  499. info.cv8_cur_li = NULL;
  500. info.cv8_cur_ls = NULL;
  501. /* source filenames string table */
  502. head = cv8_add_symhead(info.debug_symline, CV8_FILE_STRTAB, 1);
  503. cv_append_str(info.debug_symline, "");
  504. off = 1;
  505. for (i=0; i<dbgfmt_cv->filenames_size; i++) {
  506. if (!dbgfmt_cv->filenames[i].pathname) {
  507. yasm_error_set(YASM_ERROR_GENERAL,
  508. N_("codeview file number %d unassigned"), i+1);
  509. yasm_errwarn_propagate(errwarns, 0);
  510. continue;
  511. }
  512. bc = cv_append_str(info.debug_symline,
  513. dbgfmt_cv->filenames[i].pathname);
  514. dbgfmt_cv->filenames[i].str_off = off;
  515. off += bc->len;
  516. }
  517. cv8_set_symhead_end(head, yasm_section_bcs_last(info.debug_symline));
  518. /* Align 4 */
  519. bc = yasm_bc_create_align
  520. (yasm_expr_create_ident(yasm_expr_int(yasm_intnum_create_uint(4)), 0),
  521. NULL, NULL, NULL, 0);
  522. yasm_bc_finalize(bc, yasm_cv__append_bc(info.debug_symline, bc));
  523. yasm_bc_calc_len(bc, NULL, NULL);
  524. /* source file info table */
  525. head = cv8_add_symhead(info.debug_symline, CV8_FILE_INFO, 0);
  526. off = 0;
  527. for (i=0; i<dbgfmt_cv->filenames_size; i++) {
  528. if (!dbgfmt_cv->filenames[i].pathname)
  529. continue;
  530. bc = cv8_add_fileinfo(info.debug_symline, &dbgfmt_cv->filenames[i]);
  531. dbgfmt_cv->filenames[i].info_off = off;
  532. off += bc->len;
  533. }
  534. cv8_set_symhead_end(head, yasm_section_bcs_last(info.debug_symline));
  535. /* Already aligned 4 */
  536. /* Generate line numbers for sections */
  537. yasm_object_sections_traverse(object, (void *)&info,
  538. cv_generate_line_section);
  539. /* Output line numbers for sections */
  540. head = NULL;
  541. STAILQ_FOREACH(li, &info.cv8_lineinfos, link) {
  542. if (li->first_in_sect) {
  543. if (head)
  544. cv8_set_symhead_end(head, yasm_section_bcs_last(info.debug_symline));
  545. head = cv8_add_symhead(info.debug_symline, CV8_LINE_NUMS, 0);
  546. }
  547. bc = yasm_bc_create_common(&cv8_lineinfo_bc_callback, li, 0);
  548. bc->len = (li->first_in_sect ? 24 : 12) + li->num_linenums*8;
  549. yasm_cv__append_bc(info.debug_symline, bc);
  550. }
  551. if (head)
  552. cv8_set_symhead_end(head, yasm_section_bcs_last(info.debug_symline));
  553. /* Already aligned 4 */
  554. /* Output debugging symbols */
  555. head = cv8_add_symhead(info.debug_symline, CV8_DEBUG_SYMS, 0);
  556. /* add object and compile flag first */
  557. cv8_add_sym_objname(info.debug_symline,
  558. yasm__abspath(object->obj_filename));
  559. if (getenv("YASM_TEST_SUITE"))
  560. cv8_add_sym_compile(object, info.debug_symline,
  561. yasm__xstrdup("yasm HEAD"));
  562. else
  563. cv8_add_sym_compile(object, info.debug_symline,
  564. yasm__xstrdup(PACKAGE_STRING));
  565. /* then iterate through symbol table */
  566. yasm_symtab_traverse(object->symtab, &info, cv_generate_sym);
  567. cv8_set_symhead_end(head, yasm_section_bcs_last(info.debug_symline));
  568. /* Align 4 at end */
  569. bc = yasm_bc_create_align
  570. (yasm_expr_create_ident(yasm_expr_int(yasm_intnum_create_uint(4)), 0),
  571. NULL, NULL, NULL, 0);
  572. yasm_bc_finalize(bc, yasm_cv__append_bc(info.debug_symline, bc));
  573. yasm_bc_calc_len(bc, NULL, NULL);
  574. return info.debug_symline;
  575. }
  576. static void
  577. cv_out_sym(yasm_symrec *sym, unsigned long off, yasm_bytecode *bc,
  578. unsigned char **bufp, void *d, yasm_output_value_func output_value)
  579. {
  580. yasm_value val;
  581. /* sym in its section */
  582. yasm_value_init_sym(&val, sym, 32);
  583. val.section_rel = 1;
  584. output_value(&val, *bufp, 4, off, bc, 0, d);
  585. *bufp += 4;
  586. /* section index */
  587. yasm_value_init_sym(&val, sym, 16);
  588. val.seg_of = 1;
  589. output_value(&val, *bufp, 2, off+4, bc, 0, d);
  590. *bufp += 2;
  591. }
  592. static cv8_symhead *
  593. cv8_add_symhead(yasm_section *sect, unsigned long type, int first)
  594. {
  595. cv8_symhead *head;
  596. yasm_bytecode *bc;
  597. head = yasm_xmalloc(sizeof(cv8_symhead));
  598. head->type = type;
  599. head->first = first;
  600. head->start_prevbc = yasm_section_bcs_last(sect);
  601. bc = yasm_bc_create_common(&cv8_symhead_bc_callback, head, 0);
  602. if (first)
  603. bc->len = 12;
  604. else
  605. bc->len = 8;
  606. head->end_prevbc = bc;
  607. yasm_cv__append_bc(sect, bc);
  608. return head;
  609. }
  610. static void
  611. cv8_set_symhead_end(cv8_symhead *head, yasm_bytecode *end_prevbc)
  612. {
  613. head->end_prevbc = end_prevbc;
  614. }
  615. static void
  616. cv8_symhead_bc_destroy(void *contents)
  617. {
  618. yasm_xfree(contents);
  619. }
  620. static void
  621. cv8_symhead_bc_print(const void *contents, FILE *f, int indent_level)
  622. {
  623. /* TODO */
  624. }
  625. static int
  626. cv8_symhead_bc_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
  627. void *add_span_data)
  628. {
  629. yasm_internal_error(N_("tried to calc_len a codeview symhead bytecode"));
  630. /*@notreached@*/
  631. return 0;
  632. }
  633. static int
  634. cv8_symhead_bc_tobytes(yasm_bytecode *bc, unsigned char **bufp,
  635. unsigned char *bufstart, void *d,
  636. yasm_output_value_func output_value,
  637. yasm_output_reloc_func output_reloc)
  638. {
  639. yasm_object *object = yasm_section_get_object(bc->section);
  640. cv8_symhead *head = (cv8_symhead *)bc->contents;
  641. unsigned char *buf = *bufp;
  642. yasm_intnum *intn, *cval;
  643. cval = yasm_intnum_create_uint(4);
  644. /* Output "version" if first */
  645. if (head->first) {
  646. yasm_arch_intnum_tobytes(object->arch, cval, buf, 4, 32, 0, bc, 0);
  647. buf += 4;
  648. }
  649. /* Type contained - 4 bytes */
  650. yasm_intnum_set_uint(cval, head->type);
  651. yasm_arch_intnum_tobytes(object->arch, cval, buf, 4, 32, 0, bc, 0);
  652. buf += 4;
  653. /* Total length of info (following this field) - 4 bytes */
  654. yasm_intnum_set_uint(cval, bc->len);
  655. intn = yasm_calc_bc_dist(head->start_prevbc, head->end_prevbc);
  656. yasm_intnum_calc(intn, YASM_EXPR_SUB, cval);
  657. yasm_arch_intnum_tobytes(object->arch, intn, buf, 4, 32, 0, bc, 0);
  658. buf += 4;
  659. yasm_intnum_destroy(intn);
  660. *bufp = buf;
  661. yasm_intnum_destroy(cval);
  662. return 0;
  663. }
  664. static yasm_bytecode *
  665. cv8_add_fileinfo(yasm_section *sect, const cv_filename *fn)
  666. {
  667. cv8_fileinfo *fi;
  668. yasm_bytecode *bc;
  669. fi = yasm_xmalloc(sizeof(cv8_fileinfo));
  670. fi->fn = fn;
  671. bc = yasm_bc_create_common(&cv8_fileinfo_bc_callback, fi, 0);
  672. bc->len = 24;
  673. yasm_cv__append_bc(sect, bc);
  674. return bc;
  675. }
  676. static void
  677. cv8_fileinfo_bc_destroy(void *contents)
  678. {
  679. yasm_xfree(contents);
  680. }
  681. static void
  682. cv8_fileinfo_bc_print(const void *contents, FILE *f, int indent_level)
  683. {
  684. /* TODO */
  685. }
  686. static int
  687. cv8_fileinfo_bc_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
  688. void *add_span_data)
  689. {
  690. yasm_internal_error(N_("tried to calc_len a codeview fileinfo bytecode"));
  691. /*@notreached@*/
  692. return 0;
  693. }
  694. static int
  695. cv8_fileinfo_bc_tobytes(yasm_bytecode *bc, unsigned char **bufp,
  696. unsigned char *bufstart, void *d,
  697. yasm_output_value_func output_value,
  698. yasm_output_reloc_func output_reloc)
  699. {
  700. yasm_object *object = yasm_section_get_object(bc->section);
  701. cv8_fileinfo *fi = (cv8_fileinfo *)bc->contents;
  702. unsigned char *buf = *bufp;
  703. yasm_intnum *cval;
  704. int i;
  705. /* Offset in filename string table */
  706. cval = yasm_intnum_create_uint(fi->fn->str_off);
  707. yasm_arch_intnum_tobytes(object->arch, cval, buf, 4, 32, 0, bc, 0);
  708. buf += 4;
  709. /* Checksum type/length */
  710. yasm_intnum_set_uint(cval, 0x0110);
  711. yasm_arch_intnum_tobytes(object->arch, cval, buf, 2, 16, 0, bc, 0);
  712. buf += 2;
  713. /* Checksum */
  714. for (i=0; i<16; i++)
  715. YASM_WRITE_8(buf, fi->fn->digest[i]);
  716. /* Pad */
  717. YASM_WRITE_8(buf, 0);
  718. YASM_WRITE_8(buf, 0);
  719. *bufp = buf;
  720. yasm_intnum_destroy(cval);
  721. return 0;
  722. }
  723. static void
  724. cv8_lineinfo_bc_destroy(void *contents)
  725. {
  726. cv8_lineinfo *li = (cv8_lineinfo *)contents;
  727. cv8_lineset *ls1, *ls2;
  728. /* delete line sets */
  729. ls1 = STAILQ_FIRST(&li->linesets);
  730. while (ls1) {
  731. ls2 = STAILQ_NEXT(ls1, link);
  732. yasm_xfree(ls1);
  733. ls1 = ls2;
  734. }
  735. yasm_xfree(contents);
  736. }
  737. static void
  738. cv8_lineinfo_bc_print(const void *contents, FILE *f, int indent_level)
  739. {
  740. /* TODO */
  741. }
  742. static int
  743. cv8_lineinfo_bc_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
  744. void *add_span_data)
  745. {
  746. yasm_internal_error(N_("tried to calc_len a codeview linehead bytecode"));
  747. /*@notreached@*/
  748. return 0;
  749. }
  750. static int
  751. cv8_lineinfo_bc_tobytes(yasm_bytecode *bc, unsigned char **bufp,
  752. unsigned char *bufstart, void *d,
  753. yasm_output_value_func output_value,
  754. yasm_output_reloc_func output_reloc)
  755. {
  756. yasm_object *object = yasm_section_get_object(bc->section);
  757. cv8_lineinfo *li = (cv8_lineinfo *)bc->contents;
  758. unsigned char *buf = *bufp;
  759. yasm_intnum *cval;
  760. unsigned long i;
  761. cv8_lineset *ls;
  762. if (li->first_in_sect) {
  763. /* start offset and section */
  764. cv_out_sym(li->sectsym, (unsigned long)(buf - bufstart), bc, &buf,
  765. d, output_value);
  766. /* Two bytes of pad/alignment */
  767. YASM_WRITE_8(buf, 0);
  768. YASM_WRITE_8(buf, 0);
  769. /* Section length covered by line number info */
  770. cval = yasm_calc_bc_dist(yasm_section_bcs_first(li->sect),
  771. yasm_section_bcs_last(li->sect));
  772. yasm_arch_intnum_tobytes(object->arch, cval, buf, 4, 32, 0, bc, 0);
  773. yasm_intnum_destroy(cval);
  774. buf += 4;
  775. }
  776. /* Offset of source file in info table */
  777. cval = yasm_intnum_create_uint(li->fn->info_off);
  778. yasm_arch_intnum_tobytes(object->arch, cval, buf, 4, 32, 0, bc, 0);
  779. buf += 4;
  780. /* Number of line number pairs */
  781. yasm_intnum_set_uint(cval, li->num_linenums);
  782. yasm_arch_intnum_tobytes(object->arch, cval, buf, 4, 32, 0, bc, 0);
  783. buf += 4;
  784. /* Number of bytes of line number pairs + 12 (no, I don't know why) */
  785. yasm_intnum_set_uint(cval, li->num_linenums*8+12);
  786. yasm_arch_intnum_tobytes(object->arch, cval, buf, 4, 32, 0, bc, 0);
  787. buf += 4;
  788. /* Offset / line number pairs */
  789. i = 0;
  790. STAILQ_FOREACH(ls, &li->linesets, link) {
  791. unsigned long j;
  792. for (j=0; i<li->num_linenums && j<126; i++, j++) {
  793. /* offset in section */
  794. yasm_intnum_set_uint(cval, ls->pairs[j].offset);
  795. yasm_arch_intnum_tobytes(object->arch, cval, buf, 4, 32, 0, bc, 0);
  796. buf += 4;
  797. /* line number in file */
  798. yasm_intnum_set_uint(cval, ls->pairs[j].line);
  799. yasm_arch_intnum_tobytes(object->arch, cval, buf, 4, 32, 0, bc, 0);
  800. buf += 4;
  801. }
  802. }
  803. *bufp = buf;
  804. yasm_intnum_destroy(cval);
  805. return 0;
  806. }
  807. static unsigned long
  808. cv_sym_size(const cv_sym *cvs)
  809. {
  810. const char *ch = cvs->format;
  811. unsigned long len = 4; /* sym length and type */
  812. unsigned long slen;
  813. int arg = 0;
  814. while (*ch) {
  815. switch (*ch) {
  816. case 'b':
  817. len++;
  818. arg++;
  819. break;
  820. case 'h':
  821. len += 2;
  822. arg++;
  823. break;
  824. case 'w':
  825. len += 4;
  826. arg++;
  827. break;
  828. case 'Y':
  829. len += 6; /* XXX: will be 4 in 16-bit version */
  830. arg++;
  831. break;
  832. case 'T':
  833. len += 4; /* XXX: will be 2 in CV4 */
  834. arg++;
  835. break;
  836. case 'S':
  837. len += 1; /* XXX: is this 1 or 2? */
  838. slen = (unsigned long)strlen((const char *)cvs->args[arg++].p);
  839. len += slen <= 0xff ? slen : 0xff;
  840. break;
  841. case 'Z':
  842. len +=
  843. (unsigned long)strlen((const char *)cvs->args[arg++].p) + 1;
  844. break;
  845. default:
  846. yasm_internal_error(N_("unknown sym format character"));
  847. }
  848. ch++;
  849. }
  850. return len;
  851. }
  852. static void
  853. cv_sym_bc_destroy(void *contents)
  854. {
  855. cv_sym *cvs = (cv_sym *)contents;
  856. const char *ch = cvs->format;
  857. int arg = 0;
  858. while (*ch) {
  859. switch (*ch) {
  860. case 'b':
  861. case 'h':
  862. case 'w':
  863. case 'Y':
  864. case 'T':
  865. arg++;
  866. break; /* nothing to destroy */
  867. case 'S':
  868. case 'Z':
  869. yasm_xfree(cvs->args[arg++].p);
  870. break;
  871. default:
  872. yasm_internal_error(N_("unknown sym format character"));
  873. }
  874. ch++;
  875. }
  876. yasm_xfree(contents);
  877. }
  878. static void
  879. cv_sym_bc_print(const void *contents, FILE *f, int indent_level)
  880. {
  881. /* TODO */
  882. }
  883. static int
  884. cv_sym_bc_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
  885. void *add_span_data)
  886. {
  887. yasm_internal_error(N_("tried to calc_len a codeview sym bytecode"));
  888. /*@notreached@*/
  889. return 0;
  890. }
  891. static int
  892. cv_sym_bc_tobytes(yasm_bytecode *bc, unsigned char **bufp,
  893. unsigned char *bufstart, void *d,
  894. yasm_output_value_func output_value,
  895. yasm_output_reloc_func output_reloc)
  896. {
  897. yasm_object *object = yasm_section_get_object(bc->section);
  898. cv_sym *cvs = (cv_sym *)bc->contents;
  899. unsigned char *buf = *bufp;
  900. yasm_intnum *cval;
  901. const char *ch = cvs->format;
  902. size_t len;
  903. int arg = 0;
  904. /* Total length of record (following this field) - 2 bytes */
  905. cval = yasm_intnum_create_uint(bc->len-2);
  906. yasm_arch_intnum_tobytes(object->arch, cval, buf, 2, 16, 0, bc, 1);
  907. buf += 2;
  908. /* Type contained - 2 bytes */
  909. yasm_intnum_set_uint(cval, cvs->type);
  910. yasm_arch_intnum_tobytes(object->arch, cval, buf, 2, 16, 0, bc, 0);
  911. buf += 2;
  912. while (*ch) {
  913. switch (*ch) {
  914. case 'b':
  915. YASM_WRITE_8(buf, cvs->args[arg].i);
  916. arg++;
  917. break;
  918. case 'h':
  919. yasm_intnum_set_uint(cval, cvs->args[arg++].i);
  920. yasm_arch_intnum_tobytes(object->arch, cval, buf, 2, 16, 0,
  921. bc, 0);
  922. buf += 2;
  923. break;
  924. case 'w':
  925. yasm_intnum_set_uint(cval, cvs->args[arg++].i);
  926. yasm_arch_intnum_tobytes(object->arch, cval, buf, 4, 32, 0,
  927. bc, 0);
  928. buf += 4;
  929. break;
  930. case 'Y':
  931. cv_out_sym((yasm_symrec *)cvs->args[arg++].p,
  932. (unsigned long)(buf-bufstart), bc, &buf, d,
  933. output_value);
  934. break;
  935. case 'T':
  936. yasm_intnum_set_uint(cval, cvs->args[arg++].i);
  937. yasm_arch_intnum_tobytes(object->arch, cval, buf, 4, 32, 0,
  938. bc, 0);
  939. buf += 4; /* XXX: will be 2 in CV4 */
  940. break;
  941. case 'S':
  942. len = strlen((char *)cvs->args[arg].p);
  943. len = len <= 0xff ? len : 0xff;
  944. YASM_WRITE_8(buf, len);
  945. memcpy(buf, (char *)cvs->args[arg].p, len);
  946. buf += len;
  947. arg++;
  948. break;
  949. case 'Z':
  950. len = strlen((char *)cvs->args[arg].p)+1;
  951. memcpy(buf, (char *)cvs->args[arg].p, len);
  952. buf += len;
  953. arg++;
  954. break;
  955. default:
  956. yasm_internal_error(N_("unknown leaf format character"));
  957. }
  958. ch++;
  959. }
  960. *bufp = buf;
  961. yasm_intnum_destroy(cval);
  962. return 0;
  963. }