diff options
author | somov <somov@yandex-team.ru> | 2022-02-10 16:45:47 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:45:47 +0300 |
commit | a5950576e397b1909261050b8c7da16db58f10b1 (patch) | |
tree | 7ba7677f6a4c3e19e2cefab34d16df2c8963b4d4 /contrib/tools/yasm/modules/dbgfmts/codeview | |
parent | 81eddc8c0b55990194e112b02d127b87d54164a9 (diff) | |
download | ydb-a5950576e397b1909261050b8c7da16db58f10b1.tar.gz |
Restoring authorship annotation for <somov@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/tools/yasm/modules/dbgfmts/codeview')
-rw-r--r-- | contrib/tools/yasm/modules/dbgfmts/codeview/cv-dbgfmt.c | 214 | ||||
-rw-r--r-- | contrib/tools/yasm/modules/dbgfmts/codeview/cv-dbgfmt.h | 116 | ||||
-rw-r--r-- | contrib/tools/yasm/modules/dbgfmts/codeview/cv-symline.c | 2204 | ||||
-rw-r--r-- | contrib/tools/yasm/modules/dbgfmts/codeview/cv-type.c | 1556 |
4 files changed, 2045 insertions, 2045 deletions
diff --git a/contrib/tools/yasm/modules/dbgfmts/codeview/cv-dbgfmt.c b/contrib/tools/yasm/modules/dbgfmts/codeview/cv-dbgfmt.c index 9b06fe3495..285478dbb6 100644 --- a/contrib/tools/yasm/modules/dbgfmts/codeview/cv-dbgfmt.c +++ b/contrib/tools/yasm/modules/dbgfmts/codeview/cv-dbgfmt.c @@ -1,107 +1,107 @@ -/* - * CodeView debugging formats implementation for Yasm - * - * Copyright (C) 2006-2007 Peter Johnson - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ -#include <util.h> - -#include <libyasm.h> - -#include "cv-dbgfmt.h" - -yasm_dbgfmt_module yasm_cv8_LTX_dbgfmt; - - -static /*@null@*/ /*@only@*/ yasm_dbgfmt * -cv_dbgfmt_create(yasm_object *object, yasm_dbgfmt_module *module, int version) -{ - yasm_dbgfmt_cv *dbgfmt_cv = yasm_xmalloc(sizeof(yasm_dbgfmt_cv)); - size_t i; - - dbgfmt_cv->dbgfmt.module = module; - - dbgfmt_cv->filenames_allocated = 32; - dbgfmt_cv->filenames_size = 0; - dbgfmt_cv->filenames = - yasm_xmalloc(sizeof(cv_filename)*dbgfmt_cv->filenames_allocated); - for (i=0; i<dbgfmt_cv->filenames_allocated; i++) { - dbgfmt_cv->filenames[i].pathname = NULL; - dbgfmt_cv->filenames[i].filename = NULL; - dbgfmt_cv->filenames[i].str_off = 0; - dbgfmt_cv->filenames[i].info_off = 0; - } - - dbgfmt_cv->version = version; - - return (yasm_dbgfmt *)dbgfmt_cv; -} - -static /*@null@*/ /*@only@*/ yasm_dbgfmt * -cv8_dbgfmt_create(yasm_object *object) -{ - return cv_dbgfmt_create(object, &yasm_cv8_LTX_dbgfmt, 8); -} - -static void -cv_dbgfmt_destroy(/*@only@*/ yasm_dbgfmt *dbgfmt) -{ - yasm_dbgfmt_cv *dbgfmt_cv = (yasm_dbgfmt_cv *)dbgfmt; - size_t i; - for (i=0; i<dbgfmt_cv->filenames_size; i++) { - if (dbgfmt_cv->filenames[i].pathname) - yasm_xfree(dbgfmt_cv->filenames[i].pathname); - } - yasm_xfree(dbgfmt_cv->filenames); - yasm_xfree(dbgfmt); -} - -/* Add a bytecode to a section, updating offset on insertion; - * no optimization necessary. - */ -yasm_bytecode * -yasm_cv__append_bc(yasm_section *sect, yasm_bytecode *bc) -{ - yasm_bytecode *precbc = yasm_section_bcs_last(sect); - bc->offset = yasm_bc_next_offset(precbc); - yasm_section_bcs_append(sect, bc); - return precbc; -} - -static void -cv_dbgfmt_generate(yasm_object *object, yasm_linemap *linemap, - yasm_errwarns *errwarns) -{ - yasm_cv__generate_symline(object, linemap, errwarns); - yasm_cv__generate_type(object); -} - -/* Define dbgfmt structure -- see dbgfmt.h for details */ -yasm_dbgfmt_module yasm_cv8_LTX_dbgfmt = { - "CodeView debugging format for VC8", - "cv8", - NULL, /* no directives */ - cv8_dbgfmt_create, - cv_dbgfmt_destroy, - cv_dbgfmt_generate -}; +/* + * CodeView debugging formats implementation for Yasm + * + * Copyright (C) 2006-2007 Peter Johnson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include <util.h> + +#include <libyasm.h> + +#include "cv-dbgfmt.h" + +yasm_dbgfmt_module yasm_cv8_LTX_dbgfmt; + + +static /*@null@*/ /*@only@*/ yasm_dbgfmt * +cv_dbgfmt_create(yasm_object *object, yasm_dbgfmt_module *module, int version) +{ + yasm_dbgfmt_cv *dbgfmt_cv = yasm_xmalloc(sizeof(yasm_dbgfmt_cv)); + size_t i; + + dbgfmt_cv->dbgfmt.module = module; + + dbgfmt_cv->filenames_allocated = 32; + dbgfmt_cv->filenames_size = 0; + dbgfmt_cv->filenames = + yasm_xmalloc(sizeof(cv_filename)*dbgfmt_cv->filenames_allocated); + for (i=0; i<dbgfmt_cv->filenames_allocated; i++) { + dbgfmt_cv->filenames[i].pathname = NULL; + dbgfmt_cv->filenames[i].filename = NULL; + dbgfmt_cv->filenames[i].str_off = 0; + dbgfmt_cv->filenames[i].info_off = 0; + } + + dbgfmt_cv->version = version; + + return (yasm_dbgfmt *)dbgfmt_cv; +} + +static /*@null@*/ /*@only@*/ yasm_dbgfmt * +cv8_dbgfmt_create(yasm_object *object) +{ + return cv_dbgfmt_create(object, &yasm_cv8_LTX_dbgfmt, 8); +} + +static void +cv_dbgfmt_destroy(/*@only@*/ yasm_dbgfmt *dbgfmt) +{ + yasm_dbgfmt_cv *dbgfmt_cv = (yasm_dbgfmt_cv *)dbgfmt; + size_t i; + for (i=0; i<dbgfmt_cv->filenames_size; i++) { + if (dbgfmt_cv->filenames[i].pathname) + yasm_xfree(dbgfmt_cv->filenames[i].pathname); + } + yasm_xfree(dbgfmt_cv->filenames); + yasm_xfree(dbgfmt); +} + +/* Add a bytecode to a section, updating offset on insertion; + * no optimization necessary. + */ +yasm_bytecode * +yasm_cv__append_bc(yasm_section *sect, yasm_bytecode *bc) +{ + yasm_bytecode *precbc = yasm_section_bcs_last(sect); + bc->offset = yasm_bc_next_offset(precbc); + yasm_section_bcs_append(sect, bc); + return precbc; +} + +static void +cv_dbgfmt_generate(yasm_object *object, yasm_linemap *linemap, + yasm_errwarns *errwarns) +{ + yasm_cv__generate_symline(object, linemap, errwarns); + yasm_cv__generate_type(object); +} + +/* Define dbgfmt structure -- see dbgfmt.h for details */ +yasm_dbgfmt_module yasm_cv8_LTX_dbgfmt = { + "CodeView debugging format for VC8", + "cv8", + NULL, /* no directives */ + cv8_dbgfmt_create, + cv_dbgfmt_destroy, + cv_dbgfmt_generate +}; diff --git a/contrib/tools/yasm/modules/dbgfmts/codeview/cv-dbgfmt.h b/contrib/tools/yasm/modules/dbgfmts/codeview/cv-dbgfmt.h index 134b0b885b..d3bbb024e0 100644 --- a/contrib/tools/yasm/modules/dbgfmts/codeview/cv-dbgfmt.h +++ b/contrib/tools/yasm/modules/dbgfmts/codeview/cv-dbgfmt.h @@ -1,58 +1,58 @@ -/* - * CodeView debugging formats implementation for Yasm - * - * Copyright (C) 2006-2007 Peter Johnson - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ -#ifndef YASM_CV_DBGFMT_H -#define YASM_CV_DBGFMT_H - -typedef struct { - char *pathname; /* full pathname (drive+basepath+filename) */ - char *filename; /* filename as yasm knows it internally */ - unsigned long str_off; /* offset into pathname string table */ - unsigned long info_off; /* offset into source info table */ - unsigned char digest[16]; /* MD5 digest of source file */ -} cv_filename; - -/* Global data */ -typedef struct yasm_dbgfmt_cv { - yasm_dbgfmt_base dbgfmt; /* base structure */ - - cv_filename *filenames; - size_t filenames_size; - size_t filenames_allocated; - - int version; -} yasm_dbgfmt_cv; - -yasm_bytecode *yasm_cv__append_bc(yasm_section *sect, yasm_bytecode *bc); - -/* Symbol/Line number functions */ -yasm_section *yasm_cv__generate_symline - (yasm_object *object, yasm_linemap *linemap, yasm_errwarns *errwarns); - -/* Type functions */ -yasm_section *yasm_cv__generate_type(yasm_object *object); - -#endif +/* + * CodeView debugging formats implementation for Yasm + * + * Copyright (C) 2006-2007 Peter Johnson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef YASM_CV_DBGFMT_H +#define YASM_CV_DBGFMT_H + +typedef struct { + char *pathname; /* full pathname (drive+basepath+filename) */ + char *filename; /* filename as yasm knows it internally */ + unsigned long str_off; /* offset into pathname string table */ + unsigned long info_off; /* offset into source info table */ + unsigned char digest[16]; /* MD5 digest of source file */ +} cv_filename; + +/* Global data */ +typedef struct yasm_dbgfmt_cv { + yasm_dbgfmt_base dbgfmt; /* base structure */ + + cv_filename *filenames; + size_t filenames_size; + size_t filenames_allocated; + + int version; +} yasm_dbgfmt_cv; + +yasm_bytecode *yasm_cv__append_bc(yasm_section *sect, yasm_bytecode *bc); + +/* Symbol/Line number functions */ +yasm_section *yasm_cv__generate_symline + (yasm_object *object, yasm_linemap *linemap, yasm_errwarns *errwarns); + +/* Type functions */ +yasm_section *yasm_cv__generate_type(yasm_object *object); + +#endif diff --git a/contrib/tools/yasm/modules/dbgfmts/codeview/cv-symline.c b/contrib/tools/yasm/modules/dbgfmts/codeview/cv-symline.c index 8d7030221f..396def57e2 100644 --- a/contrib/tools/yasm/modules/dbgfmts/codeview/cv-symline.c +++ b/contrib/tools/yasm/modules/dbgfmts/codeview/cv-symline.c @@ -1,1102 +1,1102 @@ -/* - * CodeView debugging format - symbol and line information - * - * Copyright (C) 2006-2007 Peter Johnson - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the author nor the names of other contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ -#include <util.h> - -#include <libyasm.h> - -#include "cv-dbgfmt.h" - -enum cv8_symheadtype { - CV8_DEBUG_SYMS = 0xF1, /* CV5 symbol information */ - CV8_LINE_NUMS = 0xF2, /* line numbers for a section */ - CV8_FILE_STRTAB = 0xF3, /* filename string table */ - CV8_FILE_INFO = 0xF4 /* source file info */ -}; - -enum cv_symtype { - /* Non-modal Symbols */ - CV_S_COMPILE = 0x0001, /* Compile Flag */ - CV_S_REGISTER = 0x0002, /* Register */ - CV_S_CONSTANT = 0x0003, /* Constant */ - CV_S_UDT = 0x0004, /* User-defined Type */ - CV_S_SSEARCH = 0x0005, /* Start Search */ - CV_S_END = 0x0006, /* End of Block */ - CV_S_SKIP = 0x0007, /* Skip Record */ - CV_S_OBJNAME = 0x0009, /* Object File Name */ - CV_S_ENDARG = 0x000a, /* End of Arguments */ - CV_S_COBOLUDT = 0x000b, /* COBOL User-defined Type */ - CV_S_MANYREG = 0x000c, /* Many Registers */ - CV_S_RETURN = 0x000d, /* Function Return */ - CV_S_ENTRYTHIS = 0x000e, /* "this" at Method Entry */ - - /* Symbols for 16:16 Segmented Architectures */ - CV_S_BPREL16 = 0x0100, /* BP Relative 16:16 */ - CV_S_LDATA16 = 0x0101, /* Local Data 16:16 */ - CV_S_GDATA16 = 0x0102, /* Global Data Symbol 16:16 */ - CV_S_PUB16 = 0x0103, /* Public Symbol 16:16 */ - CV_S_LPROC16 = 0x0104, /* Local Start 16:16 */ - CV_S_GPROC16 = 0x0105, /* Global Start 16:16 */ - CV_S_THUNK16 = 0x0106, /* Thunk Start 16:16 */ - CV_S_BLOCK16 = 0x0107, /* Block Start 16:16 */ - CV_S_WITH16 = 0x0108, /* With Start 16:16 */ - CV_S_LABEL16 = 0x0109, /* Code Label 16:16 */ - CV_S_CEXMODEL16 = 0x0110, /* Change Execution Model 16:16 */ - CV_S_VFTPATH16 = 0x010b, /* Virtual Function Table Path 16:16 */ - CV_S_REGREL16 = 0x010c, /* Register Relative 16:16 */ - - /* Symbols for 16:32 Segmented Architectures */ - CV_S_BPREL32 = 0x0200, /* BP Relative 16:32 */ - CV_S_LDATA32 = 0x0201, /* Local Data 16:32 */ - CV_S_GDATA32 = 0x0202, /* Global Data Symbol 16:32 */ - CV_S_PUB32 = 0x0203, /* Public Symbol 16:32 */ - CV_S_LPROC32 = 0x0204, /* Local Start 16:32 */ - CV_S_GPROC32 = 0x0205, /* Global Start 16:32 */ - CV_S_THUNK32 = 0x0206, /* Thunk Start 16:32 */ - CV_S_BLOCK32 = 0x0207, /* Block Start 16:32 */ - CV_S_WITH32 = 0x0208, /* With Start 16:32 */ - CV_S_LABEL32 = 0x0209, /* Code Label 16:32 */ - CV_S_CEXMODEL32 = 0x0210, /* Change Execution Model 16:32 */ - CV_S_VFTPATH32 = 0x020b, /* Virtual Function Table Path 16:32 */ - CV_S_REGREL32 = 0x020c, /* Register Relative 16:32 */ - CV_S_LTHREAD32 = 0x020d, /* Local Thread Storage 16:32 */ - CV_S_GTHREAD32 = 0x020e, /* Global Thread Storage 16:32 */ - - /* Symbols for MIPS */ - CV_S_LPROCMIPS = 0x0300, /* Local procedure start MIPS */ - CV_S_GPROCMIPS = 0x0301, /* Global procedure start MIPS */ - - /* Symbols for CV8 - strings are 0 terminated rather than length-prefix. - * Incomplete and unofficial. - */ - CV8_S_OBJNAME = 0x1101, /* Object File Name */ - CV8_S_LABEL32 = 0x1105, /* Code Label 16:32 */ - CV8_S_LDATA32 = 0x110c, /* Local Data 16:32 */ - CV8_S_GDATA32 = 0x110d, /* Global Data 16:32 */ - CV8_S_LPROC32 = 0x1110, /* Local Start 16:32 */ - CV8_S_COMPILE = 0x1116 /* Compile Flag */ -}; - -typedef struct cv8_symhead { - enum cv8_symheadtype type; - yasm_bytecode *start_prevbc; - yasm_bytecode *end_prevbc; - int first; /* nonzero if first symhead in section */ -} cv8_symhead; - -typedef struct cv8_fileinfo { - const cv_filename *fn; -} cv8_fileinfo; - -/* Note: each line number group is associated with a file AND a section */ -typedef struct cv8_linepair { - unsigned long offset; - unsigned long line; -} cv8_linepair; - -/* Decrease linked list overhead a bit doing it this way */ -typedef struct cv8_lineset { - STAILQ_ENTRY(cv8_lineset) link; - cv8_linepair pairs[126]; - size_t num_pairs; -} cv8_lineset; - -/* Note: Due to line number sorting requirements (by section offset it seems) - * one file may need more than one record per section. */ -typedef struct cv8_lineinfo { - STAILQ_ENTRY(cv8_lineinfo) link; - const cv_filename *fn; /* filename associated with line numbers */ - yasm_section *sect; /* section line numbers are for */ - yasm_symrec *sectsym; /* symbol for beginning of sect */ - unsigned long num_linenums; - int first_in_sect; /* First lineinfo for this section. */ - STAILQ_HEAD(cv8_lineset_head, cv8_lineset) linesets; -} cv8_lineinfo; - -/* Symbols use a bit of meta-programming to encode formats: each character - * of format represents the output generated, as follows: - * 'b' : 1 byte value (integer) - * 'h' : 2 byte value (integer) - * 'w' : 4 byte value (integer) - * 'Y' : symrec SECREL+SECTION (pointer) - * 'T' : type index (integer) - * 'S' : length-prefixed string (pointer) - * 'Z' : 0-terminated string (pointer) - */ -typedef struct cv_sym { - enum cv_symtype type; - const char *format; - union { - unsigned long i; - void *p; - } args[10]; -} cv_sym; - -/* Bytecode callback function prototypes */ -static void cv8_symhead_bc_destroy(void *contents); -static void cv8_symhead_bc_print(const void *contents, FILE *f, - int indent_level); -static int cv8_symhead_bc_calc_len - (yasm_bytecode *bc, yasm_bc_add_span_func add_span, void *add_span_data); -static int cv8_symhead_bc_tobytes - (yasm_bytecode *bc, unsigned char **bufp, unsigned char *bufstart, void *d, - yasm_output_value_func output_value, - /*@null@*/ yasm_output_reloc_func output_reloc); - -static void cv8_fileinfo_bc_destroy(void *contents); -static void cv8_fileinfo_bc_print(const void *contents, FILE *f, - int indent_level); -static int cv8_fileinfo_bc_calc_len - (yasm_bytecode *bc, yasm_bc_add_span_func add_span, void *add_span_data); -static int cv8_fileinfo_bc_tobytes - (yasm_bytecode *bc, unsigned char **bufp, unsigned char *bufstart, void *d, - yasm_output_value_func output_value, - /*@null@*/ yasm_output_reloc_func output_reloc); - -static void cv8_lineinfo_bc_destroy(void *contents); -static void cv8_lineinfo_bc_print(const void *contents, FILE *f, - int indent_level); -static int cv8_lineinfo_bc_calc_len - (yasm_bytecode *bc, yasm_bc_add_span_func add_span, void *add_span_data); -static int cv8_lineinfo_bc_tobytes - (yasm_bytecode *bc, unsigned char **bufp, unsigned char *bufstart, void *d, - yasm_output_value_func output_value, - /*@null@*/ yasm_output_reloc_func output_reloc); - -static void cv_sym_bc_destroy(void *contents); -static void cv_sym_bc_print(const void *contents, FILE *f, int indent_level); -static int cv_sym_bc_calc_len - (yasm_bytecode *bc, yasm_bc_add_span_func add_span, void *add_span_data); -static int cv_sym_bc_tobytes - (yasm_bytecode *bc, unsigned char **bufp, unsigned char *bufstart, void *d, - yasm_output_value_func output_value, - /*@null@*/ yasm_output_reloc_func output_reloc); - -/* Bytecode callback structures */ -static const yasm_bytecode_callback cv8_symhead_bc_callback = { - cv8_symhead_bc_destroy, - cv8_symhead_bc_print, - yasm_bc_finalize_common, - NULL, - cv8_symhead_bc_calc_len, - yasm_bc_expand_common, - cv8_symhead_bc_tobytes, - 0 -}; - -static const yasm_bytecode_callback cv8_fileinfo_bc_callback = { - cv8_fileinfo_bc_destroy, - cv8_fileinfo_bc_print, - yasm_bc_finalize_common, - NULL, - cv8_fileinfo_bc_calc_len, - yasm_bc_expand_common, - cv8_fileinfo_bc_tobytes, - 0 -}; - -static const yasm_bytecode_callback cv8_lineinfo_bc_callback = { - cv8_lineinfo_bc_destroy, - cv8_lineinfo_bc_print, - yasm_bc_finalize_common, - NULL, - cv8_lineinfo_bc_calc_len, - yasm_bc_expand_common, - cv8_lineinfo_bc_tobytes, - 0 -}; - -static const yasm_bytecode_callback cv_sym_bc_callback = { - cv_sym_bc_destroy, - cv_sym_bc_print, - yasm_bc_finalize_common, - NULL, - cv_sym_bc_calc_len, - yasm_bc_expand_common, - cv_sym_bc_tobytes, - 0 -}; - -static cv8_symhead *cv8_add_symhead(yasm_section *sect, unsigned long type, - int first); -static void cv8_set_symhead_end(cv8_symhead *head, yasm_bytecode *end_prevbc); - -static yasm_bytecode *cv8_add_fileinfo - (yasm_section *sect, const cv_filename *fn); - -static unsigned long cv_sym_size(const cv_sym *cvs); - - -static cv_sym * -cv8_add_sym_objname(yasm_section *sect, /*@keep@*/ char *objname) -{ - yasm_bytecode *bc; - cv_sym *cvs = yasm_xmalloc(sizeof(cv_sym)); - cvs->type = CV8_S_OBJNAME; - cvs->format = "wZ"; - cvs->args[0].i = 0; /* signature (0=asm) */ - cvs->args[1].p = objname; /* object filename */ - - bc = yasm_bc_create_common(&cv_sym_bc_callback, cvs, 0); - bc->len = cv_sym_size(cvs); - yasm_cv__append_bc(sect, bc); - return cvs; -} - -static cv_sym * -cv8_add_sym_compile(yasm_object *object, yasm_section *sect, - /*@keep@*/ char *creator) -{ - yasm_bytecode *bc; - cv_sym *cvs = yasm_xmalloc(sizeof(cv_sym)); - cvs->type = CV8_S_COMPILE; - cvs->format = "wwwwZh"; - cvs->args[0].i = 3; /* language (3=Masm) */ - - /* target processor; 0xD0 = AMD64 */ - if (strcmp(yasm_arch_keyword(object->arch), "x86") == 0) { - if (strcmp(yasm_arch_get_machine(object->arch), "amd64") == 0) - cvs->args[1].i = 0xD0; - else - cvs->args[1].i = 0x6; /* 686, FIXME */ - } else - cvs->args[1].i = 0; /* XXX: unknown */ - - cvs->args[2].i = 0; /* flags (assume 0 for now) */ - cvs->args[3].i = 0; /* creator version number (assume 0 for now) */ - cvs->args[4].p = creator; /* creator string */ - cvs->args[5].i = 0; /* no pairs of key/value */ - - bc = yasm_bc_create_common(&cv_sym_bc_callback, cvs, 0); - bc->len = cv_sym_size(cvs); - yasm_cv__append_bc(sect, bc); - return cvs; -} - -static cv_sym * -cv8_add_sym_label(yasm_section *sect, yasm_symrec *sym) -{ - yasm_bytecode *bc; - cv_sym *cvs = yasm_xmalloc(sizeof(cv_sym)); - cvs->type = CV8_S_LABEL32; - cvs->format = "YbZ"; - cvs->args[0].p = sym; /* symrec for label */ - cvs->args[1].i = 0; /* flags (assume 0 for now) */ - cvs->args[2].p = yasm__xstrdup(yasm_symrec_get_name(sym)); - - bc = yasm_bc_create_common(&cv_sym_bc_callback, cvs, 0); - bc->len = cv_sym_size(cvs); - yasm_cv__append_bc(sect, bc); - return cvs; -} - -static cv_sym * -cv8_add_sym_data(yasm_section *sect, unsigned long type, yasm_symrec *sym, - int is_global) -{ - yasm_bytecode *bc; - cv_sym *cvs = yasm_xmalloc(sizeof(cv_sym)); - cvs->type = is_global ? CV8_S_GDATA32 : CV8_S_LDATA32; - cvs->format = "wYZ"; - cvs->args[0].i = type; /* type index */ - cvs->args[1].p = sym; /* symrec for label */ - cvs->args[2].p = yasm__xstrdup(yasm_symrec_get_name(sym)); - - bc = yasm_bc_create_common(&cv_sym_bc_callback, cvs, 0); - bc->len = cv_sym_size(cvs); - yasm_cv__append_bc(sect, bc); - return cvs; -} - -static size_t -cv_dbgfmt_add_file(yasm_dbgfmt_cv *dbgfmt_cv, size_t filenum, - const char *filename) -{ - char *pathname; - size_t i; - yasm_md5_context context; - FILE *f; - unsigned char *buf; - size_t len; - - /* Put the filename into the filename table */ - if (filenum == 0) { - /* Look to see if we already have that filename in the table */ - for (; filenum<dbgfmt_cv->filenames_size; filenum++) { - if (!dbgfmt_cv->filenames[filenum].filename || - strcmp(dbgfmt_cv->filenames[filenum].filename, filename) == 0) - break; - } - } else - filenum--; /* array index is 0-based */ - - /* Realloc table if necessary */ - if (filenum >= dbgfmt_cv->filenames_allocated) { - size_t old_allocated = dbgfmt_cv->filenames_allocated; - dbgfmt_cv->filenames_allocated = filenum+32; - dbgfmt_cv->filenames = yasm_xrealloc(dbgfmt_cv->filenames, - sizeof(cv_filename)*dbgfmt_cv->filenames_allocated); - for (i=old_allocated; i<dbgfmt_cv->filenames_allocated; i++) { - dbgfmt_cv->filenames[i].pathname = NULL; - dbgfmt_cv->filenames[i].filename = NULL; - dbgfmt_cv->filenames[i].str_off = 0; - dbgfmt_cv->filenames[i].info_off = 0; - } - } - - /* Calculate MD5 checksum of file */ - buf = yasm_xmalloc(1024); - yasm_md5_init(&context); - f = fopen(filename, "rb"); - if (!f) - yasm__fatal(N_("codeview: could not open source file")); - while ((len = fread(buf, 1, 1024, f)) > 0) - yasm_md5_update(&context, buf, (unsigned long)len); - yasm_md5_final(dbgfmt_cv->filenames[filenum].digest, &context); - fclose(f); - yasm_xfree(buf); - - /* Actually save in table */ - if (dbgfmt_cv->filenames[filenum].pathname) - yasm_xfree(dbgfmt_cv->filenames[filenum].pathname); - if (dbgfmt_cv->filenames[filenum].filename) - yasm_xfree(dbgfmt_cv->filenames[filenum].filename); - - pathname = yasm__abspath(filename); - dbgfmt_cv->filenames[filenum].pathname = pathname; - dbgfmt_cv->filenames[filenum].filename = yasm__xstrdup(filename); - - /* Update table size */ - if (filenum >= dbgfmt_cv->filenames_size) - dbgfmt_cv->filenames_size = filenum + 1; - - return filenum; -} - -static yasm_bytecode * -cv_append_str(yasm_section *sect, const char *str) -{ - yasm_datavalhead dvs; - yasm_bytecode *bc; - - yasm_dvs_initialize(&dvs); - yasm_dvs_append(&dvs, yasm_dv_create_string(yasm__xstrdup(str), - strlen(str))); - bc = yasm_bc_create_data(&dvs, 1, 1, NULL, 0); - yasm_bc_finalize(bc, yasm_cv__append_bc(sect, bc)); - yasm_bc_calc_len(bc, NULL, NULL); - return bc; -} - -typedef struct cv_line_info { - yasm_section *debug_symline; - yasm_object *object; - yasm_dbgfmt_cv *dbgfmt_cv; - yasm_linemap *linemap; - yasm_errwarns *errwarns; - unsigned int num_lineinfos; - STAILQ_HEAD(cv8_lineinfo_head, cv8_lineinfo) cv8_lineinfos; - /*@null@*/ cv8_lineinfo *cv8_cur_li; - /*@null@*/ cv8_lineset *cv8_cur_ls; -} cv_line_info; - -static int -cv_generate_line_bc(yasm_bytecode *bc, /*@null@*/ void *d) -{ - cv_line_info *info = (cv_line_info *)d; - yasm_dbgfmt_cv *dbgfmt_cv = info->dbgfmt_cv; - size_t i; - const char *filename; - unsigned long line; - /*@null@*/ yasm_bytecode *nextbc = yasm_bc__next(bc); - yasm_section *sect = yasm_bc_get_section(bc); - - if (nextbc && bc->offset == nextbc->offset) - return 0; - - yasm_linemap_lookup(info->linemap, bc->line, &filename, &line); - - if (!info->cv8_cur_li - || strcmp(filename, info->cv8_cur_li->fn->filename) != 0) { - yasm_bytecode *sectbc; - char symname[8]; - int first_in_sect = !info->cv8_cur_li; - - /* Find file */ - for (i=0; i<dbgfmt_cv->filenames_size; i++) { - if (strcmp(filename, dbgfmt_cv->filenames[i].filename) == 0) - break; - } - if (i >= dbgfmt_cv->filenames_size) - yasm_internal_error(N_("could not find filename in table")); - - /* and create new lineinfo structure */ - info->cv8_cur_li = yasm_xmalloc(sizeof(cv8_lineinfo)); - info->cv8_cur_li->fn = &dbgfmt_cv->filenames[i]; - info->cv8_cur_li->sect = sect; - info->cv8_cur_li->first_in_sect = first_in_sect; - sectbc = yasm_section_bcs_first(sect); - if (sectbc->symrecs && sectbc->symrecs[0]) - info->cv8_cur_li->sectsym = sectbc->symrecs[0]; - else { - sprintf(symname, ".%06u", info->num_lineinfos++); - info->cv8_cur_li->sectsym = - yasm_symtab_define_label(info->object->symtab, symname, sectbc, - 1, 0); - } - info->cv8_cur_li->num_linenums = 0; - STAILQ_INIT(&info->cv8_cur_li->linesets); - STAILQ_INSERT_TAIL(&info->cv8_lineinfos, info->cv8_cur_li, link); - info->cv8_cur_ls = NULL; - } - - /* build new lineset if necessary */ - if (!info->cv8_cur_ls || info->cv8_cur_ls->num_pairs >= 126) { - info->cv8_cur_ls = yasm_xmalloc(sizeof(cv8_lineset)); - info->cv8_cur_ls->num_pairs = 0; - STAILQ_INSERT_TAIL(&info->cv8_cur_li->linesets, info->cv8_cur_ls, link); - } - - /* add linepair for this bytecode */ - info->cv8_cur_ls->pairs[info->cv8_cur_ls->num_pairs].offset = bc->offset; - info->cv8_cur_ls->pairs[info->cv8_cur_ls->num_pairs].line = - 0x80000000 | line; - info->cv8_cur_ls->num_pairs++; - info->cv8_cur_li->num_linenums++; - - return 0; -} - -static int -cv_generate_line_section(yasm_section *sect, /*@null@*/ void *d) -{ - cv_line_info *info = (cv_line_info *)d; - - if (!yasm_section_is_code(sect)) - return 0; /* not code, so no line data for this section */ - - info->cv8_cur_li = NULL; - info->cv8_cur_ls = NULL; - - yasm_section_bcs_traverse(sect, info->errwarns, info, cv_generate_line_bc); - - return 0; -} - -static int -cv_generate_filename(const char *filename, void *d) -{ - cv_dbgfmt_add_file((yasm_dbgfmt_cv *)d, 0, filename); - return 0; -} - -static int -cv_generate_sym(yasm_symrec *sym, void *d) -{ - cv_line_info *info = (cv_line_info *)d; - yasm_bytecode *precbc; - const char *name = yasm_symrec_get_name(sym); - - /* only care about labels (for now). Don't put in symbols starting with - * ".", as these are typically internally generated ones (like section - * symbols). - */ - if (name[0] == '.' || !yasm_symrec_get_label(sym, &precbc)) - return 0; - - /* TODO: add data types; until then, just mark everything as UBYTE */ - if (yasm_section_is_code(yasm_bc_get_section(precbc))) - cv8_add_sym_label(info->debug_symline, sym); - else - cv8_add_sym_data(info->debug_symline, 0x20, sym, - yasm_symrec_get_visibility(sym) & YASM_SYM_GLOBAL?1:0); - return 0; -} - -yasm_section * -yasm_cv__generate_symline(yasm_object *object, yasm_linemap *linemap, - yasm_errwarns *errwarns) -{ - yasm_dbgfmt_cv *dbgfmt_cv = (yasm_dbgfmt_cv *)object->dbgfmt; - cv_line_info info; - int new; - size_t i; - cv8_symhead *head; - cv8_lineinfo *li; - yasm_bytecode *bc; - unsigned long off; - - /* Generate filenames based on linemap */ - yasm_linemap_traverse_filenames(linemap, dbgfmt_cv, - cv_generate_filename); - - info.object = object; - info.dbgfmt_cv = dbgfmt_cv; - info.linemap = linemap; - info.errwarns = errwarns; - info.debug_symline = - yasm_object_get_general(object, ".debug$S", 1, 0, 0, &new, 0); - info.num_lineinfos = 0; - STAILQ_INIT(&info.cv8_lineinfos); - info.cv8_cur_li = NULL; - info.cv8_cur_ls = NULL; - - /* source filenames string table */ - head = cv8_add_symhead(info.debug_symline, CV8_FILE_STRTAB, 1); - cv_append_str(info.debug_symline, ""); - off = 1; - for (i=0; i<dbgfmt_cv->filenames_size; i++) { - if (!dbgfmt_cv->filenames[i].pathname) { - yasm_error_set(YASM_ERROR_GENERAL, - N_("codeview file number %d unassigned"), i+1); - yasm_errwarn_propagate(errwarns, 0); - continue; - } - bc = cv_append_str(info.debug_symline, - dbgfmt_cv->filenames[i].pathname); - dbgfmt_cv->filenames[i].str_off = off; - off += bc->len; - } - cv8_set_symhead_end(head, yasm_section_bcs_last(info.debug_symline)); - - /* Align 4 */ - bc = yasm_bc_create_align - (yasm_expr_create_ident(yasm_expr_int(yasm_intnum_create_uint(4)), 0), - NULL, NULL, NULL, 0); - yasm_bc_finalize(bc, yasm_cv__append_bc(info.debug_symline, bc)); - yasm_bc_calc_len(bc, NULL, NULL); - - /* source file info table */ - head = cv8_add_symhead(info.debug_symline, CV8_FILE_INFO, 0); - off = 0; - for (i=0; i<dbgfmt_cv->filenames_size; i++) { - if (!dbgfmt_cv->filenames[i].pathname) - continue; - bc = cv8_add_fileinfo(info.debug_symline, &dbgfmt_cv->filenames[i]); - dbgfmt_cv->filenames[i].info_off = off; - off += bc->len; - } - cv8_set_symhead_end(head, yasm_section_bcs_last(info.debug_symline)); - - /* Already aligned 4 */ - - /* Generate line numbers for sections */ - yasm_object_sections_traverse(object, (void *)&info, - cv_generate_line_section); - - /* Output line numbers for sections */ - head = NULL; - STAILQ_FOREACH(li, &info.cv8_lineinfos, link) { - if (li->first_in_sect) { - if (head) - cv8_set_symhead_end(head, yasm_section_bcs_last(info.debug_symline)); - head = cv8_add_symhead(info.debug_symline, CV8_LINE_NUMS, 0); - } - bc = yasm_bc_create_common(&cv8_lineinfo_bc_callback, li, 0); - bc->len = (li->first_in_sect ? 24 : 12) + li->num_linenums*8; - yasm_cv__append_bc(info.debug_symline, bc); - } - if (head) - cv8_set_symhead_end(head, yasm_section_bcs_last(info.debug_symline)); - - /* Already aligned 4 */ - - /* Output debugging symbols */ - head = cv8_add_symhead(info.debug_symline, CV8_DEBUG_SYMS, 0); - /* add object and compile flag first */ - cv8_add_sym_objname(info.debug_symline, - yasm__abspath(object->obj_filename)); - if (getenv("YASM_TEST_SUITE")) - cv8_add_sym_compile(object, info.debug_symline, - yasm__xstrdup("yasm HEAD")); - else - cv8_add_sym_compile(object, info.debug_symline, - yasm__xstrdup(PACKAGE_STRING)); - /* then iterate through symbol table */ - yasm_symtab_traverse(object->symtab, &info, cv_generate_sym); - cv8_set_symhead_end(head, yasm_section_bcs_last(info.debug_symline)); - - /* Align 4 at end */ - bc = yasm_bc_create_align - (yasm_expr_create_ident(yasm_expr_int(yasm_intnum_create_uint(4)), 0), - NULL, NULL, NULL, 0); - yasm_bc_finalize(bc, yasm_cv__append_bc(info.debug_symline, bc)); - yasm_bc_calc_len(bc, NULL, NULL); - - return info.debug_symline; -} - -static void -cv_out_sym(yasm_symrec *sym, unsigned long off, yasm_bytecode *bc, - unsigned char **bufp, void *d, yasm_output_value_func output_value) -{ - yasm_value val; - - /* sym in its section */ - yasm_value_init_sym(&val, sym, 32); - val.section_rel = 1; - output_value(&val, *bufp, 4, off, bc, 0, d); - *bufp += 4; - - /* section index */ - yasm_value_init_sym(&val, sym, 16); - val.seg_of = 1; - output_value(&val, *bufp, 2, off+4, bc, 0, d); - *bufp += 2; -} - -static cv8_symhead * -cv8_add_symhead(yasm_section *sect, unsigned long type, int first) -{ - cv8_symhead *head; - yasm_bytecode *bc; - - head = yasm_xmalloc(sizeof(cv8_symhead)); - head->type = type; - head->first = first; - head->start_prevbc = yasm_section_bcs_last(sect); - - bc = yasm_bc_create_common(&cv8_symhead_bc_callback, head, 0); - if (first) - bc->len = 12; - else - bc->len = 8; - - head->end_prevbc = bc; - yasm_cv__append_bc(sect, bc); - return head; -} - -static void -cv8_set_symhead_end(cv8_symhead *head, yasm_bytecode *end_prevbc) -{ - head->end_prevbc = end_prevbc; -} - -static void -cv8_symhead_bc_destroy(void *contents) -{ - yasm_xfree(contents); -} - -static void -cv8_symhead_bc_print(const void *contents, FILE *f, int indent_level) -{ - /* TODO */ -} - -static int -cv8_symhead_bc_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span, - void *add_span_data) -{ - yasm_internal_error(N_("tried to calc_len a codeview symhead bytecode")); - /*@notreached@*/ - return 0; -} - -static int -cv8_symhead_bc_tobytes(yasm_bytecode *bc, unsigned char **bufp, - unsigned char *bufstart, void *d, - yasm_output_value_func output_value, - yasm_output_reloc_func output_reloc) -{ - yasm_object *object = yasm_section_get_object(bc->section); - cv8_symhead *head = (cv8_symhead *)bc->contents; - unsigned char *buf = *bufp; - yasm_intnum *intn, *cval; - - cval = yasm_intnum_create_uint(4); - /* Output "version" if first */ - if (head->first) { - yasm_arch_intnum_tobytes(object->arch, cval, buf, 4, 32, 0, bc, 0); - buf += 4; - } - - /* Type contained - 4 bytes */ - yasm_intnum_set_uint(cval, head->type); - yasm_arch_intnum_tobytes(object->arch, cval, buf, 4, 32, 0, bc, 0); - buf += 4; - - /* Total length of info (following this field) - 4 bytes */ - yasm_intnum_set_uint(cval, bc->len); - intn = yasm_calc_bc_dist(head->start_prevbc, head->end_prevbc); - yasm_intnum_calc(intn, YASM_EXPR_SUB, cval); - yasm_arch_intnum_tobytes(object->arch, intn, buf, 4, 32, 0, bc, 0); - buf += 4; - yasm_intnum_destroy(intn); - - *bufp = buf; - - yasm_intnum_destroy(cval); - return 0; -} - -static yasm_bytecode * -cv8_add_fileinfo(yasm_section *sect, const cv_filename *fn) -{ - cv8_fileinfo *fi; - yasm_bytecode *bc; - - fi = yasm_xmalloc(sizeof(cv8_fileinfo)); - fi->fn = fn; - - bc = yasm_bc_create_common(&cv8_fileinfo_bc_callback, fi, 0); - bc->len = 24; - - yasm_cv__append_bc(sect, bc); - return bc; -} - -static void -cv8_fileinfo_bc_destroy(void *contents) -{ - yasm_xfree(contents); -} - -static void -cv8_fileinfo_bc_print(const void *contents, FILE *f, int indent_level) -{ - /* TODO */ -} - -static int -cv8_fileinfo_bc_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span, - void *add_span_data) -{ - yasm_internal_error(N_("tried to calc_len a codeview fileinfo bytecode")); - /*@notreached@*/ - return 0; -} - -static int -cv8_fileinfo_bc_tobytes(yasm_bytecode *bc, unsigned char **bufp, - unsigned char *bufstart, void *d, - yasm_output_value_func output_value, - yasm_output_reloc_func output_reloc) -{ - yasm_object *object = yasm_section_get_object(bc->section); - cv8_fileinfo *fi = (cv8_fileinfo *)bc->contents; - unsigned char *buf = *bufp; - yasm_intnum *cval; - int i; - - /* Offset in filename string table */ - cval = yasm_intnum_create_uint(fi->fn->str_off); - yasm_arch_intnum_tobytes(object->arch, cval, buf, 4, 32, 0, bc, 0); - buf += 4; - - /* Checksum type/length */ - yasm_intnum_set_uint(cval, 0x0110); - yasm_arch_intnum_tobytes(object->arch, cval, buf, 2, 16, 0, bc, 0); - buf += 2; - - /* Checksum */ - for (i=0; i<16; i++) - YASM_WRITE_8(buf, fi->fn->digest[i]); - - /* Pad */ - YASM_WRITE_8(buf, 0); - YASM_WRITE_8(buf, 0); - - *bufp = buf; - - yasm_intnum_destroy(cval); - return 0; -} - -static void -cv8_lineinfo_bc_destroy(void *contents) -{ - cv8_lineinfo *li = (cv8_lineinfo *)contents; - cv8_lineset *ls1, *ls2; - - /* delete line sets */ - ls1 = STAILQ_FIRST(&li->linesets); - while (ls1) { - ls2 = STAILQ_NEXT(ls1, link); - yasm_xfree(ls1); - ls1 = ls2; - } - - yasm_xfree(contents); -} - -static void -cv8_lineinfo_bc_print(const void *contents, FILE *f, int indent_level) -{ - /* TODO */ -} - -static int -cv8_lineinfo_bc_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span, - void *add_span_data) -{ - yasm_internal_error(N_("tried to calc_len a codeview linehead bytecode")); - /*@notreached@*/ - return 0; -} - -static int -cv8_lineinfo_bc_tobytes(yasm_bytecode *bc, unsigned char **bufp, - unsigned char *bufstart, void *d, - yasm_output_value_func output_value, - yasm_output_reloc_func output_reloc) -{ - yasm_object *object = yasm_section_get_object(bc->section); - cv8_lineinfo *li = (cv8_lineinfo *)bc->contents; - unsigned char *buf = *bufp; - yasm_intnum *cval; - unsigned long i; - cv8_lineset *ls; - - if (li->first_in_sect) { - /* start offset and section */ - cv_out_sym(li->sectsym, (unsigned long)(buf - bufstart), bc, &buf, - d, output_value); - - /* Two bytes of pad/alignment */ - YASM_WRITE_8(buf, 0); - YASM_WRITE_8(buf, 0); - - /* Section length covered by line number info */ - cval = yasm_calc_bc_dist(yasm_section_bcs_first(li->sect), - yasm_section_bcs_last(li->sect)); - yasm_arch_intnum_tobytes(object->arch, cval, buf, 4, 32, 0, bc, 0); - yasm_intnum_destroy(cval); - buf += 4; - } - - /* Offset of source file in info table */ - cval = yasm_intnum_create_uint(li->fn->info_off); - yasm_arch_intnum_tobytes(object->arch, cval, buf, 4, 32, 0, bc, 0); - buf += 4; - - /* Number of line number pairs */ - yasm_intnum_set_uint(cval, li->num_linenums); - yasm_arch_intnum_tobytes(object->arch, cval, buf, 4, 32, 0, bc, 0); - buf += 4; - - /* Number of bytes of line number pairs + 12 (no, I don't know why) */ - yasm_intnum_set_uint(cval, li->num_linenums*8+12); - yasm_arch_intnum_tobytes(object->arch, cval, buf, 4, 32, 0, bc, 0); - buf += 4; - - /* Offset / line number pairs */ - i = 0; - STAILQ_FOREACH(ls, &li->linesets, link) { - unsigned long j; - for (j=0; i<li->num_linenums && j<126; i++, j++) { - /* offset in section */ - yasm_intnum_set_uint(cval, ls->pairs[j].offset); - yasm_arch_intnum_tobytes(object->arch, cval, buf, 4, 32, 0, bc, 0); - buf += 4; - - /* line number in file */ - yasm_intnum_set_uint(cval, ls->pairs[j].line); - yasm_arch_intnum_tobytes(object->arch, cval, buf, 4, 32, 0, bc, 0); - buf += 4; - } - } - - *bufp = buf; - - yasm_intnum_destroy(cval); - return 0; -} - -static unsigned long -cv_sym_size(const cv_sym *cvs) -{ - const char *ch = cvs->format; - unsigned long len = 4; /* sym length and type */ - unsigned long slen; - int arg = 0; - - while (*ch) { - switch (*ch) { - case 'b': - len++; - arg++; - break; - case 'h': - len += 2; - arg++; - break; - case 'w': - len += 4; - arg++; - break; - case 'Y': - len += 6; /* XXX: will be 4 in 16-bit version */ - arg++; - break; - case 'T': - len += 4; /* XXX: will be 2 in CV4 */ - arg++; - break; - case 'S': - len += 1; /* XXX: is this 1 or 2? */ - slen = (unsigned long)strlen((const char *)cvs->args[arg++].p); - len += slen <= 0xff ? slen : 0xff; - break; - case 'Z': - len += - (unsigned long)strlen((const char *)cvs->args[arg++].p) + 1; - break; - default: - yasm_internal_error(N_("unknown sym format character")); - } - ch++; - } - - return len; -} - -static void -cv_sym_bc_destroy(void *contents) -{ - cv_sym *cvs = (cv_sym *)contents; - const char *ch = cvs->format; - int arg = 0; - - while (*ch) { - switch (*ch) { - case 'b': - case 'h': - case 'w': - case 'Y': - case 'T': - arg++; - break; /* nothing to destroy */ - case 'S': - case 'Z': - yasm_xfree(cvs->args[arg++].p); - break; - default: - yasm_internal_error(N_("unknown sym format character")); - } - ch++; - } - - yasm_xfree(contents); -} - -static void -cv_sym_bc_print(const void *contents, FILE *f, int indent_level) -{ - /* TODO */ -} - -static int -cv_sym_bc_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span, - void *add_span_data) -{ - yasm_internal_error(N_("tried to calc_len a codeview sym bytecode")); - /*@notreached@*/ - return 0; -} - -static int -cv_sym_bc_tobytes(yasm_bytecode *bc, unsigned char **bufp, - unsigned char *bufstart, void *d, - yasm_output_value_func output_value, - yasm_output_reloc_func output_reloc) -{ - yasm_object *object = yasm_section_get_object(bc->section); - cv_sym *cvs = (cv_sym *)bc->contents; - unsigned char *buf = *bufp; - yasm_intnum *cval; - const char *ch = cvs->format; - size_t len; - int arg = 0; - - /* Total length of record (following this field) - 2 bytes */ - cval = yasm_intnum_create_uint(bc->len-2); - yasm_arch_intnum_tobytes(object->arch, cval, buf, 2, 16, 0, bc, 1); - buf += 2; - - /* Type contained - 2 bytes */ - yasm_intnum_set_uint(cval, cvs->type); - yasm_arch_intnum_tobytes(object->arch, cval, buf, 2, 16, 0, bc, 0); - buf += 2; - - while (*ch) { - switch (*ch) { - case 'b': - YASM_WRITE_8(buf, cvs->args[arg].i); - arg++; - break; - case 'h': - yasm_intnum_set_uint(cval, cvs->args[arg++].i); - yasm_arch_intnum_tobytes(object->arch, cval, buf, 2, 16, 0, - bc, 0); - buf += 2; - break; - case 'w': - yasm_intnum_set_uint(cval, cvs->args[arg++].i); - yasm_arch_intnum_tobytes(object->arch, cval, buf, 4, 32, 0, - bc, 0); - buf += 4; - break; - case 'Y': - cv_out_sym((yasm_symrec *)cvs->args[arg++].p, - (unsigned long)(buf-bufstart), bc, &buf, d, - output_value); - break; - case 'T': - yasm_intnum_set_uint(cval, cvs->args[arg++].i); - yasm_arch_intnum_tobytes(object->arch, cval, buf, 4, 32, 0, - bc, 0); - buf += 4; /* XXX: will be 2 in CV4 */ - break; - case 'S': - len = strlen((char *)cvs->args[arg].p); - len = len <= 0xff ? len : 0xff; - YASM_WRITE_8(buf, len); - memcpy(buf, (char *)cvs->args[arg].p, len); - buf += len; - arg++; - break; - case 'Z': - len = strlen((char *)cvs->args[arg].p)+1; - memcpy(buf, (char *)cvs->args[arg].p, len); - buf += len; - arg++; - break; - default: - yasm_internal_error(N_("unknown leaf format character")); - } - ch++; - } - - *bufp = buf; - - yasm_intnum_destroy(cval); - return 0; -} +/* + * CodeView debugging format - symbol and line information + * + * Copyright (C) 2006-2007 Peter Johnson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of other contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include <util.h> + +#include <libyasm.h> + +#include "cv-dbgfmt.h" + +enum cv8_symheadtype { + CV8_DEBUG_SYMS = 0xF1, /* CV5 symbol information */ + CV8_LINE_NUMS = 0xF2, /* line numbers for a section */ + CV8_FILE_STRTAB = 0xF3, /* filename string table */ + CV8_FILE_INFO = 0xF4 /* source file info */ +}; + +enum cv_symtype { + /* Non-modal Symbols */ + CV_S_COMPILE = 0x0001, /* Compile Flag */ + CV_S_REGISTER = 0x0002, /* Register */ + CV_S_CONSTANT = 0x0003, /* Constant */ + CV_S_UDT = 0x0004, /* User-defined Type */ + CV_S_SSEARCH = 0x0005, /* Start Search */ + CV_S_END = 0x0006, /* End of Block */ + CV_S_SKIP = 0x0007, /* Skip Record */ + CV_S_OBJNAME = 0x0009, /* Object File Name */ + CV_S_ENDARG = 0x000a, /* End of Arguments */ + CV_S_COBOLUDT = 0x000b, /* COBOL User-defined Type */ + CV_S_MANYREG = 0x000c, /* Many Registers */ + CV_S_RETURN = 0x000d, /* Function Return */ + CV_S_ENTRYTHIS = 0x000e, /* "this" at Method Entry */ + + /* Symbols for 16:16 Segmented Architectures */ + CV_S_BPREL16 = 0x0100, /* BP Relative 16:16 */ + CV_S_LDATA16 = 0x0101, /* Local Data 16:16 */ + CV_S_GDATA16 = 0x0102, /* Global Data Symbol 16:16 */ + CV_S_PUB16 = 0x0103, /* Public Symbol 16:16 */ + CV_S_LPROC16 = 0x0104, /* Local Start 16:16 */ + CV_S_GPROC16 = 0x0105, /* Global Start 16:16 */ + CV_S_THUNK16 = 0x0106, /* Thunk Start 16:16 */ + CV_S_BLOCK16 = 0x0107, /* Block Start 16:16 */ + CV_S_WITH16 = 0x0108, /* With Start 16:16 */ + CV_S_LABEL16 = 0x0109, /* Code Label 16:16 */ + CV_S_CEXMODEL16 = 0x0110, /* Change Execution Model 16:16 */ + CV_S_VFTPATH16 = 0x010b, /* Virtual Function Table Path 16:16 */ + CV_S_REGREL16 = 0x010c, /* Register Relative 16:16 */ + + /* Symbols for 16:32 Segmented Architectures */ + CV_S_BPREL32 = 0x0200, /* BP Relative 16:32 */ + CV_S_LDATA32 = 0x0201, /* Local Data 16:32 */ + CV_S_GDATA32 = 0x0202, /* Global Data Symbol 16:32 */ + CV_S_PUB32 = 0x0203, /* Public Symbol 16:32 */ + CV_S_LPROC32 = 0x0204, /* Local Start 16:32 */ + CV_S_GPROC32 = 0x0205, /* Global Start 16:32 */ + CV_S_THUNK32 = 0x0206, /* Thunk Start 16:32 */ + CV_S_BLOCK32 = 0x0207, /* Block Start 16:32 */ + CV_S_WITH32 = 0x0208, /* With Start 16:32 */ + CV_S_LABEL32 = 0x0209, /* Code Label 16:32 */ + CV_S_CEXMODEL32 = 0x0210, /* Change Execution Model 16:32 */ + CV_S_VFTPATH32 = 0x020b, /* Virtual Function Table Path 16:32 */ + CV_S_REGREL32 = 0x020c, /* Register Relative 16:32 */ + CV_S_LTHREAD32 = 0x020d, /* Local Thread Storage 16:32 */ + CV_S_GTHREAD32 = 0x020e, /* Global Thread Storage 16:32 */ + + /* Symbols for MIPS */ + CV_S_LPROCMIPS = 0x0300, /* Local procedure start MIPS */ + CV_S_GPROCMIPS = 0x0301, /* Global procedure start MIPS */ + + /* Symbols for CV8 - strings are 0 terminated rather than length-prefix. + * Incomplete and unofficial. + */ + CV8_S_OBJNAME = 0x1101, /* Object File Name */ + CV8_S_LABEL32 = 0x1105, /* Code Label 16:32 */ + CV8_S_LDATA32 = 0x110c, /* Local Data 16:32 */ + CV8_S_GDATA32 = 0x110d, /* Global Data 16:32 */ + CV8_S_LPROC32 = 0x1110, /* Local Start 16:32 */ + CV8_S_COMPILE = 0x1116 /* Compile Flag */ +}; + +typedef struct cv8_symhead { + enum cv8_symheadtype type; + yasm_bytecode *start_prevbc; + yasm_bytecode *end_prevbc; + int first; /* nonzero if first symhead in section */ +} cv8_symhead; + +typedef struct cv8_fileinfo { + const cv_filename *fn; +} cv8_fileinfo; + +/* Note: each line number group is associated with a file AND a section */ +typedef struct cv8_linepair { + unsigned long offset; + unsigned long line; +} cv8_linepair; + +/* Decrease linked list overhead a bit doing it this way */ +typedef struct cv8_lineset { + STAILQ_ENTRY(cv8_lineset) link; + cv8_linepair pairs[126]; + size_t num_pairs; +} cv8_lineset; + +/* Note: Due to line number sorting requirements (by section offset it seems) + * one file may need more than one record per section. */ +typedef struct cv8_lineinfo { + STAILQ_ENTRY(cv8_lineinfo) link; + const cv_filename *fn; /* filename associated with line numbers */ + yasm_section *sect; /* section line numbers are for */ + yasm_symrec *sectsym; /* symbol for beginning of sect */ + unsigned long num_linenums; + int first_in_sect; /* First lineinfo for this section. */ + STAILQ_HEAD(cv8_lineset_head, cv8_lineset) linesets; +} cv8_lineinfo; + +/* Symbols use a bit of meta-programming to encode formats: each character + * of format represents the output generated, as follows: + * 'b' : 1 byte value (integer) + * 'h' : 2 byte value (integer) + * 'w' : 4 byte value (integer) + * 'Y' : symrec SECREL+SECTION (pointer) + * 'T' : type index (integer) + * 'S' : length-prefixed string (pointer) + * 'Z' : 0-terminated string (pointer) + */ +typedef struct cv_sym { + enum cv_symtype type; + const char *format; + union { + unsigned long i; + void *p; + } args[10]; +} cv_sym; + +/* Bytecode callback function prototypes */ +static void cv8_symhead_bc_destroy(void *contents); +static void cv8_symhead_bc_print(const void *contents, FILE *f, + int indent_level); +static int cv8_symhead_bc_calc_len + (yasm_bytecode *bc, yasm_bc_add_span_func add_span, void *add_span_data); +static int cv8_symhead_bc_tobytes + (yasm_bytecode *bc, unsigned char **bufp, unsigned char *bufstart, void *d, + yasm_output_value_func output_value, + /*@null@*/ yasm_output_reloc_func output_reloc); + +static void cv8_fileinfo_bc_destroy(void *contents); +static void cv8_fileinfo_bc_print(const void *contents, FILE *f, + int indent_level); +static int cv8_fileinfo_bc_calc_len + (yasm_bytecode *bc, yasm_bc_add_span_func add_span, void *add_span_data); +static int cv8_fileinfo_bc_tobytes + (yasm_bytecode *bc, unsigned char **bufp, unsigned char *bufstart, void *d, + yasm_output_value_func output_value, + /*@null@*/ yasm_output_reloc_func output_reloc); + +static void cv8_lineinfo_bc_destroy(void *contents); +static void cv8_lineinfo_bc_print(const void *contents, FILE *f, + int indent_level); +static int cv8_lineinfo_bc_calc_len + (yasm_bytecode *bc, yasm_bc_add_span_func add_span, void *add_span_data); +static int cv8_lineinfo_bc_tobytes + (yasm_bytecode *bc, unsigned char **bufp, unsigned char *bufstart, void *d, + yasm_output_value_func output_value, + /*@null@*/ yasm_output_reloc_func output_reloc); + +static void cv_sym_bc_destroy(void *contents); +static void cv_sym_bc_print(const void *contents, FILE *f, int indent_level); +static int cv_sym_bc_calc_len + (yasm_bytecode *bc, yasm_bc_add_span_func add_span, void *add_span_data); +static int cv_sym_bc_tobytes + (yasm_bytecode *bc, unsigned char **bufp, unsigned char *bufstart, void *d, + yasm_output_value_func output_value, + /*@null@*/ yasm_output_reloc_func output_reloc); + +/* Bytecode callback structures */ +static const yasm_bytecode_callback cv8_symhead_bc_callback = { + cv8_symhead_bc_destroy, + cv8_symhead_bc_print, + yasm_bc_finalize_common, + NULL, + cv8_symhead_bc_calc_len, + yasm_bc_expand_common, + cv8_symhead_bc_tobytes, + 0 +}; + +static const yasm_bytecode_callback cv8_fileinfo_bc_callback = { + cv8_fileinfo_bc_destroy, + cv8_fileinfo_bc_print, + yasm_bc_finalize_common, + NULL, + cv8_fileinfo_bc_calc_len, + yasm_bc_expand_common, + cv8_fileinfo_bc_tobytes, + 0 +}; + +static const yasm_bytecode_callback cv8_lineinfo_bc_callback = { + cv8_lineinfo_bc_destroy, + cv8_lineinfo_bc_print, + yasm_bc_finalize_common, + NULL, + cv8_lineinfo_bc_calc_len, + yasm_bc_expand_common, + cv8_lineinfo_bc_tobytes, + 0 +}; + +static const yasm_bytecode_callback cv_sym_bc_callback = { + cv_sym_bc_destroy, + cv_sym_bc_print, + yasm_bc_finalize_common, + NULL, + cv_sym_bc_calc_len, + yasm_bc_expand_common, + cv_sym_bc_tobytes, + 0 +}; + +static cv8_symhead *cv8_add_symhead(yasm_section *sect, unsigned long type, + int first); +static void cv8_set_symhead_end(cv8_symhead *head, yasm_bytecode *end_prevbc); + +static yasm_bytecode *cv8_add_fileinfo + (yasm_section *sect, const cv_filename *fn); + +static unsigned long cv_sym_size(const cv_sym *cvs); + + +static cv_sym * +cv8_add_sym_objname(yasm_section *sect, /*@keep@*/ char *objname) +{ + yasm_bytecode *bc; + cv_sym *cvs = yasm_xmalloc(sizeof(cv_sym)); + cvs->type = CV8_S_OBJNAME; + cvs->format = "wZ"; + cvs->args[0].i = 0; /* signature (0=asm) */ + cvs->args[1].p = objname; /* object filename */ + + bc = yasm_bc_create_common(&cv_sym_bc_callback, cvs, 0); + bc->len = cv_sym_size(cvs); + yasm_cv__append_bc(sect, bc); + return cvs; +} + +static cv_sym * +cv8_add_sym_compile(yasm_object *object, yasm_section *sect, + /*@keep@*/ char *creator) +{ + yasm_bytecode *bc; + cv_sym *cvs = yasm_xmalloc(sizeof(cv_sym)); + cvs->type = CV8_S_COMPILE; + cvs->format = "wwwwZh"; + cvs->args[0].i = 3; /* language (3=Masm) */ + + /* target processor; 0xD0 = AMD64 */ + if (strcmp(yasm_arch_keyword(object->arch), "x86") == 0) { + if (strcmp(yasm_arch_get_machine(object->arch), "amd64") == 0) + cvs->args[1].i = 0xD0; + else + cvs->args[1].i = 0x6; /* 686, FIXME */ + } else + cvs->args[1].i = 0; /* XXX: unknown */ + + cvs->args[2].i = 0; /* flags (assume 0 for now) */ + cvs->args[3].i = 0; /* creator version number (assume 0 for now) */ + cvs->args[4].p = creator; /* creator string */ + cvs->args[5].i = 0; /* no pairs of key/value */ + + bc = yasm_bc_create_common(&cv_sym_bc_callback, cvs, 0); + bc->len = cv_sym_size(cvs); + yasm_cv__append_bc(sect, bc); + return cvs; +} + +static cv_sym * +cv8_add_sym_label(yasm_section *sect, yasm_symrec *sym) +{ + yasm_bytecode *bc; + cv_sym *cvs = yasm_xmalloc(sizeof(cv_sym)); + cvs->type = CV8_S_LABEL32; + cvs->format = "YbZ"; + cvs->args[0].p = sym; /* symrec for label */ + cvs->args[1].i = 0; /* flags (assume 0 for now) */ + cvs->args[2].p = yasm__xstrdup(yasm_symrec_get_name(sym)); + + bc = yasm_bc_create_common(&cv_sym_bc_callback, cvs, 0); + bc->len = cv_sym_size(cvs); + yasm_cv__append_bc(sect, bc); + return cvs; +} + +static cv_sym * +cv8_add_sym_data(yasm_section *sect, unsigned long type, yasm_symrec *sym, + int is_global) +{ + yasm_bytecode *bc; + cv_sym *cvs = yasm_xmalloc(sizeof(cv_sym)); + cvs->type = is_global ? CV8_S_GDATA32 : CV8_S_LDATA32; + cvs->format = "wYZ"; + cvs->args[0].i = type; /* type index */ + cvs->args[1].p = sym; /* symrec for label */ + cvs->args[2].p = yasm__xstrdup(yasm_symrec_get_name(sym)); + + bc = yasm_bc_create_common(&cv_sym_bc_callback, cvs, 0); + bc->len = cv_sym_size(cvs); + yasm_cv__append_bc(sect, bc); + return cvs; +} + +static size_t +cv_dbgfmt_add_file(yasm_dbgfmt_cv *dbgfmt_cv, size_t filenum, + const char *filename) +{ + char *pathname; + size_t i; + yasm_md5_context context; + FILE *f; + unsigned char *buf; + size_t len; + + /* Put the filename into the filename table */ + if (filenum == 0) { + /* Look to see if we already have that filename in the table */ + for (; filenum<dbgfmt_cv->filenames_size; filenum++) { + if (!dbgfmt_cv->filenames[filenum].filename || + strcmp(dbgfmt_cv->filenames[filenum].filename, filename) == 0) + break; + } + } else + filenum--; /* array index is 0-based */ + + /* Realloc table if necessary */ + if (filenum >= dbgfmt_cv->filenames_allocated) { + size_t old_allocated = dbgfmt_cv->filenames_allocated; + dbgfmt_cv->filenames_allocated = filenum+32; + dbgfmt_cv->filenames = yasm_xrealloc(dbgfmt_cv->filenames, + sizeof(cv_filename)*dbgfmt_cv->filenames_allocated); + for (i=old_allocated; i<dbgfmt_cv->filenames_allocated; i++) { + dbgfmt_cv->filenames[i].pathname = NULL; + dbgfmt_cv->filenames[i].filename = NULL; + dbgfmt_cv->filenames[i].str_off = 0; + dbgfmt_cv->filenames[i].info_off = 0; + } + } + + /* Calculate MD5 checksum of file */ + buf = yasm_xmalloc(1024); + yasm_md5_init(&context); + f = fopen(filename, "rb"); + if (!f) + yasm__fatal(N_("codeview: could not open source file")); + while ((len = fread(buf, 1, 1024, f)) > 0) + yasm_md5_update(&context, buf, (unsigned long)len); + yasm_md5_final(dbgfmt_cv->filenames[filenum].digest, &context); + fclose(f); + yasm_xfree(buf); + + /* Actually save in table */ + if (dbgfmt_cv->filenames[filenum].pathname) + yasm_xfree(dbgfmt_cv->filenames[filenum].pathname); + if (dbgfmt_cv->filenames[filenum].filename) + yasm_xfree(dbgfmt_cv->filenames[filenum].filename); + + pathname = yasm__abspath(filename); + dbgfmt_cv->filenames[filenum].pathname = pathname; + dbgfmt_cv->filenames[filenum].filename = yasm__xstrdup(filename); + + /* Update table size */ + if (filenum >= dbgfmt_cv->filenames_size) + dbgfmt_cv->filenames_size = filenum + 1; + + return filenum; +} + +static yasm_bytecode * +cv_append_str(yasm_section *sect, const char *str) +{ + yasm_datavalhead dvs; + yasm_bytecode *bc; + + yasm_dvs_initialize(&dvs); + yasm_dvs_append(&dvs, yasm_dv_create_string(yasm__xstrdup(str), + strlen(str))); + bc = yasm_bc_create_data(&dvs, 1, 1, NULL, 0); + yasm_bc_finalize(bc, yasm_cv__append_bc(sect, bc)); + yasm_bc_calc_len(bc, NULL, NULL); + return bc; +} + +typedef struct cv_line_info { + yasm_section *debug_symline; + yasm_object *object; + yasm_dbgfmt_cv *dbgfmt_cv; + yasm_linemap *linemap; + yasm_errwarns *errwarns; + unsigned int num_lineinfos; + STAILQ_HEAD(cv8_lineinfo_head, cv8_lineinfo) cv8_lineinfos; + /*@null@*/ cv8_lineinfo *cv8_cur_li; + /*@null@*/ cv8_lineset *cv8_cur_ls; +} cv_line_info; + +static int +cv_generate_line_bc(yasm_bytecode *bc, /*@null@*/ void *d) +{ + cv_line_info *info = (cv_line_info *)d; + yasm_dbgfmt_cv *dbgfmt_cv = info->dbgfmt_cv; + size_t i; + const char *filename; + unsigned long line; + /*@null@*/ yasm_bytecode *nextbc = yasm_bc__next(bc); + yasm_section *sect = yasm_bc_get_section(bc); + + if (nextbc && bc->offset == nextbc->offset) + return 0; + + yasm_linemap_lookup(info->linemap, bc->line, &filename, &line); + + if (!info->cv8_cur_li + || strcmp(filename, info->cv8_cur_li->fn->filename) != 0) { + yasm_bytecode *sectbc; + char symname[8]; + int first_in_sect = !info->cv8_cur_li; + + /* Find file */ + for (i=0; i<dbgfmt_cv->filenames_size; i++) { + if (strcmp(filename, dbgfmt_cv->filenames[i].filename) == 0) + break; + } + if (i >= dbgfmt_cv->filenames_size) + yasm_internal_error(N_("could not find filename in table")); + + /* and create new lineinfo structure */ + info->cv8_cur_li = yasm_xmalloc(sizeof(cv8_lineinfo)); + info->cv8_cur_li->fn = &dbgfmt_cv->filenames[i]; + info->cv8_cur_li->sect = sect; + info->cv8_cur_li->first_in_sect = first_in_sect; + sectbc = yasm_section_bcs_first(sect); + if (sectbc->symrecs && sectbc->symrecs[0]) + info->cv8_cur_li->sectsym = sectbc->symrecs[0]; + else { + sprintf(symname, ".%06u", info->num_lineinfos++); + info->cv8_cur_li->sectsym = + yasm_symtab_define_label(info->object->symtab, symname, sectbc, + 1, 0); + } + info->cv8_cur_li->num_linenums = 0; + STAILQ_INIT(&info->cv8_cur_li->linesets); + STAILQ_INSERT_TAIL(&info->cv8_lineinfos, info->cv8_cur_li, link); + info->cv8_cur_ls = NULL; + } + + /* build new lineset if necessary */ + if (!info->cv8_cur_ls || info->cv8_cur_ls->num_pairs >= 126) { + info->cv8_cur_ls = yasm_xmalloc(sizeof(cv8_lineset)); + info->cv8_cur_ls->num_pairs = 0; + STAILQ_INSERT_TAIL(&info->cv8_cur_li->linesets, info->cv8_cur_ls, link); + } + + /* add linepair for this bytecode */ + info->cv8_cur_ls->pairs[info->cv8_cur_ls->num_pairs].offset = bc->offset; + info->cv8_cur_ls->pairs[info->cv8_cur_ls->num_pairs].line = + 0x80000000 | line; + info->cv8_cur_ls->num_pairs++; + info->cv8_cur_li->num_linenums++; + + return 0; +} + +static int +cv_generate_line_section(yasm_section *sect, /*@null@*/ void *d) +{ + cv_line_info *info = (cv_line_info *)d; + + if (!yasm_section_is_code(sect)) + return 0; /* not code, so no line data for this section */ + + info->cv8_cur_li = NULL; + info->cv8_cur_ls = NULL; + + yasm_section_bcs_traverse(sect, info->errwarns, info, cv_generate_line_bc); + + return 0; +} + +static int +cv_generate_filename(const char *filename, void *d) +{ + cv_dbgfmt_add_file((yasm_dbgfmt_cv *)d, 0, filename); + return 0; +} + +static int +cv_generate_sym(yasm_symrec *sym, void *d) +{ + cv_line_info *info = (cv_line_info *)d; + yasm_bytecode *precbc; + const char *name = yasm_symrec_get_name(sym); + + /* only care about labels (for now). Don't put in symbols starting with + * ".", as these are typically internally generated ones (like section + * symbols). + */ + if (name[0] == '.' || !yasm_symrec_get_label(sym, &precbc)) + return 0; + + /* TODO: add data types; until then, just mark everything as UBYTE */ + if (yasm_section_is_code(yasm_bc_get_section(precbc))) + cv8_add_sym_label(info->debug_symline, sym); + else + cv8_add_sym_data(info->debug_symline, 0x20, sym, + yasm_symrec_get_visibility(sym) & YASM_SYM_GLOBAL?1:0); + return 0; +} + +yasm_section * +yasm_cv__generate_symline(yasm_object *object, yasm_linemap *linemap, + yasm_errwarns *errwarns) +{ + yasm_dbgfmt_cv *dbgfmt_cv = (yasm_dbgfmt_cv *)object->dbgfmt; + cv_line_info info; + int new; + size_t i; + cv8_symhead *head; + cv8_lineinfo *li; + yasm_bytecode *bc; + unsigned long off; + + /* Generate filenames based on linemap */ + yasm_linemap_traverse_filenames(linemap, dbgfmt_cv, + cv_generate_filename); + + info.object = object; + info.dbgfmt_cv = dbgfmt_cv; + info.linemap = linemap; + info.errwarns = errwarns; + info.debug_symline = + yasm_object_get_general(object, ".debug$S", 1, 0, 0, &new, 0); + info.num_lineinfos = 0; + STAILQ_INIT(&info.cv8_lineinfos); + info.cv8_cur_li = NULL; + info.cv8_cur_ls = NULL; + + /* source filenames string table */ + head = cv8_add_symhead(info.debug_symline, CV8_FILE_STRTAB, 1); + cv_append_str(info.debug_symline, ""); + off = 1; + for (i=0; i<dbgfmt_cv->filenames_size; i++) { + if (!dbgfmt_cv->filenames[i].pathname) { + yasm_error_set(YASM_ERROR_GENERAL, + N_("codeview file number %d unassigned"), i+1); + yasm_errwarn_propagate(errwarns, 0); + continue; + } + bc = cv_append_str(info.debug_symline, + dbgfmt_cv->filenames[i].pathname); + dbgfmt_cv->filenames[i].str_off = off; + off += bc->len; + } + cv8_set_symhead_end(head, yasm_section_bcs_last(info.debug_symline)); + + /* Align 4 */ + bc = yasm_bc_create_align + (yasm_expr_create_ident(yasm_expr_int(yasm_intnum_create_uint(4)), 0), + NULL, NULL, NULL, 0); + yasm_bc_finalize(bc, yasm_cv__append_bc(info.debug_symline, bc)); + yasm_bc_calc_len(bc, NULL, NULL); + + /* source file info table */ + head = cv8_add_symhead(info.debug_symline, CV8_FILE_INFO, 0); + off = 0; + for (i=0; i<dbgfmt_cv->filenames_size; i++) { + if (!dbgfmt_cv->filenames[i].pathname) + continue; + bc = cv8_add_fileinfo(info.debug_symline, &dbgfmt_cv->filenames[i]); + dbgfmt_cv->filenames[i].info_off = off; + off += bc->len; + } + cv8_set_symhead_end(head, yasm_section_bcs_last(info.debug_symline)); + + /* Already aligned 4 */ + + /* Generate line numbers for sections */ + yasm_object_sections_traverse(object, (void *)&info, + cv_generate_line_section); + + /* Output line numbers for sections */ + head = NULL; + STAILQ_FOREACH(li, &info.cv8_lineinfos, link) { + if (li->first_in_sect) { + if (head) + cv8_set_symhead_end(head, yasm_section_bcs_last(info.debug_symline)); + head = cv8_add_symhead(info.debug_symline, CV8_LINE_NUMS, 0); + } + bc = yasm_bc_create_common(&cv8_lineinfo_bc_callback, li, 0); + bc->len = (li->first_in_sect ? 24 : 12) + li->num_linenums*8; + yasm_cv__append_bc(info.debug_symline, bc); + } + if (head) + cv8_set_symhead_end(head, yasm_section_bcs_last(info.debug_symline)); + + /* Already aligned 4 */ + + /* Output debugging symbols */ + head = cv8_add_symhead(info.debug_symline, CV8_DEBUG_SYMS, 0); + /* add object and compile flag first */ + cv8_add_sym_objname(info.debug_symline, + yasm__abspath(object->obj_filename)); + if (getenv("YASM_TEST_SUITE")) + cv8_add_sym_compile(object, info.debug_symline, + yasm__xstrdup("yasm HEAD")); + else + cv8_add_sym_compile(object, info.debug_symline, + yasm__xstrdup(PACKAGE_STRING)); + /* then iterate through symbol table */ + yasm_symtab_traverse(object->symtab, &info, cv_generate_sym); + cv8_set_symhead_end(head, yasm_section_bcs_last(info.debug_symline)); + + /* Align 4 at end */ + bc = yasm_bc_create_align + (yasm_expr_create_ident(yasm_expr_int(yasm_intnum_create_uint(4)), 0), + NULL, NULL, NULL, 0); + yasm_bc_finalize(bc, yasm_cv__append_bc(info.debug_symline, bc)); + yasm_bc_calc_len(bc, NULL, NULL); + + return info.debug_symline; +} + +static void +cv_out_sym(yasm_symrec *sym, unsigned long off, yasm_bytecode *bc, + unsigned char **bufp, void *d, yasm_output_value_func output_value) +{ + yasm_value val; + + /* sym in its section */ + yasm_value_init_sym(&val, sym, 32); + val.section_rel = 1; + output_value(&val, *bufp, 4, off, bc, 0, d); + *bufp += 4; + + /* section index */ + yasm_value_init_sym(&val, sym, 16); + val.seg_of = 1; + output_value(&val, *bufp, 2, off+4, bc, 0, d); + *bufp += 2; +} + +static cv8_symhead * +cv8_add_symhead(yasm_section *sect, unsigned long type, int first) +{ + cv8_symhead *head; + yasm_bytecode *bc; + + head = yasm_xmalloc(sizeof(cv8_symhead)); + head->type = type; + head->first = first; + head->start_prevbc = yasm_section_bcs_last(sect); + + bc = yasm_bc_create_common(&cv8_symhead_bc_callback, head, 0); + if (first) + bc->len = 12; + else + bc->len = 8; + + head->end_prevbc = bc; + yasm_cv__append_bc(sect, bc); + return head; +} + +static void +cv8_set_symhead_end(cv8_symhead *head, yasm_bytecode *end_prevbc) +{ + head->end_prevbc = end_prevbc; +} + +static void +cv8_symhead_bc_destroy(void *contents) +{ + yasm_xfree(contents); +} + +static void +cv8_symhead_bc_print(const void *contents, FILE *f, int indent_level) +{ + /* TODO */ +} + +static int +cv8_symhead_bc_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span, + void *add_span_data) +{ + yasm_internal_error(N_("tried to calc_len a codeview symhead bytecode")); + /*@notreached@*/ + return 0; +} + +static int +cv8_symhead_bc_tobytes(yasm_bytecode *bc, unsigned char **bufp, + unsigned char *bufstart, void *d, + yasm_output_value_func output_value, + yasm_output_reloc_func output_reloc) +{ + yasm_object *object = yasm_section_get_object(bc->section); + cv8_symhead *head = (cv8_symhead *)bc->contents; + unsigned char *buf = *bufp; + yasm_intnum *intn, *cval; + + cval = yasm_intnum_create_uint(4); + /* Output "version" if first */ + if (head->first) { + yasm_arch_intnum_tobytes(object->arch, cval, buf, 4, 32, 0, bc, 0); + buf += 4; + } + + /* Type contained - 4 bytes */ + yasm_intnum_set_uint(cval, head->type); + yasm_arch_intnum_tobytes(object->arch, cval, buf, 4, 32, 0, bc, 0); + buf += 4; + + /* Total length of info (following this field) - 4 bytes */ + yasm_intnum_set_uint(cval, bc->len); + intn = yasm_calc_bc_dist(head->start_prevbc, head->end_prevbc); + yasm_intnum_calc(intn, YASM_EXPR_SUB, cval); + yasm_arch_intnum_tobytes(object->arch, intn, buf, 4, 32, 0, bc, 0); + buf += 4; + yasm_intnum_destroy(intn); + + *bufp = buf; + + yasm_intnum_destroy(cval); + return 0; +} + +static yasm_bytecode * +cv8_add_fileinfo(yasm_section *sect, const cv_filename *fn) +{ + cv8_fileinfo *fi; + yasm_bytecode *bc; + + fi = yasm_xmalloc(sizeof(cv8_fileinfo)); + fi->fn = fn; + + bc = yasm_bc_create_common(&cv8_fileinfo_bc_callback, fi, 0); + bc->len = 24; + + yasm_cv__append_bc(sect, bc); + return bc; +} + +static void +cv8_fileinfo_bc_destroy(void *contents) +{ + yasm_xfree(contents); +} + +static void +cv8_fileinfo_bc_print(const void *contents, FILE *f, int indent_level) +{ + /* TODO */ +} + +static int +cv8_fileinfo_bc_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span, + void *add_span_data) +{ + yasm_internal_error(N_("tried to calc_len a codeview fileinfo bytecode")); + /*@notreached@*/ + return 0; +} + +static int +cv8_fileinfo_bc_tobytes(yasm_bytecode *bc, unsigned char **bufp, + unsigned char *bufstart, void *d, + yasm_output_value_func output_value, + yasm_output_reloc_func output_reloc) +{ + yasm_object *object = yasm_section_get_object(bc->section); + cv8_fileinfo *fi = (cv8_fileinfo *)bc->contents; + unsigned char *buf = *bufp; + yasm_intnum *cval; + int i; + + /* Offset in filename string table */ + cval = yasm_intnum_create_uint(fi->fn->str_off); + yasm_arch_intnum_tobytes(object->arch, cval, buf, 4, 32, 0, bc, 0); + buf += 4; + + /* Checksum type/length */ + yasm_intnum_set_uint(cval, 0x0110); + yasm_arch_intnum_tobytes(object->arch, cval, buf, 2, 16, 0, bc, 0); + buf += 2; + + /* Checksum */ + for (i=0; i<16; i++) + YASM_WRITE_8(buf, fi->fn->digest[i]); + + /* Pad */ + YASM_WRITE_8(buf, 0); + YASM_WRITE_8(buf, 0); + + *bufp = buf; + + yasm_intnum_destroy(cval); + return 0; +} + +static void +cv8_lineinfo_bc_destroy(void *contents) +{ + cv8_lineinfo *li = (cv8_lineinfo *)contents; + cv8_lineset *ls1, *ls2; + + /* delete line sets */ + ls1 = STAILQ_FIRST(&li->linesets); + while (ls1) { + ls2 = STAILQ_NEXT(ls1, link); + yasm_xfree(ls1); + ls1 = ls2; + } + + yasm_xfree(contents); +} + +static void +cv8_lineinfo_bc_print(const void *contents, FILE *f, int indent_level) +{ + /* TODO */ +} + +static int +cv8_lineinfo_bc_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span, + void *add_span_data) +{ + yasm_internal_error(N_("tried to calc_len a codeview linehead bytecode")); + /*@notreached@*/ + return 0; +} + +static int +cv8_lineinfo_bc_tobytes(yasm_bytecode *bc, unsigned char **bufp, + unsigned char *bufstart, void *d, + yasm_output_value_func output_value, + yasm_output_reloc_func output_reloc) +{ + yasm_object *object = yasm_section_get_object(bc->section); + cv8_lineinfo *li = (cv8_lineinfo *)bc->contents; + unsigned char *buf = *bufp; + yasm_intnum *cval; + unsigned long i; + cv8_lineset *ls; + + if (li->first_in_sect) { + /* start offset and section */ + cv_out_sym(li->sectsym, (unsigned long)(buf - bufstart), bc, &buf, + d, output_value); + + /* Two bytes of pad/alignment */ + YASM_WRITE_8(buf, 0); + YASM_WRITE_8(buf, 0); + + /* Section length covered by line number info */ + cval = yasm_calc_bc_dist(yasm_section_bcs_first(li->sect), + yasm_section_bcs_last(li->sect)); + yasm_arch_intnum_tobytes(object->arch, cval, buf, 4, 32, 0, bc, 0); + yasm_intnum_destroy(cval); + buf += 4; + } + + /* Offset of source file in info table */ + cval = yasm_intnum_create_uint(li->fn->info_off); + yasm_arch_intnum_tobytes(object->arch, cval, buf, 4, 32, 0, bc, 0); + buf += 4; + + /* Number of line number pairs */ + yasm_intnum_set_uint(cval, li->num_linenums); + yasm_arch_intnum_tobytes(object->arch, cval, buf, 4, 32, 0, bc, 0); + buf += 4; + + /* Number of bytes of line number pairs + 12 (no, I don't know why) */ + yasm_intnum_set_uint(cval, li->num_linenums*8+12); + yasm_arch_intnum_tobytes(object->arch, cval, buf, 4, 32, 0, bc, 0); + buf += 4; + + /* Offset / line number pairs */ + i = 0; + STAILQ_FOREACH(ls, &li->linesets, link) { + unsigned long j; + for (j=0; i<li->num_linenums && j<126; i++, j++) { + /* offset in section */ + yasm_intnum_set_uint(cval, ls->pairs[j].offset); + yasm_arch_intnum_tobytes(object->arch, cval, buf, 4, 32, 0, bc, 0); + buf += 4; + + /* line number in file */ + yasm_intnum_set_uint(cval, ls->pairs[j].line); + yasm_arch_intnum_tobytes(object->arch, cval, buf, 4, 32, 0, bc, 0); + buf += 4; + } + } + + *bufp = buf; + + yasm_intnum_destroy(cval); + return 0; +} + +static unsigned long +cv_sym_size(const cv_sym *cvs) +{ + const char *ch = cvs->format; + unsigned long len = 4; /* sym length and type */ + unsigned long slen; + int arg = 0; + + while (*ch) { + switch (*ch) { + case 'b': + len++; + arg++; + break; + case 'h': + len += 2; + arg++; + break; + case 'w': + len += 4; + arg++; + break; + case 'Y': + len += 6; /* XXX: will be 4 in 16-bit version */ + arg++; + break; + case 'T': + len += 4; /* XXX: will be 2 in CV4 */ + arg++; + break; + case 'S': + len += 1; /* XXX: is this 1 or 2? */ + slen = (unsigned long)strlen((const char *)cvs->args[arg++].p); + len += slen <= 0xff ? slen : 0xff; + break; + case 'Z': + len += + (unsigned long)strlen((const char *)cvs->args[arg++].p) + 1; + break; + default: + yasm_internal_error(N_("unknown sym format character")); + } + ch++; + } + + return len; +} + +static void +cv_sym_bc_destroy(void *contents) +{ + cv_sym *cvs = (cv_sym *)contents; + const char *ch = cvs->format; + int arg = 0; + + while (*ch) { + switch (*ch) { + case 'b': + case 'h': + case 'w': + case 'Y': + case 'T': + arg++; + break; /* nothing to destroy */ + case 'S': + case 'Z': + yasm_xfree(cvs->args[arg++].p); + break; + default: + yasm_internal_error(N_("unknown sym format character")); + } + ch++; + } + + yasm_xfree(contents); +} + +static void +cv_sym_bc_print(const void *contents, FILE *f, int indent_level) +{ + /* TODO */ +} + +static int +cv_sym_bc_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span, + void *add_span_data) +{ + yasm_internal_error(N_("tried to calc_len a codeview sym bytecode")); + /*@notreached@*/ + return 0; +} + +static int +cv_sym_bc_tobytes(yasm_bytecode *bc, unsigned char **bufp, + unsigned char *bufstart, void *d, + yasm_output_value_func output_value, + yasm_output_reloc_func output_reloc) +{ + yasm_object *object = yasm_section_get_object(bc->section); + cv_sym *cvs = (cv_sym *)bc->contents; + unsigned char *buf = *bufp; + yasm_intnum *cval; + const char *ch = cvs->format; + size_t len; + int arg = 0; + + /* Total length of record (following this field) - 2 bytes */ + cval = yasm_intnum_create_uint(bc->len-2); + yasm_arch_intnum_tobytes(object->arch, cval, buf, 2, 16, 0, bc, 1); + buf += 2; + + /* Type contained - 2 bytes */ + yasm_intnum_set_uint(cval, cvs->type); + yasm_arch_intnum_tobytes(object->arch, cval, buf, 2, 16, 0, bc, 0); + buf += 2; + + while (*ch) { + switch (*ch) { + case 'b': + YASM_WRITE_8(buf, cvs->args[arg].i); + arg++; + break; + case 'h': + yasm_intnum_set_uint(cval, cvs->args[arg++].i); + yasm_arch_intnum_tobytes(object->arch, cval, buf, 2, 16, 0, + bc, 0); + buf += 2; + break; + case 'w': + yasm_intnum_set_uint(cval, cvs->args[arg++].i); + yasm_arch_intnum_tobytes(object->arch, cval, buf, 4, 32, 0, + bc, 0); + buf += 4; + break; + case 'Y': + cv_out_sym((yasm_symrec *)cvs->args[arg++].p, + (unsigned long)(buf-bufstart), bc, &buf, d, + output_value); + break; + case 'T': + yasm_intnum_set_uint(cval, cvs->args[arg++].i); + yasm_arch_intnum_tobytes(object->arch, cval, buf, 4, 32, 0, + bc, 0); + buf += 4; /* XXX: will be 2 in CV4 */ + break; + case 'S': + len = strlen((char *)cvs->args[arg].p); + len = len <= 0xff ? len : 0xff; + YASM_WRITE_8(buf, len); + memcpy(buf, (char *)cvs->args[arg].p, len); + buf += len; + arg++; + break; + case 'Z': + len = strlen((char *)cvs->args[arg].p)+1; + memcpy(buf, (char *)cvs->args[arg].p, len); + buf += len; + arg++; + break; + default: + yasm_internal_error(N_("unknown leaf format character")); + } + ch++; + } + + *bufp = buf; + + yasm_intnum_destroy(cval); + return 0; +} diff --git a/contrib/tools/yasm/modules/dbgfmts/codeview/cv-type.c b/contrib/tools/yasm/modules/dbgfmts/codeview/cv-type.c index 2a52f18436..ebccbdeda9 100644 --- a/contrib/tools/yasm/modules/dbgfmts/codeview/cv-type.c +++ b/contrib/tools/yasm/modules/dbgfmts/codeview/cv-type.c @@ -1,778 +1,778 @@ -/* - * CodeView debugging format - type information - * - * Copyright (C) 2006-2007 Peter Johnson - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the author nor the names of other contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ -#include <util.h> - -#include <libyasm.h> - -#include "cv-dbgfmt.h" - -enum cv_reservedtype { - /* Bitfields representation - type */ - CV_TYPE_SPECIAL = 0x00<<4, /* Special */ - CV_TYPE_SIGNED = 0x01<<4, /* Signed integral value */ - CV_TYPE_UNSIGNED = 0x02<<4, /* Unsigned integral value */ - CV_TYPE_BOOLEAN = 0x03<<4, /* Boolean */ - CV_TYPE_REAL = 0x04<<4, /* Real */ - CV_TYPE_COMPLEX = 0x05<<4, /* Complex */ - CV_TYPE_SPECIAL2 = 0x06<<4, /* Special2 */ - CV_TYPE_REALINT = 0x07<<4, /* Really int value */ - - /* "size" of CV_TYPE_SPECIAL */ - CV_SPECIAL_NOTYPE = 0x00<<0, /* No type */ - CV_SPECIAL_ABS = 0x01<<0, /* Absolute symbol */ - CV_SPECIAL_SEG = 0x02<<0, /* Segment */ - CV_SPECIAL_VOID = 0x03<<0, /* Void */ - CV_SPECIAL_CURRENCY = 0x04<<0, /* Basic 8-byte currency value */ - CV_SPECIAL_NEARBSTR = 0x05<<0, /* Near Basic string */ - CV_SPECIAL_FARBSTR = 0x06<<0, /* Far Basic string */ - - /* Size of CV_TYPE_SIGNED, CV_TYPE_UNSIGNED, and CV_TYPE_BOOLEAN */ - CV_INTEGER_1BYTE = 0x00<<0, /* 1 byte */ - CV_INTEGER_2BYTE = 0x01<<0, /* 2 byte */ - CV_INTEGER_4BYTE = 0x02<<0, /* 4 byte */ - CV_INTEGER_8BYTE = 0x03<<0, /* 8 byte */ - - /* Size of CV_TYPE_REAL and CV_TYPE_COMPLEX */ - CV_REAL_32BIT = 0x00<<0, /* 32 bit */ - CV_REAL_64BIT = 0x01<<0, /* 64 bit */ - CV_REAL_80BIT = 0x02<<0, /* 80 bit */ - CV_REAL_128BIT = 0x03<<0, /* 128 bit */ - CV_REAL_48BIT = 0x04<<0, /* 48 bit */ - - /* "size" of CV_TYPE_SPECIAL2 */ - CV_SPECIAL2_BIT = 0x00<<0, /* Bit */ - CV_SPECIAL2_PASCHAR = 0x01<<0, /* Pascal CHAR */ - - /* Size of CV_TYPE_REALINT */ - CV_REALINT_CHAR = 0x00<<0, /* Char */ - CV_REALINT_WCHAR = 0x01<<0, /* Wide character */ - CV_REALINT_S2BYTE = 0x02<<0, /* 2-byte signed integer */ - CV_REALINT_U2BYTE = 0x03<<0, /* 2-byte unsigned integer */ - CV_REALINT_S4BYTE = 0x04<<0, /* 4-byte signed integer */ - CV_REALINT_U4BYTE = 0x05<<0, /* 4-byte unsigned integer */ - CV_REALINT_S8BYTE = 0x06<<0, /* 8-byte signed integer */ - CV_REALINT_U8BYTE = 0x07<<0, /* 8-byte unsigned integer */ - - /* Mode */ - CV_MODE_DIRECT = 0x00<<8, /* Direct; not a pointer */ - CV_MODE_NEAR = 0x01<<8, /* Near pointer */ - CV_MODE_FAR = 0x02<<8, /* Far pointer */ - CV_MODE_HUGE = 0x03<<8, /* Huge pointer */ - CV_MODE_NEAR32 = 0x04<<8, /* 32-bit near pointer */ - CV_MODE_FAR32 = 0x05<<8, /* 32-bit far pointer */ - CV_MODE_NEAR64 = 0x06<<8, /* 64-bit near pointer */ - - /* Pure primitive type listing - based on above bitfields */ - - /* Special Types */ - CV_T_NOTYPE = 0x0000, /* Uncharacterized type (no type) */ - CV_T_ABS = 0x0001, /* Absolute symbol */ - CV_T_SEGMENT = 0x0002, /* Segment type */ - CV_T_VOID = 0x0003, /* Void */ - CV_T_PVOID = 0x0103, /* Near pointer to void */ - CV_T_PFVOID = 0x0203, /* Far pointer to void */ - CV_T_PHVOID = 0x0303, /* Huge pointer to void */ - CV_T_32PVOID = 0x0403, /* 32-bit near pointer to void */ - CV_T_32PFVOID = 0x0503, /* 32-bit far pointer to void */ - CV_T_CURRENCY = 0x0004, /* Basic 8-byte currency value */ - CV_T_NBASICSTR = 0x0005, /* Near Basic string */ - CV_T_FBASICSTR = 0x0006, /* Far Basic string */ - CV_T_BIT = 0x0060, /* Bit */ - CV_T_PASCHAR = 0x0061, /* Pascal CHAR */ - /* Character Types */ - CV_T_CHAR = 0x0010, /* 8-bit signed */ - CV_T_UCHAR = 0x0020, /* 8-bit unsigned */ - CV_T_PCHAR = 0x0110, /* Near pointer to 8-bit signed */ - CV_T_PUCHAR = 0x0120, /* Near pointer to 8-bit unsigned */ - CV_T_PFCHAR = 0x0210, /* Far pointer to 8-bit signed */ - CV_T_PFUCHAR = 0x0220, /* Far pointer to 8-bit unsigned */ - CV_T_PHCHAR = 0x0310, /* Huge pointer to 8-bit signed */ - CV_T_PHUCHAR = 0x0320, /* Huge pointer to 8-bit unsigned */ - CV_T_32PCHAR = 0x0410, /* 16:32 near pointer to 8-bit signed */ - CV_T_32PUCHAR = 0x0420, /* 16:32 near pointer to 8-bit unsigned */ - CV_T_32PFCHAR = 0x0510, /* 16:32 far pointer to 8-bit signed */ - CV_T_32PFUCHAR = 0x0520, /* 16:32 far pointer to 8-bit unsigned */ - /* Real Character Types */ - CV_T_RCHAR = 0x0070, /* Real char */ - CV_T_PRCHAR = 0x0170, /* Near pointer to a real char */ - CV_T_PFRCHAR = 0x0270, /* Far pointer to a real char */ - CV_T_PHRCHAR = 0x0370, /* Huge pointer to a real char */ - CV_T_32PRCHAR = 0x0470, /* 16:32 near pointer to a real char */ - CV_T_32PFRCHAR = 0x0570, /* 16:32 far pointer to a real char */ - /* Wide Character Types */ - CV_T_WCHAR = 0x0071, /* Wide char */ - CV_T_PWCHAR = 0x0171, /* Near pointer to a wide char */ - CV_T_PFWCHAR = 0x0271, /* Far pointer to a wide char */ - CV_T_PHWCHAR = 0x0371, /* Huge pointer to a wide char */ - CV_T_32PWCHAR = 0x0471, /* 16:32 near pointer to a wide char */ - CV_T_32PFWCHAR = 0x0571, /* 16:32 far pointer to a wide char */ - /* Real 16-bit Integer Types */ - CV_T_INT2 = 0x0072, /* Real 16-bit signed int */ - CV_T_UINT2 = 0x0073, /* Real 16-bit unsigned int */ - CV_T_PINT2 = 0x0172, /* Near pointer to 16-bit signed int */ - CV_T_PUINT2 = 0x0173, /* Near pointer to 16-bit unsigned int */ - CV_T_PFINT2 = 0x0272, /* Far pointer to 16-bit signed int */ - CV_T_PFUINT2 = 0x0273, /* Far pointer to 16-bit unsigned int */ - CV_T_PHINT2 = 0x0372, /* Huge pointer to 16-bit signed int */ - CV_T_PHUINT2 = 0x0373, /* Huge pointer to 16-bit unsigned int */ - CV_T_32PINT2 = 0x0472, /* 16:32 near pointer to 16-bit signed int */ - CV_T_32PUINT2 = 0x0473, /* 16:32 near pointer to 16-bit unsigned int */ - CV_T_32PFINT2 = 0x0572, /* 16:32 far pointer to 16-bit signed int */ - CV_T_32PFUINT2 = 0x0573, /* 16:32 far pointer to 16-bit unsigned int */ - /* 16-bit Short Types */ - CV_T_SHORT = 0x0011, /* 16-bit signed */ - CV_T_USHORT = 0x0021, /* 16-bit unsigned */ - CV_T_PSHORT = 0x0111, /* Near pointer to 16-bit signed */ - CV_T_PUSHORT = 0x0121, /* Near pointer to 16-bit unsigned */ - CV_T_PFSHORT = 0x0211, /* Far pointer to 16-bit signed */ - CV_T_PFUSHORT = 0x0221, /* Far pointer to 16-bit unsigned */ - CV_T_PHSHORT = 0x0311, /* Huge pointer to 16-bit signed */ - CV_T_PHUSHORT = 0x0321, /* Huge pointer to 16-bit unsigned */ - CV_T_32PSHORT = 0x0411, /* 16:32 near pointer to 16-bit signed */ - CV_T_32PUSHORT = 0x0421, /* 16:32 near pointer to 16-bit unsigned */ - CV_T_32PFSHORT = 0x0511, /* 16:32 far pointer to 16-bit signed */ - CV_T_32PFUSHORT = 0x0521, /* 16:32 far pointer to 16-bit unsigned */ - /* Real 32-bit Integer Types */ - CV_T_INT4 = 0x0074, /* Real 32-bit signed int */ - CV_T_UINT4 = 0x0075, /* Real 32-bit unsigned int */ - CV_T_PINT4 = 0x0174, /* Near pointer to 32-bit signed int */ - CV_T_PUINT4 = 0x0175, /* Near pointer to 32-bit unsigned int */ - CV_T_PFINT4 = 0x0274, /* Far pointer to 32-bit signed int */ - CV_T_PFUINT4 = 0x0275, /* Far pointer to 32-bit unsigned int */ - CV_T_PHINT4 = 0x0374, /* Huge pointer to 32-bit signed int */ - CV_T_PHUINT4 = 0x0375, /* Huge pointer to 32-bit unsigned int */ - CV_T_32PINT4 = 0x0474, /* 16:32 near pointer to 32-bit signed int */ - CV_T_32PUINT4 = 0x0475, /* 16:32 near pointer to 32-bit unsigned int */ - CV_T_32PFINT4 = 0x0574, /* 16:32 far pointer to 32-bit signed int */ - CV_T_32PFUINT4 = 0x0575, /* 16:32 far pointer to 32-bit unsigned int */ - /* 32-bit Long Types */ - CV_T_LONG = 0x0012, /* 32-bit signed */ - CV_T_ULONG = 0x0022, /* 32-bit unsigned */ - CV_T_PLONG = 0x0112, /* Near pointer to 32-bit signed */ - CV_T_PULONG = 0x0122, /* Near pointer to 32-bit unsigned */ - CV_T_PFLONG = 0x0212, /* Far pointer to 32-bit signed */ - CV_T_PFULONG = 0x0222, /* Far pointer to 32-bit unsigned */ - CV_T_PHLONG = 0x0312, /* Huge pointer to 32-bit signed */ - CV_T_PHULONG = 0x0322, /* Huge pointer to 32-bit unsigned */ - CV_T_32PLONG = 0x0412, /* 16:32 near pointer to 32-bit signed */ - CV_T_32PULONG = 0x0422, /* 16:32 near pointer to 32-bit unsigned */ - CV_T_32PFLONG = 0x0512, /* 16:32 far pointer to 32-bit signed */ - CV_T_32PFULONG = 0x0522, /* 16:32 far pointer to 32-bit unsigned */ - /* Real 64-bit int Types */ - CV_T_INT8 = 0x0076, /* 64-bit signed int */ - CV_T_UINT8 = 0x0077, /* 64-bit unsigned int */ - CV_T_PINT8 = 0x0176, /* Near pointer to 64-bit signed int */ - CV_T_PUINT8 = 0x0177, /* Near pointer to 64-bit unsigned int */ - CV_T_PFINT8 = 0x0276, /* Far pointer to 64-bit signed int */ - CV_T_PFUINT8 = 0x0277, /* Far pointer to 64-bit unsigned int */ - CV_T_PHINT8 = 0x0376, /* Huge pointer to 64-bit signed int */ - CV_T_PHUINT8 = 0x0377, /* Huge pointer to 64-bit unsigned int */ - CV_T_32PINT8 = 0x0476, /* 16:32 near pointer to 64-bit signed int */ - CV_T_32PUINT8 = 0x0477, /* 16:32 near pointer to 64-bit unsigned int */ - CV_T_32PFINT8 = 0x0576, /* 16:32 far pointer to 64-bit signed int */ - CV_T_32PFUINT8 = 0x0577, /* 16:32 far pointer to 64-bit unsigned int */ - /* 64-bit Integral Types */ - CV_T_QUAD = 0x0013, /* 64-bit signed */ - CV_T_UQUAD = 0x0023, /* 64-bit unsigned */ - CV_T_PQUAD = 0x0113, /* Near pointer to 64-bit signed */ - CV_T_PUQUAD = 0x0123, /* Near pointer to 64-bit unsigned */ - CV_T_PFQUAD = 0x0213, /* Far pointer to 64-bit signed */ - CV_T_PFUQUAD = 0x0223, /* Far pointer to 64-bit unsigned */ - CV_T_PHQUAD = 0x0313, /* Huge pointer to 64-bit signed */ - CV_T_PHUQUAD = 0x0323, /* Huge pointer to 64-bit unsigned */ - CV_T_32PQUAD = 0x0413, /* 16:32 near pointer to 64-bit signed */ - CV_T_32PUQUAD = 0x0423, /* 16:32 near pointer to 64-bit unsigned */ - CV_T_32PFQUAD = 0x0513, /* 16:32 far pointer to 64-bit signed */ - CV_T_32PFUQUAD = 0x0523, /* 16:32 far pointer to 64-bit unsigned */ - /* 32-bit Real Types */ - CV_T_REAL32 = 0x0040, /* 32-bit real */ - CV_T_PREAL32 = 0x0140, /* Near pointer to 32-bit real */ - CV_T_PFREAL32 = 0x0240, /* Far pointer to 32-bit real */ - CV_T_PHREAL32 = 0x0340, /* Huge pointer to 32-bit real */ - CV_T_32PREAL32 = 0x0440, /* 16:32 near pointer to 32-bit real */ - CV_T_32PFREAL32 = 0x0540, /* 16:32 far pointer to 32-bit real */ - /* 48-bit Real Types */ - CV_T_REAL48 = 0x0044, /* 48-bit real */ - CV_T_PREAL48 = 0x0144, /* Near pointer to 48-bit real */ - CV_T_PFREAL48 = 0x0244, /* Far pointer to 48-bit real */ - CV_T_PHREAL48 = 0x0344, /* Huge pointer to 48-bit real */ - CV_T_32PREAL48 = 0x0444, /* 16:32 near pointer to 48-bit real */ - CV_T_32PFREAL48 = 0x0544, /* 16:32 far pointer to 48-bit real */ - /* 64-bit Real Types */ - CV_T_REAL64 = 0x0041, /* 64-bit real */ - CV_T_PREAL64 = 0x0141, /* Near pointer to 64-bit real */ - CV_T_PFREAL64 = 0x0241, /* Far pointer to 64-bit real */ - CV_T_PHREAL64 = 0x0341, /* Huge pointer to 64-bit real */ - CV_T_32PREAL64 = 0x0441, /* 16:32 near pointer to 64-bit real */ - CV_T_32PFREAL64 = 0x0541, /* 16:32 far pointer to 64-bit real */ - /* 80-bit Real Types */ - CV_T_REAL80 = 0x0042, /* 80-bit real */ - CV_T_PREAL80 = 0x0142, /* Near pointer to 80-bit real */ - CV_T_PFREAL80 = 0x0242, /* Far pointer to 80-bit real */ - CV_T_PHREAL80 = 0x0342, /* Huge pointer to 80-bit real */ - CV_T_32PREAL80 = 0x0442, /* 16:32 near pointer to 80-bit real */ - CV_T_32PFREAL80 = 0x0542, /* 16:32 far pointer to 80-bit real */ - /* 128-bit Real Types */ - CV_T_REAL128 = 0x0043, /* 128-bit real */ - CV_T_PREAL128 = 0x0143, /* Near pointer to 128-bit real */ - CV_T_PFREAL128 = 0x0243, /* Far pointer to 128-bit real */ - CV_T_PHREAL128 = 0x0343, /* Huge pointer to 128-bit real */ - CV_T_32PREAL128 = 0x0443, /* 16:32 near pointer to 128-bit real */ - CV_T_32PFREAL128 = 0x0543, /* 16:32 far pointer to 128-bit real */ - /* 32-bit Complex Types */ - CV_T_CPLX32 = 0x0050, /* 32-bit complex */ - CV_T_PCPLX32 = 0x0150, /* Near pointer to 32-bit complex */ - CV_T_PFCPLX32 = 0x0250, /* Far pointer to 32-bit complex */ - CV_T_PHCPLX32 = 0x0350, /* Huge pointer to 32-bit complex */ - CV_T_32PCPLX32 = 0x0450, /* 16:32 near pointer to 32-bit complex */ - CV_T_32PFCPLX32 = 0x0550, /* 16:32 far pointer to 32-bit complex */ - /* 64-bit Complex Types */ - CV_T_CPLX64 = 0x0051, /* 64-bit complex */ - CV_T_PCPLX64 = 0x0151, /* Near pointer to 64-bit complex */ - CV_T_PFCPLX64 = 0x0251, /* Far pointer to 64-bit complex */ - CV_T_PHCPLX64 = 0x0351, /* Huge pointer to 64-bit complex */ - CV_T_32PCPLX64 = 0x0451, /* 16:32 near pointer to 64-bit complex */ - CV_T_32PFCPLX64 = 0x0551, /* 16:32 far pointer to 64-bit complex */ - /* 80-bit Complex Types */ - CV_T_CPLX80 = 0x0052, /* 80-bit complex */ - CV_T_PCPLX80 = 0x0152, /* Near pointer to 80-bit complex */ - CV_T_PFCPLX80 = 0x0252, /* Far pointer to 80-bit complex */ - CV_T_PHCPLX80 = 0x0352, /* Huge pointer to 80-bit complex */ - CV_T_32PCPLX80 = 0x0452, /* 16:32 near pointer to 80-bit complex */ - CV_T_32PFCPLX80 = 0x0552, /* 16:32 far pointer to 80-bit complex */ - /* 128-bit Complex Types */ - CV_T_CPLX128 = 0x0053, /* 128-bit complex */ - CV_T_PCPLX128 = 0x0153, /* Near pointer to 128-bit complex */ - CV_T_PFCPLX128 = 0x0253, /* Far pointer to 128-bit complex */ - CV_T_PHCPLX128 = 0x0353, /* Huge pointer to 128-bit real */ - CV_T_32PCPLX128 = 0x0453, /* 16:32 near pointer to 128-bit complex */ - CV_T_32PFCPLX128 = 0x0553, /* 16:32 far pointer to 128-bit complex */ - /* Boolean Types */ - CV_T_BOOL08 = 0x0030, /* 8-bit Boolean */ - CV_T_BOOL16 = 0x0031, /* 16-bit Boolean */ - CV_T_BOOL32 = 0x0032, /* 32-bit Boolean */ - CV_T_BOOL64 = 0x0033, /* 64-bit Boolean */ - CV_T_PBOOL08 = 0x0130, /* Near pointer to 8-bit Boolean */ - CV_T_PBOOL16 = 0x0131, /* Near pointer to 16-bit Boolean */ - CV_T_PBOOL32 = 0x0132, /* Near pointer to 32-bit Boolean */ - CV_T_PBOOL64 = 0x0133, /* Near pointer to 64-bit Boolean */ - CV_T_PFBOOL08 = 0x0230, /* Far pointer to 8-bit Boolean */ - CV_T_PFBOOL16 = 0x0231, /* Far pointer to 16-bit Boolean */ - CV_T_PFBOOL32 = 0x0232, /* Far pointer to 32-bit Boolean */ - CV_T_PFBOOL64 = 0x0233, /* Far pointer to 64-bit Boolean */ - CV_T_PHBOOL08 = 0x0330, /* Huge pointer to 8-bit Boolean */ - CV_T_PHBOOL16 = 0x0331, /* Huge pointer to 16-bit Boolean */ - CV_T_PHBOOL32 = 0x0332, /* Huge pointer to 32-bit Boolean */ - CV_T_PHBOOL64 = 0x0333, /* Huge pointer to 64-bit Boolean */ - CV_T_32PBOOL08 = 0x0430, /* 16:32 near pointer to 8-bit Boolean */ - CV_T_32PBOOL16 = 0x0431, /* 16:32 near pointer to 16-bit Boolean */ - CV_T_32PBOOL32 = 0x0432, /* 16:32 near pointer to 32-bit Boolean */ - CV_T_32PBOOL64 = 0x0433, /* 16:32 near pointer to 64-bit Boolean */ - CV_T_32PFBOOL08 = 0x0530, /* 16:32 far pointer to 8-bit Boolean */ - CV_T_32PFBOOL16 = 0x0531, /* 16:32 far pointer to 16-bit Boolean */ - CV_T_32PFBOOL32 = 0x0532, /* 16:32 far pointer to 32-bit Boolean */ - CV_T_32PFBOOL64 = 0x0533, /* 16:32 far pointer to 64-bit Boolean */ - - /* Non-primitive types are stored in the TYPES section (generated in - * cv-type.c) and start at this index (e.g. 0x1000 is the first type - * in TYPES, 0x1001 the second, etc. - */ - CV_FIRST_NONPRIM = 0x1000 -}; - -enum cv_leaftype { - /* Leaf indices for type records that can be referenced from symbols */ - CV4_LF_MODIFIER = 0x0001, /* Type Modifier */ - CV4_LF_POINTER = 0x0002, /* Pointer */ - CV4_LF_ARRAY = 0x0003, /* Simple Array */ - CV4_LF_CLASS = 0x0004, /* Classes */ - CV4_LF_STRUCTURE = 0x0005, /* Structures */ - CV4_LF_UNION = 0x0006, /* Unions */ - CV4_LF_ENUM = 0x0007, /* Enumeration */ - CV4_LF_PROCEDURE = 0x0008, /* Procedure */ - CV4_LF_MFUNCTION = 0x0009, /* Member Function */ - CV4_LF_VTSHAPE = 0x000a, /* Virtual Function Table Shape */ - CV4_LF_BARRAY = 0x000d, /* Basic Array */ - CV4_LF_LABEL = 0x000e, /* Label */ - CV4_LF_NULL = 0x000f, /* Null */ - CV4_LF_DIMARRAY = 0x0011, /* Multiply Dimensioned Array */ - CV4_LF_VFTPATH = 0x0012, /* Path to Virtual Function Table */ - CV4_LF_PRECOMP = 0x0013, /* Reference Precompiled Types */ - CV4_LF_ENDPRECOMP = 0x0014, /* End of Precompiled Types */ - - /* CodeView 5.0 version */ - CV5_LF_MODIFIER = 0x1001, /* Type Modifier */ - CV5_LF_POINTER = 0x1002, /* Pointer */ - CV5_LF_ARRAY = 0x1003, /* Simple Array */ - CV5_LF_CLASS = 0x1004, /* Classes */ - CV5_LF_STRUCTURE = 0x1005, /* Structures */ - CV5_LF_UNION = 0x1006, /* Unions */ - CV5_LF_ENUM = 0x1007, /* Enumeration */ - CV5_LF_PROCEDURE = 0x1008, /* Procedure */ - CV5_LF_MFUNCTION = 0x1009, /* Member Function */ - CV5_LF_VTSHAPE = 0x000a, /* Virtual Function Table Shape */ - CV5_LF_BARRAY = 0x100d, /* Basic Array */ - CV5_LF_LABEL = 0x000e, /* Label */ - CV5_LF_NULL = 0x000f, /* Null */ - CV5_LF_DIMARRAY = 0x100c, /* Multiply Dimensioned Array */ - CV5_LF_VFTPATH = 0x100d, /* Path to Virtual Function Table */ - CV5_LF_PRECOMP = 0x100e, /* Reference Precompiled Types */ - CV5_LF_ENDPRECOMP = 0x0014, /* End of Precompiled Types */ - CV5_LF_TYPESERVER = 0x0016, /* Reference Typeserver */ - - /* Leaf indices for type records that can be referenced from other type - * records - */ - CV4_LF_SKIP = 0x0200, /* Skip */ - CV4_LF_ARGLIST = 0x0201, /* Argument List */ - CV4_LF_DEFARG = 0x0202, /* Default Argument */ - CV4_LF_LIST = 0x0203, /* Arbitrary List */ - CV4_LF_FIELDLIST = 0x0204, /* Field List */ - CV4_LF_DERIVED = 0x0205, /* Derived Classes */ - CV4_LF_BITFIELD = 0x0206, /* Bit Fields */ - CV4_LF_METHODLIST = 0x0207, /* Method List */ - CV4_LF_DIMCONU = 0x0208, /* Dimensioned Array with Constant Upper Bound */ - CV4_LF_DIMCONLU = 0x0209, /* Dimensioned Array with Constant Lower and Upper Bounds */ - CV4_LF_DIMVARU = 0x020a, /* Dimensioned Array with Variable Upper Bound */ - CV4_LF_DIMVARLU = 0x020b, /* Dimensioned Array with Variable Lower and Upper Bounds */ - CV4_LF_REFSYM = 0x020c, /* Referenced Symbol */ - - /* CodeView 5.0 version */ - CV5_LF_SKIP = 0x1200, /* Skip */ - CV5_LF_ARGLIST = 0x1201, /* Argument List */ - CV5_LF_DEFARG = 0x1202, /* Default Argument */ - CV5_LF_FIELDLIST = 0x1203, /* Field List */ - CV5_LF_DERIVED = 0x1204, /* Derived Classes */ - CV5_LF_BITFIELD = 0x1205, /* Bit Fields */ - CV5_LF_METHODLIST = 0x1206, /* Method List */ - CV5_LF_DIMCONU = 0x1207, /* Dimensioned Array with Constant Upper Bound */ - CV5_LF_DIMCONLU = 0x1208, /* Dimensioned Array with Constant Lower and Upper Bounds */ - CV5_LF_DIMVARU = 0x1209, /* Dimensioned Array with Variable Upper Bound */ - CV5_LF_DIMVARLU = 0x120a, /* Dimensioned Array with Variable Lower and Upper Bounds */ - CV5_LF_REFSYM = 0x020c, /* Referenced Symbol */ - - /* Leaf indices for fields of complex lists */ - CV4_LF_BCLASS = 0x0400, /* Real Base Class */ - CV4_LF_VBCLASS = 0x0401, /* Direct Virtual Base Class */ - CV4_LF_IVBCLASS = 0x0402, /* Indirect Virtual Base Class */ - CV4_LF_ENUMERATE = 0x0403, /* Enumeration Name and Value */ - CV4_LF_FRIENDFCN = 0x0404, /* Friend Function */ - CV4_LF_INDEX = 0x0405, /* Index To Another Type Record */ - CV4_LF_MEMBER = 0x0406, /* Data Member */ - CV4_LF_STMEMBER = 0x0407, /* Static Data Member */ - CV4_LF_METHOD = 0x0408, /* Method */ - CV4_LF_NESTTYPE = 0x0409, /* Nested Type Definition */ - CV4_LF_VFUNCTAB = 0x040a, /* Virtual Function Table Pointer */ - CV4_LF_FRIENDCLS = 0x040b, /* Friend Class */ - CV4_LF_ONEMETHOD = 0x040c, /* One Method */ - CV4_LF_VFUNCOFF = 0x040d, /* Virtual Function Offset */ - - /* CodeView 5.0 version */ - CV5_LF_BCLASS = 0x1400, /* Real Base Class */ - CV5_LF_VBCLASS = 0x1401, /* Direct Virtual Base Class */ - CV5_LF_IVBCLASS = 0x1402, /* Indirect Virtual Base Class */ - CV5_LF_ENUMERATE = 0x0403, /* Enumeration Name and Value */ - CV5_LF_FRIENDFCN = 0x1403, /* Friend Function */ - CV5_LF_INDEX = 0x1404, /* Index To Another Type Record */ - CV5_LF_MEMBER = 0x1405, /* Data Member */ - CV5_LF_STMEMBER = 0x1406, /* Static Data Member */ - CV5_LF_METHOD = 0x1407, /* Method */ - CV5_LF_NESTTYPE = 0x1408, /* Nested Type Definition */ - CV5_LF_VFUNCTAB = 0x1409, /* Virtual Function Table Pointer */ - CV5_LF_FRIENDCLS = 0x140a, /* Friend Class */ - CV5_LF_ONEMETHOD = 0x140b, /* One Method */ - CV5_LF_VFUNCOFF = 0x140c, /* Virtual Function Offset */ - CV5_LF_NESTTYPEEX = 0x140d, /* Nested Type Extended Definition */ - CV5_LF_MEMBERMODIFY = 0x140e, /* Member Modification */ - /* XXX: CodeView 5.0 spec also lists 0x040f as LF_MEMBERMODIFY? */ - - /* Leaf indices for numeric fields of symbols and type records */ - CV_LF_NUMERIC = 0x8000, - CV_LF_CHAR = 0x8000, /* Signed Char (8-bit) */ - CV_LF_SHORT = 0x8001, /* Signed Short (16-bit) */ - CV_LF_USHORT = 0x8002, /* Unsigned Short (16-bit) */ - CV_LF_LONG = 0x8003, /* Signed Long (32-bit) */ - CV_LF_ULONG = 0x8004, /* Unsigned Long (32-bit) */ - CV_LF_REAL32 = 0x8005, /* 32-bit Float */ - CV_LF_REAL64 = 0x8006, /* 64-bit Float */ - CV_LF_REAL80 = 0x8007, /* 80-bit Float */ - CV_LF_REAL128 = 0x8008, /* 128-bit Float */ - CV_LF_QUADWORD = 0x8009, /* Signed Quad Word (64-bit) */ - CV_LF_UQUADWORD = 0x800a, /* Unsigned Quad Word (64-bit) */ - CV_LF_REAL48 = 0x800b, /* 48-bit Float */ - CV_LF_COMPLEX32 = 0x800c, /* 32-bit Complex */ - CV_LF_COMPLEX64 = 0x800d, /* 64-bit Complex */ - CV_LF_COMPLEX80 = 0x800e, /* 80-bit Complex */ - CV_LF_COMPLEX128 = 0x800f, /* 128-bit Complex */ - CV_LF_VARSTRING = 0x8010, /* Variable-length String */ - - /* Leaf padding bytes */ - CV_LF_PAD0 = 0xf0, - CV_LF_PAD1 = 0xf1, - CV_LF_PAD2 = 0xf2, - CV_LF_PAD3 = 0xf3, - CV_LF_PAD4 = 0xf4, - CV_LF_PAD5 = 0xf5, - CV_LF_PAD6 = 0xf6, - CV_LF_PAD7 = 0xf7, - CV_LF_PAD8 = 0xf8, - CV_LF_PAD9 = 0xf9, - CV_LF_PAD10 = 0xfa, - CV_LF_PAD11 = 0xfb, - CV_LF_PAD12 = 0xfc, - CV_LF_PAD13 = 0xfc, - CV_LF_PAD14 = 0xfe, - CV_LF_PAD15 = 0xff -}; - -/* Leaves use a bit of meta-programming to encode formats: each character - * of format represents the output generated, as follows: - * 'b' : 1 byte value (integer) - * 'h' : 2 byte value (integer) - * 'w' : 4 byte value (integer) - * 'L' : subleaf, recurses into cv_leaf (pointer) - * 'T' : 4 byte type index, pulls cv_type.index from cv_type (pointer) - * 'S' : length-prefixed string (pointer) - */ -typedef struct cv_leaf { - enum cv_leaftype type; - const char *format; /* format of args */ - union { - unsigned long i; - void *p; - } args[6]; -} cv_leaf; - -typedef struct cv_type { - unsigned long indx; /* type # (must be same as output order) */ - size_t num_leaves; - /*@null@*/ /*@only@*/ cv_leaf **leaves; -} cv_type; - -/* Bytecode callback function prototypes */ -static void cv_type_bc_destroy(void *contents); -static void cv_type_bc_print(const void *contents, FILE *f, int indent_level); -static int cv_type_bc_calc_len - (yasm_bytecode *bc, yasm_bc_add_span_func add_span, void *add_span_data); -static int cv_type_bc_tobytes - (yasm_bytecode *bc, unsigned char **bufp, unsigned char *bufstart, void *d, - yasm_output_value_func output_value, - /*@null@*/ yasm_output_reloc_func output_reloc); - -/* Bytecode callback structures */ -static const yasm_bytecode_callback cv_type_bc_callback = { - cv_type_bc_destroy, - cv_type_bc_print, - yasm_bc_finalize_common, - NULL, - cv_type_bc_calc_len, - yasm_bc_expand_common, - cv_type_bc_tobytes, - 0 -}; - -static cv_type *cv_type_create(unsigned long indx); -static void cv_type_append_leaf(cv_type *type, /*@keep@*/ cv_leaf *leaf); - - -static cv_leaf * -cv_leaf_create_label(int is_far) -{ - cv_leaf *leaf = yasm_xmalloc(sizeof(cv_leaf)); - leaf->type = CV5_LF_LABEL; - leaf->format = "h"; - leaf->args[0].i = is_far ? 4 : 0; - return leaf; -} - -yasm_section * -yasm_cv__generate_type(yasm_object *object) -{ - int new; - unsigned long indx = CV_FIRST_NONPRIM; - yasm_section *debug_type; - yasm_bytecode *bc; - cv_type *type; - - debug_type = - yasm_object_get_general(object, ".debug$T", 1, 0, 0, &new, 0); - - /* Add label type */ - type = cv_type_create(indx++); - cv_type_append_leaf(type, cv_leaf_create_label(0)); - bc = yasm_bc_create_common(&cv_type_bc_callback, type, 0); - yasm_bc_finalize(bc, yasm_cv__append_bc(debug_type, bc)); - yasm_bc_calc_len(bc, NULL, NULL); - - return debug_type; -} - -static void -cv_leaf_destroy(cv_leaf *leaf) -{ - const char *ch = leaf->format; - int arg = 0; - - while (*ch) { - switch (*ch) { - case 'b': - case 'h': - case 'w': - arg++; - break; /* nothing to destroy */ - case 'L': - cv_leaf_destroy((cv_leaf *)leaf->args[arg++].p); - break; - case 'T': - arg++; /* nothing to destroy */ - break; - case 'S': - yasm_xfree(leaf->args[arg++].p); - break; - default: - yasm_internal_error(N_("unknown leaf format character")); - } - ch++; - } -} - -static unsigned long -cv_leaf_size(const cv_leaf *leaf) -{ - const char *ch = leaf->format; - unsigned long len = 2; /* leaf type */ - unsigned long slen; - int arg = 0; - - while (*ch) { - switch (*ch) { - case 'b': - len++; - arg++; - break; - case 'h': - len += 2; - arg++; - break; - case 'w': - len += 4; - arg++; - break; - case 'L': - len += cv_leaf_size((const cv_leaf *)leaf->args[arg++].p); - break; - case 'T': - len += 4; /* XXX: will be 2 in CV4 */ - arg++; - break; - case 'S': - len += 1; /* XXX: is this 1 or 2? */ - slen = (unsigned long)strlen((const char *)leaf->args[arg++].p); - len += slen <= 0xff ? slen : 0xff; - break; - default: - yasm_internal_error(N_("unknown leaf format character")); - } - ch++; - } - - return len; -} - -static void -cv_leaf_tobytes(const cv_leaf *leaf, yasm_bytecode *bc, yasm_arch *arch, - unsigned char **bufp, yasm_intnum *cval) -{ - unsigned char *buf = *bufp; - const char *ch = leaf->format; - size_t len; - int arg = 0; - - /* leaf type */ - yasm_intnum_set_uint(cval, leaf->type); - yasm_arch_intnum_tobytes(arch, cval, buf, 2, 16, 0, bc, 0); - buf += 2; - - while (*ch) { - switch (*ch) { - case 'b': - YASM_WRITE_8(buf, leaf->args[arg].i); - arg++; - break; - case 'h': - yasm_intnum_set_uint(cval, leaf->args[arg++].i); - yasm_arch_intnum_tobytes(arch, cval, buf, 2, 16, 0, bc, 0); - buf += 2; - break; - case 'w': - yasm_intnum_set_uint(cval, leaf->args[arg++].i); - yasm_arch_intnum_tobytes(arch, cval, buf, 4, 32, 0, bc, 0); - buf += 4; - break; - case 'L': - cv_leaf_tobytes((const cv_leaf *)leaf->args[arg++].p, bc, arch, - &buf, cval); - break; - case 'T': - yasm_intnum_set_uint(cval, - ((const cv_type *)leaf->args[arg++].p)->indx); - yasm_arch_intnum_tobytes(arch, cval, buf, 4, 32, 0, bc, 0); - buf += 4; /* XXX: will be 2 in CV4 */ - break; - case 'S': - len = strlen((const char *)leaf->args[arg].p); - len = len <= 0xff ? len : 0xff; - YASM_WRITE_8(buf, len); - memcpy(buf, (const char *)leaf->args[arg].p, len); - buf += len; - arg++; - break; - default: - yasm_internal_error(N_("unknown leaf format character")); - } - ch++; - } - - *bufp = buf; -} - -static cv_type * -cv_type_create(unsigned long indx) -{ - cv_type *type = yasm_xmalloc(sizeof(cv_type)); - - type->indx = indx; - type->num_leaves = 0; - type->leaves = NULL; - - return type; -} - -static void -cv_type_append_leaf(cv_type *type, /*@keep@*/ cv_leaf *leaf) -{ - type->num_leaves++; - - /* This is inefficient for large numbers of leaves, but that won't happen - * until we add structure support. - */ - type->leaves = yasm_xrealloc(type->leaves, - type->num_leaves*sizeof(cv_leaf *)); - - type->leaves[type->num_leaves-1] = leaf; -} - -static void -cv_type_bc_destroy(void *contents) -{ - cv_type *type = (cv_type *)contents; - size_t i; - - for (i=0; i<type->num_leaves; i++) - cv_leaf_destroy(type->leaves[i]); - if (type->leaves) - yasm_xfree(type->leaves); - yasm_xfree(contents); -} - -static void -cv_type_bc_print(const void *contents, FILE *f, int indent_level) -{ - /* TODO */ -} - -static int -cv_type_bc_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span, - void *add_span_data) -{ - cv_type *type = (cv_type *)bc->contents; - size_t i; - - if (type->indx == CV_FIRST_NONPRIM) - bc->len = 4+2; - else - bc->len = 2; - - for (i=0; i<type->num_leaves; i++) - bc->len += cv_leaf_size(type->leaves[i]); - - /* Pad to multiple of 4 */ - if (bc->len & 0x3) - bc->len += 4-(bc->len & 0x3); - - return 0; -} - -static int -cv_type_bc_tobytes(yasm_bytecode *bc, unsigned char **bufp, - unsigned char *bufstart, void *d, - yasm_output_value_func output_value, - yasm_output_reloc_func output_reloc) -{ - yasm_object *object = yasm_section_get_object(bc->section); - cv_type *type = (cv_type *)bc->contents; - unsigned char *buf = *bufp; - yasm_intnum *cval; - size_t i; - unsigned long reclen = bc->len - 2; - - cval = yasm_intnum_create_uint(4); /* version */ - if (type->indx == CV_FIRST_NONPRIM) { - yasm_arch_intnum_tobytes(object->arch, cval, buf, 4, 32, 0, bc, 1); - buf += 4; - reclen -= 4; - } - - /* Total length of record (following this field) - 2 bytes */ - yasm_intnum_set_uint(cval, reclen); - yasm_arch_intnum_tobytes(object->arch, cval, buf, 2, 16, 0, bc, 1); - buf += 2; - - /* Leaves */ - for (i=0; i<type->num_leaves; i++) - cv_leaf_tobytes(type->leaves[i], bc, object->arch, &buf, cval); - - /* Pad to multiple of 4 */ - switch ((buf-(*bufp)) & 0x3) { - case 3: - YASM_WRITE_8(buf, CV_LF_PAD3); - case 2: - YASM_WRITE_8(buf, CV_LF_PAD2); - case 1: - YASM_WRITE_8(buf, CV_LF_PAD1); - case 0: - break; - } - - *bufp = buf; - - yasm_intnum_destroy(cval); - return 0; -} +/* + * CodeView debugging format - type information + * + * Copyright (C) 2006-2007 Peter Johnson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of other contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include <util.h> + +#include <libyasm.h> + +#include "cv-dbgfmt.h" + +enum cv_reservedtype { + /* Bitfields representation - type */ + CV_TYPE_SPECIAL = 0x00<<4, /* Special */ + CV_TYPE_SIGNED = 0x01<<4, /* Signed integral value */ + CV_TYPE_UNSIGNED = 0x02<<4, /* Unsigned integral value */ + CV_TYPE_BOOLEAN = 0x03<<4, /* Boolean */ + CV_TYPE_REAL = 0x04<<4, /* Real */ + CV_TYPE_COMPLEX = 0x05<<4, /* Complex */ + CV_TYPE_SPECIAL2 = 0x06<<4, /* Special2 */ + CV_TYPE_REALINT = 0x07<<4, /* Really int value */ + + /* "size" of CV_TYPE_SPECIAL */ + CV_SPECIAL_NOTYPE = 0x00<<0, /* No type */ + CV_SPECIAL_ABS = 0x01<<0, /* Absolute symbol */ + CV_SPECIAL_SEG = 0x02<<0, /* Segment */ + CV_SPECIAL_VOID = 0x03<<0, /* Void */ + CV_SPECIAL_CURRENCY = 0x04<<0, /* Basic 8-byte currency value */ + CV_SPECIAL_NEARBSTR = 0x05<<0, /* Near Basic string */ + CV_SPECIAL_FARBSTR = 0x06<<0, /* Far Basic string */ + + /* Size of CV_TYPE_SIGNED, CV_TYPE_UNSIGNED, and CV_TYPE_BOOLEAN */ + CV_INTEGER_1BYTE = 0x00<<0, /* 1 byte */ + CV_INTEGER_2BYTE = 0x01<<0, /* 2 byte */ + CV_INTEGER_4BYTE = 0x02<<0, /* 4 byte */ + CV_INTEGER_8BYTE = 0x03<<0, /* 8 byte */ + + /* Size of CV_TYPE_REAL and CV_TYPE_COMPLEX */ + CV_REAL_32BIT = 0x00<<0, /* 32 bit */ + CV_REAL_64BIT = 0x01<<0, /* 64 bit */ + CV_REAL_80BIT = 0x02<<0, /* 80 bit */ + CV_REAL_128BIT = 0x03<<0, /* 128 bit */ + CV_REAL_48BIT = 0x04<<0, /* 48 bit */ + + /* "size" of CV_TYPE_SPECIAL2 */ + CV_SPECIAL2_BIT = 0x00<<0, /* Bit */ + CV_SPECIAL2_PASCHAR = 0x01<<0, /* Pascal CHAR */ + + /* Size of CV_TYPE_REALINT */ + CV_REALINT_CHAR = 0x00<<0, /* Char */ + CV_REALINT_WCHAR = 0x01<<0, /* Wide character */ + CV_REALINT_S2BYTE = 0x02<<0, /* 2-byte signed integer */ + CV_REALINT_U2BYTE = 0x03<<0, /* 2-byte unsigned integer */ + CV_REALINT_S4BYTE = 0x04<<0, /* 4-byte signed integer */ + CV_REALINT_U4BYTE = 0x05<<0, /* 4-byte unsigned integer */ + CV_REALINT_S8BYTE = 0x06<<0, /* 8-byte signed integer */ + CV_REALINT_U8BYTE = 0x07<<0, /* 8-byte unsigned integer */ + + /* Mode */ + CV_MODE_DIRECT = 0x00<<8, /* Direct; not a pointer */ + CV_MODE_NEAR = 0x01<<8, /* Near pointer */ + CV_MODE_FAR = 0x02<<8, /* Far pointer */ + CV_MODE_HUGE = 0x03<<8, /* Huge pointer */ + CV_MODE_NEAR32 = 0x04<<8, /* 32-bit near pointer */ + CV_MODE_FAR32 = 0x05<<8, /* 32-bit far pointer */ + CV_MODE_NEAR64 = 0x06<<8, /* 64-bit near pointer */ + + /* Pure primitive type listing - based on above bitfields */ + + /* Special Types */ + CV_T_NOTYPE = 0x0000, /* Uncharacterized type (no type) */ + CV_T_ABS = 0x0001, /* Absolute symbol */ + CV_T_SEGMENT = 0x0002, /* Segment type */ + CV_T_VOID = 0x0003, /* Void */ + CV_T_PVOID = 0x0103, /* Near pointer to void */ + CV_T_PFVOID = 0x0203, /* Far pointer to void */ + CV_T_PHVOID = 0x0303, /* Huge pointer to void */ + CV_T_32PVOID = 0x0403, /* 32-bit near pointer to void */ + CV_T_32PFVOID = 0x0503, /* 32-bit far pointer to void */ + CV_T_CURRENCY = 0x0004, /* Basic 8-byte currency value */ + CV_T_NBASICSTR = 0x0005, /* Near Basic string */ + CV_T_FBASICSTR = 0x0006, /* Far Basic string */ + CV_T_BIT = 0x0060, /* Bit */ + CV_T_PASCHAR = 0x0061, /* Pascal CHAR */ + /* Character Types */ + CV_T_CHAR = 0x0010, /* 8-bit signed */ + CV_T_UCHAR = 0x0020, /* 8-bit unsigned */ + CV_T_PCHAR = 0x0110, /* Near pointer to 8-bit signed */ + CV_T_PUCHAR = 0x0120, /* Near pointer to 8-bit unsigned */ + CV_T_PFCHAR = 0x0210, /* Far pointer to 8-bit signed */ + CV_T_PFUCHAR = 0x0220, /* Far pointer to 8-bit unsigned */ + CV_T_PHCHAR = 0x0310, /* Huge pointer to 8-bit signed */ + CV_T_PHUCHAR = 0x0320, /* Huge pointer to 8-bit unsigned */ + CV_T_32PCHAR = 0x0410, /* 16:32 near pointer to 8-bit signed */ + CV_T_32PUCHAR = 0x0420, /* 16:32 near pointer to 8-bit unsigned */ + CV_T_32PFCHAR = 0x0510, /* 16:32 far pointer to 8-bit signed */ + CV_T_32PFUCHAR = 0x0520, /* 16:32 far pointer to 8-bit unsigned */ + /* Real Character Types */ + CV_T_RCHAR = 0x0070, /* Real char */ + CV_T_PRCHAR = 0x0170, /* Near pointer to a real char */ + CV_T_PFRCHAR = 0x0270, /* Far pointer to a real char */ + CV_T_PHRCHAR = 0x0370, /* Huge pointer to a real char */ + CV_T_32PRCHAR = 0x0470, /* 16:32 near pointer to a real char */ + CV_T_32PFRCHAR = 0x0570, /* 16:32 far pointer to a real char */ + /* Wide Character Types */ + CV_T_WCHAR = 0x0071, /* Wide char */ + CV_T_PWCHAR = 0x0171, /* Near pointer to a wide char */ + CV_T_PFWCHAR = 0x0271, /* Far pointer to a wide char */ + CV_T_PHWCHAR = 0x0371, /* Huge pointer to a wide char */ + CV_T_32PWCHAR = 0x0471, /* 16:32 near pointer to a wide char */ + CV_T_32PFWCHAR = 0x0571, /* 16:32 far pointer to a wide char */ + /* Real 16-bit Integer Types */ + CV_T_INT2 = 0x0072, /* Real 16-bit signed int */ + CV_T_UINT2 = 0x0073, /* Real 16-bit unsigned int */ + CV_T_PINT2 = 0x0172, /* Near pointer to 16-bit signed int */ + CV_T_PUINT2 = 0x0173, /* Near pointer to 16-bit unsigned int */ + CV_T_PFINT2 = 0x0272, /* Far pointer to 16-bit signed int */ + CV_T_PFUINT2 = 0x0273, /* Far pointer to 16-bit unsigned int */ + CV_T_PHINT2 = 0x0372, /* Huge pointer to 16-bit signed int */ + CV_T_PHUINT2 = 0x0373, /* Huge pointer to 16-bit unsigned int */ + CV_T_32PINT2 = 0x0472, /* 16:32 near pointer to 16-bit signed int */ + CV_T_32PUINT2 = 0x0473, /* 16:32 near pointer to 16-bit unsigned int */ + CV_T_32PFINT2 = 0x0572, /* 16:32 far pointer to 16-bit signed int */ + CV_T_32PFUINT2 = 0x0573, /* 16:32 far pointer to 16-bit unsigned int */ + /* 16-bit Short Types */ + CV_T_SHORT = 0x0011, /* 16-bit signed */ + CV_T_USHORT = 0x0021, /* 16-bit unsigned */ + CV_T_PSHORT = 0x0111, /* Near pointer to 16-bit signed */ + CV_T_PUSHORT = 0x0121, /* Near pointer to 16-bit unsigned */ + CV_T_PFSHORT = 0x0211, /* Far pointer to 16-bit signed */ + CV_T_PFUSHORT = 0x0221, /* Far pointer to 16-bit unsigned */ + CV_T_PHSHORT = 0x0311, /* Huge pointer to 16-bit signed */ + CV_T_PHUSHORT = 0x0321, /* Huge pointer to 16-bit unsigned */ + CV_T_32PSHORT = 0x0411, /* 16:32 near pointer to 16-bit signed */ + CV_T_32PUSHORT = 0x0421, /* 16:32 near pointer to 16-bit unsigned */ + CV_T_32PFSHORT = 0x0511, /* 16:32 far pointer to 16-bit signed */ + CV_T_32PFUSHORT = 0x0521, /* 16:32 far pointer to 16-bit unsigned */ + /* Real 32-bit Integer Types */ + CV_T_INT4 = 0x0074, /* Real 32-bit signed int */ + CV_T_UINT4 = 0x0075, /* Real 32-bit unsigned int */ + CV_T_PINT4 = 0x0174, /* Near pointer to 32-bit signed int */ + CV_T_PUINT4 = 0x0175, /* Near pointer to 32-bit unsigned int */ + CV_T_PFINT4 = 0x0274, /* Far pointer to 32-bit signed int */ + CV_T_PFUINT4 = 0x0275, /* Far pointer to 32-bit unsigned int */ + CV_T_PHINT4 = 0x0374, /* Huge pointer to 32-bit signed int */ + CV_T_PHUINT4 = 0x0375, /* Huge pointer to 32-bit unsigned int */ + CV_T_32PINT4 = 0x0474, /* 16:32 near pointer to 32-bit signed int */ + CV_T_32PUINT4 = 0x0475, /* 16:32 near pointer to 32-bit unsigned int */ + CV_T_32PFINT4 = 0x0574, /* 16:32 far pointer to 32-bit signed int */ + CV_T_32PFUINT4 = 0x0575, /* 16:32 far pointer to 32-bit unsigned int */ + /* 32-bit Long Types */ + CV_T_LONG = 0x0012, /* 32-bit signed */ + CV_T_ULONG = 0x0022, /* 32-bit unsigned */ + CV_T_PLONG = 0x0112, /* Near pointer to 32-bit signed */ + CV_T_PULONG = 0x0122, /* Near pointer to 32-bit unsigned */ + CV_T_PFLONG = 0x0212, /* Far pointer to 32-bit signed */ + CV_T_PFULONG = 0x0222, /* Far pointer to 32-bit unsigned */ + CV_T_PHLONG = 0x0312, /* Huge pointer to 32-bit signed */ + CV_T_PHULONG = 0x0322, /* Huge pointer to 32-bit unsigned */ + CV_T_32PLONG = 0x0412, /* 16:32 near pointer to 32-bit signed */ + CV_T_32PULONG = 0x0422, /* 16:32 near pointer to 32-bit unsigned */ + CV_T_32PFLONG = 0x0512, /* 16:32 far pointer to 32-bit signed */ + CV_T_32PFULONG = 0x0522, /* 16:32 far pointer to 32-bit unsigned */ + /* Real 64-bit int Types */ + CV_T_INT8 = 0x0076, /* 64-bit signed int */ + CV_T_UINT8 = 0x0077, /* 64-bit unsigned int */ + CV_T_PINT8 = 0x0176, /* Near pointer to 64-bit signed int */ + CV_T_PUINT8 = 0x0177, /* Near pointer to 64-bit unsigned int */ + CV_T_PFINT8 = 0x0276, /* Far pointer to 64-bit signed int */ + CV_T_PFUINT8 = 0x0277, /* Far pointer to 64-bit unsigned int */ + CV_T_PHINT8 = 0x0376, /* Huge pointer to 64-bit signed int */ + CV_T_PHUINT8 = 0x0377, /* Huge pointer to 64-bit unsigned int */ + CV_T_32PINT8 = 0x0476, /* 16:32 near pointer to 64-bit signed int */ + CV_T_32PUINT8 = 0x0477, /* 16:32 near pointer to 64-bit unsigned int */ + CV_T_32PFINT8 = 0x0576, /* 16:32 far pointer to 64-bit signed int */ + CV_T_32PFUINT8 = 0x0577, /* 16:32 far pointer to 64-bit unsigned int */ + /* 64-bit Integral Types */ + CV_T_QUAD = 0x0013, /* 64-bit signed */ + CV_T_UQUAD = 0x0023, /* 64-bit unsigned */ + CV_T_PQUAD = 0x0113, /* Near pointer to 64-bit signed */ + CV_T_PUQUAD = 0x0123, /* Near pointer to 64-bit unsigned */ + CV_T_PFQUAD = 0x0213, /* Far pointer to 64-bit signed */ + CV_T_PFUQUAD = 0x0223, /* Far pointer to 64-bit unsigned */ + CV_T_PHQUAD = 0x0313, /* Huge pointer to 64-bit signed */ + CV_T_PHUQUAD = 0x0323, /* Huge pointer to 64-bit unsigned */ + CV_T_32PQUAD = 0x0413, /* 16:32 near pointer to 64-bit signed */ + CV_T_32PUQUAD = 0x0423, /* 16:32 near pointer to 64-bit unsigned */ + CV_T_32PFQUAD = 0x0513, /* 16:32 far pointer to 64-bit signed */ + CV_T_32PFUQUAD = 0x0523, /* 16:32 far pointer to 64-bit unsigned */ + /* 32-bit Real Types */ + CV_T_REAL32 = 0x0040, /* 32-bit real */ + CV_T_PREAL32 = 0x0140, /* Near pointer to 32-bit real */ + CV_T_PFREAL32 = 0x0240, /* Far pointer to 32-bit real */ + CV_T_PHREAL32 = 0x0340, /* Huge pointer to 32-bit real */ + CV_T_32PREAL32 = 0x0440, /* 16:32 near pointer to 32-bit real */ + CV_T_32PFREAL32 = 0x0540, /* 16:32 far pointer to 32-bit real */ + /* 48-bit Real Types */ + CV_T_REAL48 = 0x0044, /* 48-bit real */ + CV_T_PREAL48 = 0x0144, /* Near pointer to 48-bit real */ + CV_T_PFREAL48 = 0x0244, /* Far pointer to 48-bit real */ + CV_T_PHREAL48 = 0x0344, /* Huge pointer to 48-bit real */ + CV_T_32PREAL48 = 0x0444, /* 16:32 near pointer to 48-bit real */ + CV_T_32PFREAL48 = 0x0544, /* 16:32 far pointer to 48-bit real */ + /* 64-bit Real Types */ + CV_T_REAL64 = 0x0041, /* 64-bit real */ + CV_T_PREAL64 = 0x0141, /* Near pointer to 64-bit real */ + CV_T_PFREAL64 = 0x0241, /* Far pointer to 64-bit real */ + CV_T_PHREAL64 = 0x0341, /* Huge pointer to 64-bit real */ + CV_T_32PREAL64 = 0x0441, /* 16:32 near pointer to 64-bit real */ + CV_T_32PFREAL64 = 0x0541, /* 16:32 far pointer to 64-bit real */ + /* 80-bit Real Types */ + CV_T_REAL80 = 0x0042, /* 80-bit real */ + CV_T_PREAL80 = 0x0142, /* Near pointer to 80-bit real */ + CV_T_PFREAL80 = 0x0242, /* Far pointer to 80-bit real */ + CV_T_PHREAL80 = 0x0342, /* Huge pointer to 80-bit real */ + CV_T_32PREAL80 = 0x0442, /* 16:32 near pointer to 80-bit real */ + CV_T_32PFREAL80 = 0x0542, /* 16:32 far pointer to 80-bit real */ + /* 128-bit Real Types */ + CV_T_REAL128 = 0x0043, /* 128-bit real */ + CV_T_PREAL128 = 0x0143, /* Near pointer to 128-bit real */ + CV_T_PFREAL128 = 0x0243, /* Far pointer to 128-bit real */ + CV_T_PHREAL128 = 0x0343, /* Huge pointer to 128-bit real */ + CV_T_32PREAL128 = 0x0443, /* 16:32 near pointer to 128-bit real */ + CV_T_32PFREAL128 = 0x0543, /* 16:32 far pointer to 128-bit real */ + /* 32-bit Complex Types */ + CV_T_CPLX32 = 0x0050, /* 32-bit complex */ + CV_T_PCPLX32 = 0x0150, /* Near pointer to 32-bit complex */ + CV_T_PFCPLX32 = 0x0250, /* Far pointer to 32-bit complex */ + CV_T_PHCPLX32 = 0x0350, /* Huge pointer to 32-bit complex */ + CV_T_32PCPLX32 = 0x0450, /* 16:32 near pointer to 32-bit complex */ + CV_T_32PFCPLX32 = 0x0550, /* 16:32 far pointer to 32-bit complex */ + /* 64-bit Complex Types */ + CV_T_CPLX64 = 0x0051, /* 64-bit complex */ + CV_T_PCPLX64 = 0x0151, /* Near pointer to 64-bit complex */ + CV_T_PFCPLX64 = 0x0251, /* Far pointer to 64-bit complex */ + CV_T_PHCPLX64 = 0x0351, /* Huge pointer to 64-bit complex */ + CV_T_32PCPLX64 = 0x0451, /* 16:32 near pointer to 64-bit complex */ + CV_T_32PFCPLX64 = 0x0551, /* 16:32 far pointer to 64-bit complex */ + /* 80-bit Complex Types */ + CV_T_CPLX80 = 0x0052, /* 80-bit complex */ + CV_T_PCPLX80 = 0x0152, /* Near pointer to 80-bit complex */ + CV_T_PFCPLX80 = 0x0252, /* Far pointer to 80-bit complex */ + CV_T_PHCPLX80 = 0x0352, /* Huge pointer to 80-bit complex */ + CV_T_32PCPLX80 = 0x0452, /* 16:32 near pointer to 80-bit complex */ + CV_T_32PFCPLX80 = 0x0552, /* 16:32 far pointer to 80-bit complex */ + /* 128-bit Complex Types */ + CV_T_CPLX128 = 0x0053, /* 128-bit complex */ + CV_T_PCPLX128 = 0x0153, /* Near pointer to 128-bit complex */ + CV_T_PFCPLX128 = 0x0253, /* Far pointer to 128-bit complex */ + CV_T_PHCPLX128 = 0x0353, /* Huge pointer to 128-bit real */ + CV_T_32PCPLX128 = 0x0453, /* 16:32 near pointer to 128-bit complex */ + CV_T_32PFCPLX128 = 0x0553, /* 16:32 far pointer to 128-bit complex */ + /* Boolean Types */ + CV_T_BOOL08 = 0x0030, /* 8-bit Boolean */ + CV_T_BOOL16 = 0x0031, /* 16-bit Boolean */ + CV_T_BOOL32 = 0x0032, /* 32-bit Boolean */ + CV_T_BOOL64 = 0x0033, /* 64-bit Boolean */ + CV_T_PBOOL08 = 0x0130, /* Near pointer to 8-bit Boolean */ + CV_T_PBOOL16 = 0x0131, /* Near pointer to 16-bit Boolean */ + CV_T_PBOOL32 = 0x0132, /* Near pointer to 32-bit Boolean */ + CV_T_PBOOL64 = 0x0133, /* Near pointer to 64-bit Boolean */ + CV_T_PFBOOL08 = 0x0230, /* Far pointer to 8-bit Boolean */ + CV_T_PFBOOL16 = 0x0231, /* Far pointer to 16-bit Boolean */ + CV_T_PFBOOL32 = 0x0232, /* Far pointer to 32-bit Boolean */ + CV_T_PFBOOL64 = 0x0233, /* Far pointer to 64-bit Boolean */ + CV_T_PHBOOL08 = 0x0330, /* Huge pointer to 8-bit Boolean */ + CV_T_PHBOOL16 = 0x0331, /* Huge pointer to 16-bit Boolean */ + CV_T_PHBOOL32 = 0x0332, /* Huge pointer to 32-bit Boolean */ + CV_T_PHBOOL64 = 0x0333, /* Huge pointer to 64-bit Boolean */ + CV_T_32PBOOL08 = 0x0430, /* 16:32 near pointer to 8-bit Boolean */ + CV_T_32PBOOL16 = 0x0431, /* 16:32 near pointer to 16-bit Boolean */ + CV_T_32PBOOL32 = 0x0432, /* 16:32 near pointer to 32-bit Boolean */ + CV_T_32PBOOL64 = 0x0433, /* 16:32 near pointer to 64-bit Boolean */ + CV_T_32PFBOOL08 = 0x0530, /* 16:32 far pointer to 8-bit Boolean */ + CV_T_32PFBOOL16 = 0x0531, /* 16:32 far pointer to 16-bit Boolean */ + CV_T_32PFBOOL32 = 0x0532, /* 16:32 far pointer to 32-bit Boolean */ + CV_T_32PFBOOL64 = 0x0533, /* 16:32 far pointer to 64-bit Boolean */ + + /* Non-primitive types are stored in the TYPES section (generated in + * cv-type.c) and start at this index (e.g. 0x1000 is the first type + * in TYPES, 0x1001 the second, etc. + */ + CV_FIRST_NONPRIM = 0x1000 +}; + +enum cv_leaftype { + /* Leaf indices for type records that can be referenced from symbols */ + CV4_LF_MODIFIER = 0x0001, /* Type Modifier */ + CV4_LF_POINTER = 0x0002, /* Pointer */ + CV4_LF_ARRAY = 0x0003, /* Simple Array */ + CV4_LF_CLASS = 0x0004, /* Classes */ + CV4_LF_STRUCTURE = 0x0005, /* Structures */ + CV4_LF_UNION = 0x0006, /* Unions */ + CV4_LF_ENUM = 0x0007, /* Enumeration */ + CV4_LF_PROCEDURE = 0x0008, /* Procedure */ + CV4_LF_MFUNCTION = 0x0009, /* Member Function */ + CV4_LF_VTSHAPE = 0x000a, /* Virtual Function Table Shape */ + CV4_LF_BARRAY = 0x000d, /* Basic Array */ + CV4_LF_LABEL = 0x000e, /* Label */ + CV4_LF_NULL = 0x000f, /* Null */ + CV4_LF_DIMARRAY = 0x0011, /* Multiply Dimensioned Array */ + CV4_LF_VFTPATH = 0x0012, /* Path to Virtual Function Table */ + CV4_LF_PRECOMP = 0x0013, /* Reference Precompiled Types */ + CV4_LF_ENDPRECOMP = 0x0014, /* End of Precompiled Types */ + + /* CodeView 5.0 version */ + CV5_LF_MODIFIER = 0x1001, /* Type Modifier */ + CV5_LF_POINTER = 0x1002, /* Pointer */ + CV5_LF_ARRAY = 0x1003, /* Simple Array */ + CV5_LF_CLASS = 0x1004, /* Classes */ + CV5_LF_STRUCTURE = 0x1005, /* Structures */ + CV5_LF_UNION = 0x1006, /* Unions */ + CV5_LF_ENUM = 0x1007, /* Enumeration */ + CV5_LF_PROCEDURE = 0x1008, /* Procedure */ + CV5_LF_MFUNCTION = 0x1009, /* Member Function */ + CV5_LF_VTSHAPE = 0x000a, /* Virtual Function Table Shape */ + CV5_LF_BARRAY = 0x100d, /* Basic Array */ + CV5_LF_LABEL = 0x000e, /* Label */ + CV5_LF_NULL = 0x000f, /* Null */ + CV5_LF_DIMARRAY = 0x100c, /* Multiply Dimensioned Array */ + CV5_LF_VFTPATH = 0x100d, /* Path to Virtual Function Table */ + CV5_LF_PRECOMP = 0x100e, /* Reference Precompiled Types */ + CV5_LF_ENDPRECOMP = 0x0014, /* End of Precompiled Types */ + CV5_LF_TYPESERVER = 0x0016, /* Reference Typeserver */ + + /* Leaf indices for type records that can be referenced from other type + * records + */ + CV4_LF_SKIP = 0x0200, /* Skip */ + CV4_LF_ARGLIST = 0x0201, /* Argument List */ + CV4_LF_DEFARG = 0x0202, /* Default Argument */ + CV4_LF_LIST = 0x0203, /* Arbitrary List */ + CV4_LF_FIELDLIST = 0x0204, /* Field List */ + CV4_LF_DERIVED = 0x0205, /* Derived Classes */ + CV4_LF_BITFIELD = 0x0206, /* Bit Fields */ + CV4_LF_METHODLIST = 0x0207, /* Method List */ + CV4_LF_DIMCONU = 0x0208, /* Dimensioned Array with Constant Upper Bound */ + CV4_LF_DIMCONLU = 0x0209, /* Dimensioned Array with Constant Lower and Upper Bounds */ + CV4_LF_DIMVARU = 0x020a, /* Dimensioned Array with Variable Upper Bound */ + CV4_LF_DIMVARLU = 0x020b, /* Dimensioned Array with Variable Lower and Upper Bounds */ + CV4_LF_REFSYM = 0x020c, /* Referenced Symbol */ + + /* CodeView 5.0 version */ + CV5_LF_SKIP = 0x1200, /* Skip */ + CV5_LF_ARGLIST = 0x1201, /* Argument List */ + CV5_LF_DEFARG = 0x1202, /* Default Argument */ + CV5_LF_FIELDLIST = 0x1203, /* Field List */ + CV5_LF_DERIVED = 0x1204, /* Derived Classes */ + CV5_LF_BITFIELD = 0x1205, /* Bit Fields */ + CV5_LF_METHODLIST = 0x1206, /* Method List */ + CV5_LF_DIMCONU = 0x1207, /* Dimensioned Array with Constant Upper Bound */ + CV5_LF_DIMCONLU = 0x1208, /* Dimensioned Array with Constant Lower and Upper Bounds */ + CV5_LF_DIMVARU = 0x1209, /* Dimensioned Array with Variable Upper Bound */ + CV5_LF_DIMVARLU = 0x120a, /* Dimensioned Array with Variable Lower and Upper Bounds */ + CV5_LF_REFSYM = 0x020c, /* Referenced Symbol */ + + /* Leaf indices for fields of complex lists */ + CV4_LF_BCLASS = 0x0400, /* Real Base Class */ + CV4_LF_VBCLASS = 0x0401, /* Direct Virtual Base Class */ + CV4_LF_IVBCLASS = 0x0402, /* Indirect Virtual Base Class */ + CV4_LF_ENUMERATE = 0x0403, /* Enumeration Name and Value */ + CV4_LF_FRIENDFCN = 0x0404, /* Friend Function */ + CV4_LF_INDEX = 0x0405, /* Index To Another Type Record */ + CV4_LF_MEMBER = 0x0406, /* Data Member */ + CV4_LF_STMEMBER = 0x0407, /* Static Data Member */ + CV4_LF_METHOD = 0x0408, /* Method */ + CV4_LF_NESTTYPE = 0x0409, /* Nested Type Definition */ + CV4_LF_VFUNCTAB = 0x040a, /* Virtual Function Table Pointer */ + CV4_LF_FRIENDCLS = 0x040b, /* Friend Class */ + CV4_LF_ONEMETHOD = 0x040c, /* One Method */ + CV4_LF_VFUNCOFF = 0x040d, /* Virtual Function Offset */ + + /* CodeView 5.0 version */ + CV5_LF_BCLASS = 0x1400, /* Real Base Class */ + CV5_LF_VBCLASS = 0x1401, /* Direct Virtual Base Class */ + CV5_LF_IVBCLASS = 0x1402, /* Indirect Virtual Base Class */ + CV5_LF_ENUMERATE = 0x0403, /* Enumeration Name and Value */ + CV5_LF_FRIENDFCN = 0x1403, /* Friend Function */ + CV5_LF_INDEX = 0x1404, /* Index To Another Type Record */ + CV5_LF_MEMBER = 0x1405, /* Data Member */ + CV5_LF_STMEMBER = 0x1406, /* Static Data Member */ + CV5_LF_METHOD = 0x1407, /* Method */ + CV5_LF_NESTTYPE = 0x1408, /* Nested Type Definition */ + CV5_LF_VFUNCTAB = 0x1409, /* Virtual Function Table Pointer */ + CV5_LF_FRIENDCLS = 0x140a, /* Friend Class */ + CV5_LF_ONEMETHOD = 0x140b, /* One Method */ + CV5_LF_VFUNCOFF = 0x140c, /* Virtual Function Offset */ + CV5_LF_NESTTYPEEX = 0x140d, /* Nested Type Extended Definition */ + CV5_LF_MEMBERMODIFY = 0x140e, /* Member Modification */ + /* XXX: CodeView 5.0 spec also lists 0x040f as LF_MEMBERMODIFY? */ + + /* Leaf indices for numeric fields of symbols and type records */ + CV_LF_NUMERIC = 0x8000, + CV_LF_CHAR = 0x8000, /* Signed Char (8-bit) */ + CV_LF_SHORT = 0x8001, /* Signed Short (16-bit) */ + CV_LF_USHORT = 0x8002, /* Unsigned Short (16-bit) */ + CV_LF_LONG = 0x8003, /* Signed Long (32-bit) */ + CV_LF_ULONG = 0x8004, /* Unsigned Long (32-bit) */ + CV_LF_REAL32 = 0x8005, /* 32-bit Float */ + CV_LF_REAL64 = 0x8006, /* 64-bit Float */ + CV_LF_REAL80 = 0x8007, /* 80-bit Float */ + CV_LF_REAL128 = 0x8008, /* 128-bit Float */ + CV_LF_QUADWORD = 0x8009, /* Signed Quad Word (64-bit) */ + CV_LF_UQUADWORD = 0x800a, /* Unsigned Quad Word (64-bit) */ + CV_LF_REAL48 = 0x800b, /* 48-bit Float */ + CV_LF_COMPLEX32 = 0x800c, /* 32-bit Complex */ + CV_LF_COMPLEX64 = 0x800d, /* 64-bit Complex */ + CV_LF_COMPLEX80 = 0x800e, /* 80-bit Complex */ + CV_LF_COMPLEX128 = 0x800f, /* 128-bit Complex */ + CV_LF_VARSTRING = 0x8010, /* Variable-length String */ + + /* Leaf padding bytes */ + CV_LF_PAD0 = 0xf0, + CV_LF_PAD1 = 0xf1, + CV_LF_PAD2 = 0xf2, + CV_LF_PAD3 = 0xf3, + CV_LF_PAD4 = 0xf4, + CV_LF_PAD5 = 0xf5, + CV_LF_PAD6 = 0xf6, + CV_LF_PAD7 = 0xf7, + CV_LF_PAD8 = 0xf8, + CV_LF_PAD9 = 0xf9, + CV_LF_PAD10 = 0xfa, + CV_LF_PAD11 = 0xfb, + CV_LF_PAD12 = 0xfc, + CV_LF_PAD13 = 0xfc, + CV_LF_PAD14 = 0xfe, + CV_LF_PAD15 = 0xff +}; + +/* Leaves use a bit of meta-programming to encode formats: each character + * of format represents the output generated, as follows: + * 'b' : 1 byte value (integer) + * 'h' : 2 byte value (integer) + * 'w' : 4 byte value (integer) + * 'L' : subleaf, recurses into cv_leaf (pointer) + * 'T' : 4 byte type index, pulls cv_type.index from cv_type (pointer) + * 'S' : length-prefixed string (pointer) + */ +typedef struct cv_leaf { + enum cv_leaftype type; + const char *format; /* format of args */ + union { + unsigned long i; + void *p; + } args[6]; +} cv_leaf; + +typedef struct cv_type { + unsigned long indx; /* type # (must be same as output order) */ + size_t num_leaves; + /*@null@*/ /*@only@*/ cv_leaf **leaves; +} cv_type; + +/* Bytecode callback function prototypes */ +static void cv_type_bc_destroy(void *contents); +static void cv_type_bc_print(const void *contents, FILE *f, int indent_level); +static int cv_type_bc_calc_len + (yasm_bytecode *bc, yasm_bc_add_span_func add_span, void *add_span_data); +static int cv_type_bc_tobytes + (yasm_bytecode *bc, unsigned char **bufp, unsigned char *bufstart, void *d, + yasm_output_value_func output_value, + /*@null@*/ yasm_output_reloc_func output_reloc); + +/* Bytecode callback structures */ +static const yasm_bytecode_callback cv_type_bc_callback = { + cv_type_bc_destroy, + cv_type_bc_print, + yasm_bc_finalize_common, + NULL, + cv_type_bc_calc_len, + yasm_bc_expand_common, + cv_type_bc_tobytes, + 0 +}; + +static cv_type *cv_type_create(unsigned long indx); +static void cv_type_append_leaf(cv_type *type, /*@keep@*/ cv_leaf *leaf); + + +static cv_leaf * +cv_leaf_create_label(int is_far) +{ + cv_leaf *leaf = yasm_xmalloc(sizeof(cv_leaf)); + leaf->type = CV5_LF_LABEL; + leaf->format = "h"; + leaf->args[0].i = is_far ? 4 : 0; + return leaf; +} + +yasm_section * +yasm_cv__generate_type(yasm_object *object) +{ + int new; + unsigned long indx = CV_FIRST_NONPRIM; + yasm_section *debug_type; + yasm_bytecode *bc; + cv_type *type; + + debug_type = + yasm_object_get_general(object, ".debug$T", 1, 0, 0, &new, 0); + + /* Add label type */ + type = cv_type_create(indx++); + cv_type_append_leaf(type, cv_leaf_create_label(0)); + bc = yasm_bc_create_common(&cv_type_bc_callback, type, 0); + yasm_bc_finalize(bc, yasm_cv__append_bc(debug_type, bc)); + yasm_bc_calc_len(bc, NULL, NULL); + + return debug_type; +} + +static void +cv_leaf_destroy(cv_leaf *leaf) +{ + const char *ch = leaf->format; + int arg = 0; + + while (*ch) { + switch (*ch) { + case 'b': + case 'h': + case 'w': + arg++; + break; /* nothing to destroy */ + case 'L': + cv_leaf_destroy((cv_leaf *)leaf->args[arg++].p); + break; + case 'T': + arg++; /* nothing to destroy */ + break; + case 'S': + yasm_xfree(leaf->args[arg++].p); + break; + default: + yasm_internal_error(N_("unknown leaf format character")); + } + ch++; + } +} + +static unsigned long +cv_leaf_size(const cv_leaf *leaf) +{ + const char *ch = leaf->format; + unsigned long len = 2; /* leaf type */ + unsigned long slen; + int arg = 0; + + while (*ch) { + switch (*ch) { + case 'b': + len++; + arg++; + break; + case 'h': + len += 2; + arg++; + break; + case 'w': + len += 4; + arg++; + break; + case 'L': + len += cv_leaf_size((const cv_leaf *)leaf->args[arg++].p); + break; + case 'T': + len += 4; /* XXX: will be 2 in CV4 */ + arg++; + break; + case 'S': + len += 1; /* XXX: is this 1 or 2? */ + slen = (unsigned long)strlen((const char *)leaf->args[arg++].p); + len += slen <= 0xff ? slen : 0xff; + break; + default: + yasm_internal_error(N_("unknown leaf format character")); + } + ch++; + } + + return len; +} + +static void +cv_leaf_tobytes(const cv_leaf *leaf, yasm_bytecode *bc, yasm_arch *arch, + unsigned char **bufp, yasm_intnum *cval) +{ + unsigned char *buf = *bufp; + const char *ch = leaf->format; + size_t len; + int arg = 0; + + /* leaf type */ + yasm_intnum_set_uint(cval, leaf->type); + yasm_arch_intnum_tobytes(arch, cval, buf, 2, 16, 0, bc, 0); + buf += 2; + + while (*ch) { + switch (*ch) { + case 'b': + YASM_WRITE_8(buf, leaf->args[arg].i); + arg++; + break; + case 'h': + yasm_intnum_set_uint(cval, leaf->args[arg++].i); + yasm_arch_intnum_tobytes(arch, cval, buf, 2, 16, 0, bc, 0); + buf += 2; + break; + case 'w': + yasm_intnum_set_uint(cval, leaf->args[arg++].i); + yasm_arch_intnum_tobytes(arch, cval, buf, 4, 32, 0, bc, 0); + buf += 4; + break; + case 'L': + cv_leaf_tobytes((const cv_leaf *)leaf->args[arg++].p, bc, arch, + &buf, cval); + break; + case 'T': + yasm_intnum_set_uint(cval, + ((const cv_type *)leaf->args[arg++].p)->indx); + yasm_arch_intnum_tobytes(arch, cval, buf, 4, 32, 0, bc, 0); + buf += 4; /* XXX: will be 2 in CV4 */ + break; + case 'S': + len = strlen((const char *)leaf->args[arg].p); + len = len <= 0xff ? len : 0xff; + YASM_WRITE_8(buf, len); + memcpy(buf, (const char *)leaf->args[arg].p, len); + buf += len; + arg++; + break; + default: + yasm_internal_error(N_("unknown leaf format character")); + } + ch++; + } + + *bufp = buf; +} + +static cv_type * +cv_type_create(unsigned long indx) +{ + cv_type *type = yasm_xmalloc(sizeof(cv_type)); + + type->indx = indx; + type->num_leaves = 0; + type->leaves = NULL; + + return type; +} + +static void +cv_type_append_leaf(cv_type *type, /*@keep@*/ cv_leaf *leaf) +{ + type->num_leaves++; + + /* This is inefficient for large numbers of leaves, but that won't happen + * until we add structure support. + */ + type->leaves = yasm_xrealloc(type->leaves, + type->num_leaves*sizeof(cv_leaf *)); + + type->leaves[type->num_leaves-1] = leaf; +} + +static void +cv_type_bc_destroy(void *contents) +{ + cv_type *type = (cv_type *)contents; + size_t i; + + for (i=0; i<type->num_leaves; i++) + cv_leaf_destroy(type->leaves[i]); + if (type->leaves) + yasm_xfree(type->leaves); + yasm_xfree(contents); +} + +static void +cv_type_bc_print(const void *contents, FILE *f, int indent_level) +{ + /* TODO */ +} + +static int +cv_type_bc_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span, + void *add_span_data) +{ + cv_type *type = (cv_type *)bc->contents; + size_t i; + + if (type->indx == CV_FIRST_NONPRIM) + bc->len = 4+2; + else + bc->len = 2; + + for (i=0; i<type->num_leaves; i++) + bc->len += cv_leaf_size(type->leaves[i]); + + /* Pad to multiple of 4 */ + if (bc->len & 0x3) + bc->len += 4-(bc->len & 0x3); + + return 0; +} + +static int +cv_type_bc_tobytes(yasm_bytecode *bc, unsigned char **bufp, + unsigned char *bufstart, void *d, + yasm_output_value_func output_value, + yasm_output_reloc_func output_reloc) +{ + yasm_object *object = yasm_section_get_object(bc->section); + cv_type *type = (cv_type *)bc->contents; + unsigned char *buf = *bufp; + yasm_intnum *cval; + size_t i; + unsigned long reclen = bc->len - 2; + + cval = yasm_intnum_create_uint(4); /* version */ + if (type->indx == CV_FIRST_NONPRIM) { + yasm_arch_intnum_tobytes(object->arch, cval, buf, 4, 32, 0, bc, 1); + buf += 4; + reclen -= 4; + } + + /* Total length of record (following this field) - 2 bytes */ + yasm_intnum_set_uint(cval, reclen); + yasm_arch_intnum_tobytes(object->arch, cval, buf, 2, 16, 0, bc, 1); + buf += 2; + + /* Leaves */ + for (i=0; i<type->num_leaves; i++) + cv_leaf_tobytes(type->leaves[i], bc, object->arch, &buf, cval); + + /* Pad to multiple of 4 */ + switch ((buf-(*bufp)) & 0x3) { + case 3: + YASM_WRITE_8(buf, CV_LF_PAD3); + case 2: + YASM_WRITE_8(buf, CV_LF_PAD2); + case 1: + YASM_WRITE_8(buf, CV_LF_PAD1); + case 0: + break; + } + + *bufp = buf; + + yasm_intnum_destroy(cval); + return 0; +} |