* md5.c, md5.h: Import MD5 from public domain version in CVS source.
* libyasm/Makefile.inc: Attach to libyasm build.
* libyasm.h: Include md5.h.
* coretype.h (yasm_value): Add new section_rel member.
* value.h (yasm_value_init, yasm_value_init_sym): Initialize.
* value.c (yasm_value_output_basic): Don't output if set.
* xdf-objfmt.c (xdf_objfmt_output_value): Likewise.
* elf-objfmt.c (elf_objfmt_output_value): Likewise.
* coff-objfmt.c (coff_objfmt_output_value): Generate SECREL for this.
* coretype.h (YASM_PATHSEP): New define for path separator.
* vc8/config.h, vc/config.h, dj/config.h: Override.
* dbgfmts/codeview: New, adds "cv8" dbgfmt.
* dbgfmts/Makefile.inc: Hook into build.
* coff-objfmt.c: Enable cv8 dbgfmt for win32 and win64. Change a few things
to more closely match MASM output.
(coff_section_data): Add isdebug flag so that section flags are set properly.
(coff_objfmt_secton_switch): Initialize to 0 here.
(coff_objfmt_init_remaining_section): Initialize to 1 and set various section
flags (DATA, DISCARD, READ) if section name starts with ".debug".
(coff_objfmt_output): If non-NULL dbgfmt, set object flags to say line numbers
are included.
* dwarfwin64_testhd.hex: Minor update due to coff_objfmt_output() change.
svn path=/trunk/yasm/; revision=1428
/* $Id$ */\r
\r
#define yasm__splitpath(path, tail) yasm__splitpath_win(path, tail)\r
+#define YASM_PATHSEP '\\'\r
+\r
/* */\r
/* #undef ENABLE_NLS */\r
\r
/* $Id$ */\r
\r
#define yasm__splitpath(path, tail) yasm__splitpath_win(path, tail)\r
+#define YASM_PATHSEP '\\'\r
\r
/* */\r
/* #undef ENABLE_NLS */\r
/* $Id: config.h 1137 2004-09-04 01:24:57Z peter $ */\r
\r
#define yasm__splitpath(path, tail) yasm__splitpath_win(path, tail)\r
+#define YASM_PATHSEP '\\'\r
\r
#define _CRT_SECURE_NO_DEPRECATE 1\r
\r
#endif
#include <libyasm/hamt.h>
#include <libyasm/bitvect.h>
+#include <libyasm/md5.h>
#endif
#endif
libyasm_a_SOURCES += libyasm/hamt.c
libyasm_a_SOURCES += libyasm/intnum.c
libyasm_a_SOURCES += libyasm/linemgr.c
+libyasm_a_SOURCES += libyasm/md5.c
libyasm_a_SOURCES += libyasm/mergesort.c
libyasm_a_SOURCES += libyasm/phash.c
libyasm_a_SOURCES += libyasm/section.c
modinclude_HEADERS += libyasm/intnum.h
modinclude_HEADERS += libyasm/linemgr.h
modinclude_HEADERS += libyasm/listfmt.h
+modinclude_HEADERS += libyasm/md5.h
modinclude_HEADERS += libyasm/module.h
modinclude_HEADERS += libyasm/objfmt.h
modinclude_HEADERS += libyasm/optimizer.h
* is needed to generate special relocations.
*/
unsigned int ip_rel : 1;
+
+ /** Indicates the relative portion of the value should be relocated
+ * relative to its own section start rather than relative to the
+ * section start of the bytecode containing this value. E.g. the value
+ * resulting from the relative portion should be the offset from its
+ * section start. Boolean.
+ */
+ unsigned int section_rel : 1;
} yasm_value;
/** Maximum value of #yasm_value.rshift */
defined (__DJGPP__) || defined (__OS2__) || defined (__CYGWIN__) || \
defined (__CYGWIN32__)
# define yasm__splitpath(path, tail) yasm__splitpath_win(path, tail)
+# ifndef YASM_PATHSEP
+# define YASM_PATHSEP '\\'
+# endif
# else
# define yasm__splitpath(path, tail) yasm__splitpath_unix(path, tail)
+# ifndef YASM_PATHSEP
+# define YASM_PATHSEP '/'
+# endif
# endif
#endif
--- /dev/null
+/*
+ * This code implements the MD5 message-digest algorithm.
+ * The algorithm is due to Ron Rivest. This code was
+ * written by Colin Plumb in 1993, no copyright is claimed.
+ * This code is in the public domain; do with it what you wish.
+ *
+ * Equivalent code is available from RSA Data Security, Inc.
+ * This code has been tested against that, and is equivalent,
+ * except that you don't need to include two pages of legalese
+ * with every copy.
+ *
+ * To compute the message digest of a chunk of bytes, declare an
+ * MD5Context structure, pass it to MD5Init, call MD5Update as
+ * needed on buffers full of bytes, and then call MD5Final, which
+ * will fill a supplied 16-byte array with the digest.
+ */
+
+/* This code was modified in 1997 by Jim Kingdon of Cyclic Software to
+ not require an integer type which is exactly 32 bits. This work
+ draws on the changes for the same purpose by Tatu Ylonen
+ <ylo@cs.hut.fi> as part of SSH, but since I didn't actually use
+ that code, there is no copyright issue. I hereby disclaim
+ copyright in any changes I have made; this code remains in the
+ public domain. */
+
+/* Note regarding cvs_* namespace: this avoids potential conflicts
+ with libraries such as some versions of Kerberos. No particular
+ need to worry about whether the system supplies an MD5 library, as
+ this file is only about 3k of object code. */
+
+#include <util.h>
+/*@unused@*/ RCSID("$Id$");
+
+#include "md5.h"
+
+/* Little-endian byte-swapping routines. Note that these do not
+ depend on the size of datatypes such as cvs_uint32, nor do they require
+ us to detect the endianness of the machine we are running on. It
+ is possible they should be macros for speed, but I would be
+ surprised if they were a performance bottleneck for MD5. */
+
+static unsigned long
+getu32(const unsigned char *addr)
+{
+ return (((((unsigned long)addr[3] << 8) | addr[2]) << 8)
+ | addr[1]) << 8 | addr[0];
+}
+
+static void
+putu32(unsigned long data, unsigned char *addr)
+{
+ addr[0] = (unsigned char)data;
+ addr[1] = (unsigned char)(data >> 8);
+ addr[2] = (unsigned char)(data >> 16);
+ addr[3] = (unsigned char)(data >> 24);
+}
+
+/*
+ * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
+ * initialization constants.
+ */
+void
+yasm_md5_init(yasm_md5_context *ctx)
+{
+ ctx->buf[0] = 0x67452301;
+ ctx->buf[1] = 0xefcdab89;
+ ctx->buf[2] = 0x98badcfe;
+ ctx->buf[3] = 0x10325476;
+
+ ctx->bits[0] = 0;
+ ctx->bits[1] = 0;
+}
+
+/*
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+void
+yasm_md5_update(yasm_md5_context *ctx, unsigned char const *buf,
+ unsigned len)
+{
+ unsigned long t;
+
+ /* Update bitcount */
+
+ t = ctx->bits[0];
+ if ((ctx->bits[0] = (t + ((unsigned long)len << 3)) & 0xffffffff) < t)
+ ctx->bits[1]++; /* Carry from low to high */
+ ctx->bits[1] += len >> 29;
+
+ t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
+
+ /* Handle any leading odd-sized chunks */
+
+ if ( t ) {
+ unsigned char *p = ctx->in + t;
+
+ t = 64-t;
+ if (len < t) {
+ memcpy(p, buf, len);
+ return;
+ }
+ memcpy(p, buf, t);
+ yasm_md5_transform (ctx->buf, ctx->in);
+ buf += t;
+ len -= t;
+ }
+
+ /* Process data in 64-byte chunks */
+
+ while (len >= 64) {
+ memcpy(ctx->in, buf, 64);
+ yasm_md5_transform (ctx->buf, ctx->in);
+ buf += 64;
+ len -= 64;
+ }
+
+ /* Handle any remaining bytes of data. */
+
+ memcpy(ctx->in, buf, len);
+}
+
+/*
+ * Final wrapup - pad to 64-byte boundary with the bit pattern
+ * 1 0* (64-bit count of bits processed, MSB-first)
+ */
+void
+yasm_md5_final(unsigned char digest[16], yasm_md5_context *ctx)
+{
+ unsigned count;
+ unsigned char *p;
+
+ /* Compute number of bytes mod 64 */
+ count = (ctx->bits[0] >> 3) & 0x3F;
+
+ /* Set the first char of padding to 0x80. This is safe since there is
+ always at least one byte free */
+ p = ctx->in + count;
+ *p++ = 0x80;
+
+ /* Bytes of padding needed to make 64 bytes */
+ count = 64 - 1 - count;
+
+ /* Pad out to 56 mod 64 */
+ if (count < 8) {
+ /* Two lots of padding: Pad the first block to 64 bytes */
+ memset(p, 0, count);
+ yasm_md5_transform (ctx->buf, ctx->in);
+
+ /* Now fill the next block with 56 bytes */
+ memset(ctx->in, 0, 56);
+ } else {
+ /* Pad block to 56 bytes */
+ memset(p, 0, count-8);
+ }
+
+ /* Append length in bits and transform */
+ putu32(ctx->bits[0], ctx->in + 56);
+ putu32(ctx->bits[1], ctx->in + 60);
+
+ yasm_md5_transform (ctx->buf, ctx->in);
+ putu32(ctx->buf[0], digest);
+ putu32(ctx->buf[1], digest + 4);
+ putu32(ctx->buf[2], digest + 8);
+ putu32(ctx->buf[3], digest + 12);
+ memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */
+}
+
+#ifndef ASM_MD5
+
+/* The four core functions - F1 is optimized somewhat */
+
+/* #define F1(x, y, z) (x & y | ~x & z) */
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+
+/* This is the central step in the MD5 algorithm. */
+#define MD5STEP(f, w, x, y, z, data, s) \
+ ( w += f(x, y, z) + data, w &= 0xffffffff, w = w<<s | w>>(32-s), w += x )
+
+/*
+ * The core of the MD5 algorithm, this alters an existing MD5 hash to
+ * reflect the addition of 16 longwords of new data. MD5Update blocks
+ * the data and converts bytes into longwords for this routine.
+ */
+void
+yasm_md5_transform(unsigned long buf[4], const unsigned char inraw[64])
+{
+ register unsigned long a, b, c, d;
+ unsigned long in[16];
+ int i;
+
+ for (i = 0; i < 16; ++i)
+ in[i] = getu32 (inraw + 4 * i);
+
+ a = buf[0];
+ b = buf[1];
+ c = buf[2];
+ d = buf[3];
+
+ MD5STEP(F1, a, b, c, d, in[ 0]+0xd76aa478, 7);
+ MD5STEP(F1, d, a, b, c, in[ 1]+0xe8c7b756, 12);
+ MD5STEP(F1, c, d, a, b, in[ 2]+0x242070db, 17);
+ MD5STEP(F1, b, c, d, a, in[ 3]+0xc1bdceee, 22);
+ MD5STEP(F1, a, b, c, d, in[ 4]+0xf57c0faf, 7);
+ MD5STEP(F1, d, a, b, c, in[ 5]+0x4787c62a, 12);
+ MD5STEP(F1, c, d, a, b, in[ 6]+0xa8304613, 17);
+ MD5STEP(F1, b, c, d, a, in[ 7]+0xfd469501, 22);
+ MD5STEP(F1, a, b, c, d, in[ 8]+0x698098d8, 7);
+ MD5STEP(F1, d, a, b, c, in[ 9]+0x8b44f7af, 12);
+ MD5STEP(F1, c, d, a, b, in[10]+0xffff5bb1, 17);
+ MD5STEP(F1, b, c, d, a, in[11]+0x895cd7be, 22);
+ MD5STEP(F1, a, b, c, d, in[12]+0x6b901122, 7);
+ MD5STEP(F1, d, a, b, c, in[13]+0xfd987193, 12);
+ MD5STEP(F1, c, d, a, b, in[14]+0xa679438e, 17);
+ MD5STEP(F1, b, c, d, a, in[15]+0x49b40821, 22);
+
+ MD5STEP(F2, a, b, c, d, in[ 1]+0xf61e2562, 5);
+ MD5STEP(F2, d, a, b, c, in[ 6]+0xc040b340, 9);
+ MD5STEP(F2, c, d, a, b, in[11]+0x265e5a51, 14);
+ MD5STEP(F2, b, c, d, a, in[ 0]+0xe9b6c7aa, 20);
+ MD5STEP(F2, a, b, c, d, in[ 5]+0xd62f105d, 5);
+ MD5STEP(F2, d, a, b, c, in[10]+0x02441453, 9);
+ MD5STEP(F2, c, d, a, b, in[15]+0xd8a1e681, 14);
+ MD5STEP(F2, b, c, d, a, in[ 4]+0xe7d3fbc8, 20);
+ MD5STEP(F2, a, b, c, d, in[ 9]+0x21e1cde6, 5);
+ MD5STEP(F2, d, a, b, c, in[14]+0xc33707d6, 9);
+ MD5STEP(F2, c, d, a, b, in[ 3]+0xf4d50d87, 14);
+ MD5STEP(F2, b, c, d, a, in[ 8]+0x455a14ed, 20);
+ MD5STEP(F2, a, b, c, d, in[13]+0xa9e3e905, 5);
+ MD5STEP(F2, d, a, b, c, in[ 2]+0xfcefa3f8, 9);
+ MD5STEP(F2, c, d, a, b, in[ 7]+0x676f02d9, 14);
+ MD5STEP(F2, b, c, d, a, in[12]+0x8d2a4c8a, 20);
+
+ MD5STEP(F3, a, b, c, d, in[ 5]+0xfffa3942, 4);
+ MD5STEP(F3, d, a, b, c, in[ 8]+0x8771f681, 11);
+ MD5STEP(F3, c, d, a, b, in[11]+0x6d9d6122, 16);
+ MD5STEP(F3, b, c, d, a, in[14]+0xfde5380c, 23);
+ MD5STEP(F3, a, b, c, d, in[ 1]+0xa4beea44, 4);
+ MD5STEP(F3, d, a, b, c, in[ 4]+0x4bdecfa9, 11);
+ MD5STEP(F3, c, d, a, b, in[ 7]+0xf6bb4b60, 16);
+ MD5STEP(F3, b, c, d, a, in[10]+0xbebfbc70, 23);
+ MD5STEP(F3, a, b, c, d, in[13]+0x289b7ec6, 4);
+ MD5STEP(F3, d, a, b, c, in[ 0]+0xeaa127fa, 11);
+ MD5STEP(F3, c, d, a, b, in[ 3]+0xd4ef3085, 16);
+ MD5STEP(F3, b, c, d, a, in[ 6]+0x04881d05, 23);
+ MD5STEP(F3, a, b, c, d, in[ 9]+0xd9d4d039, 4);
+ MD5STEP(F3, d, a, b, c, in[12]+0xe6db99e5, 11);
+ MD5STEP(F3, c, d, a, b, in[15]+0x1fa27cf8, 16);
+ MD5STEP(F3, b, c, d, a, in[ 2]+0xc4ac5665, 23);
+
+ MD5STEP(F4, a, b, c, d, in[ 0]+0xf4292244, 6);
+ MD5STEP(F4, d, a, b, c, in[ 7]+0x432aff97, 10);
+ MD5STEP(F4, c, d, a, b, in[14]+0xab9423a7, 15);
+ MD5STEP(F4, b, c, d, a, in[ 5]+0xfc93a039, 21);
+ MD5STEP(F4, a, b, c, d, in[12]+0x655b59c3, 6);
+ MD5STEP(F4, d, a, b, c, in[ 3]+0x8f0ccc92, 10);
+ MD5STEP(F4, c, d, a, b, in[10]+0xffeff47d, 15);
+ MD5STEP(F4, b, c, d, a, in[ 1]+0x85845dd1, 21);
+ MD5STEP(F4, a, b, c, d, in[ 8]+0x6fa87e4f, 6);
+ MD5STEP(F4, d, a, b, c, in[15]+0xfe2ce6e0, 10);
+ MD5STEP(F4, c, d, a, b, in[ 6]+0xa3014314, 15);
+ MD5STEP(F4, b, c, d, a, in[13]+0x4e0811a1, 21);
+ MD5STEP(F4, a, b, c, d, in[ 4]+0xf7537e82, 6);
+ MD5STEP(F4, d, a, b, c, in[11]+0xbd3af235, 10);
+ MD5STEP(F4, c, d, a, b, in[ 2]+0x2ad7d2bb, 15);
+ MD5STEP(F4, b, c, d, a, in[ 9]+0xeb86d391, 21);
+
+ buf[0] += a;
+ buf[1] += b;
+ buf[2] += c;
+ buf[3] += d;
+}
+#endif
+
+#ifdef TEST
+/* Simple test program. Can use it to manually run the tests from
+ RFC1321 for example. */
+#include <stdio.h>
+
+int
+main (int argc, char **argv)
+{
+ yasm_md5_context context;
+ unsigned char checksum[16];
+ int i;
+ int j;
+
+ if (argc < 2)
+ {
+ fprintf (stderr, "usage: %s string-to-hash\n", argv[0]);
+ exit (1);
+ }
+ for (j = 1; j < argc; ++j)
+ {
+ printf ("MD5 (\"%s\") = ", argv[j]);
+ yasm_md5_init (&context);
+ yasm_md5_update (&context, argv[j], strlen (argv[j]));
+ yasm_md5_final (checksum, &context);
+ for (i = 0; i < 16; i++)
+ {
+ printf ("%02x", (unsigned int) checksum[i]);
+ }
+ printf ("\n");
+ }
+ return 0;
+}
+#endif /* TEST */
--- /dev/null
+/* See md5.c for explanation and copyright information. */
+
+/*
+ * $Id$
+ */
+
+#ifndef YASM_MD5_H
+#define YASM_MD5_H
+
+/* Unlike previous versions of this code, uint32 need not be exactly
+ 32 bits, merely 32 bits or more. Choosing a data type which is 32
+ bits instead of 64 is not important; speed is considerably more
+ important. ANSI guarantees that "unsigned long" will be big enough,
+ and always using it seems to have few disadvantages. */
+
+typedef struct yasm_md5_context {
+ unsigned long buf[4];
+ unsigned long bits[2];
+ unsigned char in[64];
+} yasm_md5_context;
+
+void yasm_md5_init(yasm_md5_context *context);
+void yasm_md5_update(yasm_md5_context *context, unsigned char const *buf,
+ unsigned len);
+void yasm_md5_final(unsigned char digest[16], yasm_md5_context *context);
+void yasm_md5_transform(unsigned long buf[4], const unsigned char in[64]);
+
+#endif /* !YASM_MD5_H */
unsigned long dist;
sym_local = yasm_symrec_get_label(value->rel, &rel_prevbc);
- if (value->wrt || value->seg_of || !sym_local)
+ if (value->wrt || value->seg_of || value->section_rel || !sym_local)
return 0; /* we can't handle SEG, WRT, or external symbols */
if (rel_prevbc->section != bc->section)
return 0; /* not in this section */
(value)->rshift = 0; \
(value)->curpos_rel = 0; \
(value)->ip_rel = 0; \
+ (value)->section_rel = 0; \
} while(0)
#define yasm_value_init_sym(value, sym) \
(value)->rshift = 0; \
(value)->curpos_rel = 0; \
(value)->ip_rel = 0; \
+ (value)->section_rel = 0; \
} while(0)
#define yasm_value_delete(value) \
# $Id$
+EXTRA_DIST += modules/dbgfmts/codeview/Makefile.inc
EXTRA_DIST += modules/dbgfmts/dwarf2/Makefile.inc
EXTRA_DIST += modules/dbgfmts/null/Makefile.inc
EXTRA_DIST += modules/dbgfmts/stabs/Makefile.inc
+include modules/dbgfmts/codeview/Makefile.inc
include modules/dbgfmts/dwarf2/Makefile.inc
include modules/dbgfmts/null/Makefile.inc
include modules/dbgfmts/stabs/Makefile.inc
--- /dev/null
+# $Id$
+
+libyasm_a_SOURCES += modules/dbgfmts/codeview/cv-dbgfmt.h
+libyasm_a_SOURCES += modules/dbgfmts/codeview/cv-dbgfmt.c
+libyasm_a_SOURCES += modules/dbgfmts/codeview/cv-symline.c
+libyasm_a_SOURCES += modules/dbgfmts/codeview/cv-type.c
+
+YASM_MODULES += dbgfmt_cv8
+
+EXTRA_DIST += modules/dbgfmts/codeview/cv8.txt
+
+#EXTRA_DIST += modules/dbgfmts/codeview/tests/Makefile.inc
+#include modules/dbgfmts/codeview/tests/Makefile.inc
--- /dev/null
+/*
+ * CodeView debugging formats implementation for Yasm
+ *
+ * Copyright (C) 2006 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>
+/*@unused@*/ RCSID("$Id$");
+
+#define YASM_LIB_INTERNAL
+#define YASM_BC_INTERNAL
+#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_objfmt *of, yasm_arch *a,
+ 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->object = object;
+ dbgfmt_cv->symtab = yasm_object_get_symtab(object);
+ dbgfmt_cv->linemap = yasm_object_get_linemap(object);
+ dbgfmt_cv->arch = a;
+
+ 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, yasm_objfmt *of, yasm_arch *a)
+{
+ return cv_dbgfmt_create(object, of, a, &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 = precbc ? precbc->offset + precbc->len : 0;
+ yasm_section_bcs_append(sect, bc);
+ return precbc;
+}
+
+static void
+cv_dbgfmt_generate(yasm_dbgfmt *dbgfmt)
+{
+ yasm_dbgfmt_cv *dbgfmt_cv = (yasm_dbgfmt_cv *)dbgfmt;
+
+ yasm_cv__generate_symline(dbgfmt_cv);
+
+ yasm_cv__generate_type(dbgfmt_cv);
+}
+
+static int
+cv_dbgfmt_directive(yasm_dbgfmt *dbgfmt, const char *name,
+ yasm_section *sect, yasm_valparamhead *valparams,
+ unsigned long line)
+{
+ return 1; /* TODO */
+}
+
+/* Define dbgfmt structure -- see dbgfmt.h for details */
+yasm_dbgfmt_module yasm_cv8_LTX_dbgfmt = {
+ "CodeView debugging format for VC8",
+ "cv8",
+ cv8_dbgfmt_create,
+ cv_dbgfmt_destroy,
+ cv_dbgfmt_directive,
+ cv_dbgfmt_generate
+};
--- /dev/null
+/* $Id$
+ * CodeView debugging formats implementation for Yasm
+ *
+ * Copyright (C) 2006 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 */
+
+ yasm_object *object;
+ yasm_symtab *symtab;
+ yasm_linemap *linemap;
+ yasm_arch *arch;
+
+ 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_dbgfmt_cv *dbgfmt_cv);
+
+/* Type functions */
+yasm_section *yasm_cv__generate_type(yasm_dbgfmt_cv *dbgfmt_cv);
+
+#endif
--- /dev/null
+/*
+ * CodeView debugging format - symbol and line information
+ *
+ * Copyright (C) 2006 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.
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#undef HAVE_CONFIG_H
+#endif
+
+/* Need either unistd.h or direct.h (on Windows) to prototype getcwd() */
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#elif defined(WIN32) || defined(_WIN32)
+#include <direct.h>
+#endif
+
+#include <util.h>
+/*@unused@*/ RCSID("$Id$");
+
+#define YASM_LIB_INTERNAL
+#define YASM_BC_INTERNAL
+#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 {
+ yasm_dbgfmt_cv *dbgfmt_cv;
+ 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 {
+ yasm_dbgfmt_cv *dbgfmt_cv;
+ 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;
+
+typedef struct cv8_lineinfo {
+ STAILQ_ENTRY(cv8_lineinfo) link;
+ yasm_dbgfmt_cv *dbgfmt_cv;
+ 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;
+ STAILQ_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 {
+ yasm_dbgfmt_cv *dbgfmt_cv;
+ 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 yasm_bc_resolve_flags cv8_symhead_bc_resolve
+ (yasm_bytecode *bc, int save, yasm_calc_bc_dist_func calc_bc_dist);
+static int cv8_symhead_bc_tobytes
+ (yasm_bytecode *bc, unsigned char **bufp, 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 yasm_bc_resolve_flags cv8_fileinfo_bc_resolve
+ (yasm_bytecode *bc, int save, yasm_calc_bc_dist_func calc_bc_dist);
+static int cv8_fileinfo_bc_tobytes
+ (yasm_bytecode *bc, unsigned char **bufp, 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 yasm_bc_resolve_flags cv8_lineinfo_bc_resolve
+ (yasm_bytecode *bc, int save, yasm_calc_bc_dist_func calc_bc_dist);
+static int cv8_lineinfo_bc_tobytes
+ (yasm_bytecode *bc, unsigned char **bufp, 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 yasm_bc_resolve_flags cv_sym_bc_resolve
+ (yasm_bytecode *bc, int save, yasm_calc_bc_dist_func calc_bc_dist);
+static int cv_sym_bc_tobytes
+ (yasm_bytecode *bc, unsigned char **bufp, 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,
+ cv8_symhead_bc_resolve,
+ cv8_symhead_bc_tobytes
+};
+
+static const yasm_bytecode_callback cv8_fileinfo_bc_callback = {
+ cv8_fileinfo_bc_destroy,
+ cv8_fileinfo_bc_print,
+ yasm_bc_finalize_common,
+ cv8_fileinfo_bc_resolve,
+ cv8_fileinfo_bc_tobytes
+};
+
+static const yasm_bytecode_callback cv8_lineinfo_bc_callback = {
+ cv8_lineinfo_bc_destroy,
+ cv8_lineinfo_bc_print,
+ yasm_bc_finalize_common,
+ cv8_lineinfo_bc_resolve,
+ cv8_lineinfo_bc_tobytes
+};
+
+static const yasm_bytecode_callback cv_sym_bc_callback = {
+ cv_sym_bc_destroy,
+ cv_sym_bc_print,
+ yasm_bc_finalize_common,
+ cv_sym_bc_resolve,
+ cv_sym_bc_tobytes
+};
+
+static cv8_symhead *cv8_add_symhead(yasm_dbgfmt_cv *dbgfmt_cv,
+ 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_dbgfmt_cv *dbgfmt_cv, 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_dbgfmt_cv *dbgfmt_cv, yasm_section *sect,
+ /*@keep@*/ char *objname)
+{
+ yasm_bytecode *bc;
+ cv_sym *cvs = yasm_xmalloc(sizeof(cv_sym));
+ cvs->dbgfmt_cv = dbgfmt_cv;
+ 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_dbgfmt_cv *dbgfmt_cv, yasm_section *sect,
+ /*@keep@*/ char *creator)
+{
+ yasm_bytecode *bc;
+ cv_sym *cvs = yasm_xmalloc(sizeof(cv_sym));
+ cvs->dbgfmt_cv = dbgfmt_cv;
+ cvs->type = CV8_S_COMPILE;
+ cvs->format = "wwwwZ";
+ cvs->args[0].i = 3; /* language (3=Masm) */
+
+ /* target processor; 0xD0 = AMD64 */
+ if (strcmp(yasm_arch_keyword(dbgfmt_cv->arch), "x86") == 0) {
+ if (strcmp(yasm_arch_get_machine(dbgfmt_cv->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 */
+
+ 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_dbgfmt_cv *dbgfmt_cv, yasm_section *sect,
+ yasm_symrec *sym)
+{
+ yasm_bytecode *bc;
+ cv_sym *cvs = yasm_xmalloc(sizeof(cv_sym));
+ cvs->dbgfmt_cv = dbgfmt_cv;
+ 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_dbgfmt_cv *dbgfmt_cv, yasm_section *sect,
+ unsigned long type, yasm_symrec *sym, int is_global)
+{
+ yasm_bytecode *bc;
+ cv_sym *cvs = yasm_xmalloc(sizeof(cv_sym));
+ cvs->dbgfmt_cv = dbgfmt_cv;
+ 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 /*@only@*/ char *
+cv_make_pathname(const char *filename)
+{
+ char *curdir, *pathname;
+ static const char pathsep[2] = { YASM_PATHSEP, '\0' };
+
+ curdir = getcwd(NULL, 0);
+
+ pathname = yasm_xmalloc(strlen(curdir) + strlen(filename) + 2);
+ strcpy(pathname, curdir);
+ strcat(pathname, pathsep);
+ strcat(pathname, filename);
+
+ free(curdir);
+
+ return pathname;
+}
+
+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, 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 = cv_make_pathname(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, 0);
+ yasm_bc_finalize(bc, yasm_cv__append_bc(sect, bc));
+ yasm_bc_resolve(bc, 0, NULL);
+ return bc;
+}
+
+typedef struct cv_line_info {
+ yasm_section *debug_symline;
+ yasm_dbgfmt_cv *dbgfmt_cv;
+ unsigned int num_lineinfos;
+ STAILQ_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);
+ cv8_lineset *ls;
+
+ if (nextbc && bc->offset == nextbc->offset)
+ return 0;
+
+ yasm_linemap_lookup(dbgfmt_cv->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];
+
+ /* first see if we already have a lineinfo that is for this section and
+ * filename
+ */
+ STAILQ_FOREACH(info->cv8_cur_li, &info->cv8_lineinfos, link) {
+ if (sect == info->cv8_cur_li->sect
+ && strcmp(filename, info->cv8_cur_li->fn->filename) == 0)
+ break;
+ }
+
+ if (info->cv8_cur_li) {
+ info->cv8_cur_ls = STAILQ_LAST(&info->cv8_cur_li->linesets,
+ cv8_lineset, link);
+ goto done; /* found one */
+ }
+
+ /* Nope; 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->dbgfmt_cv = dbgfmt_cv;
+ info->cv8_cur_li->fn = &dbgfmt_cv->filenames[i];
+ info->cv8_cur_li->sect = 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(dbgfmt_cv->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;
+ }
+done:
+
+ /* 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;
+ yasm_dbgfmt_cv *dbgfmt_cv = info->dbgfmt_cv;
+ /*@null@*/ yasm_bytecode *bc;
+ /*cv_line_state state;*/
+ unsigned long addr_delta;
+
+ 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, cv_generate_line_bc);
+
+ return 0;
+}
+
+static int
+cv_generate_filename(const char *filename, void *d)
+{
+ yasm_dbgfmt_cv *dbgfmt_cv = (yasm_dbgfmt_cv *)d;
+ cv_dbgfmt_add_file(dbgfmt_cv, 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;
+ unsigned long type;
+
+ /* only care about labels (for now) */
+ if (!yasm_symrec_get_label(sym, &precbc))
+ return 0;
+
+ /* TODO: add data types */
+ if (yasm_section_is_code(yasm_bc_get_section(precbc)))
+ cv8_add_sym_label(info->dbgfmt_cv, info->debug_symline, sym);
+ else
+ cv8_add_sym_data(info->dbgfmt_cv, info->debug_symline, 0, sym,
+ yasm_symrec_get_visibility(sym) & YASM_SYM_GLOBAL?1:0);
+
+ return 0;
+}
+
+yasm_section *
+yasm_cv__generate_symline(yasm_dbgfmt_cv *dbgfmt_cv)
+{
+ 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(dbgfmt_cv->linemap, dbgfmt_cv,
+ cv_generate_filename);
+
+ info.dbgfmt_cv = dbgfmt_cv;
+ info.debug_symline = yasm_object_get_general(dbgfmt_cv->object,
+ ".debug$S", 0, 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(dbgfmt_cv, 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(0, N_("codeview file number %d unassigned"), i+1);
+ 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_resolve(bc, 0, NULL);
+
+ /* source file info table */
+ head = cv8_add_symhead(dbgfmt_cv, 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(dbgfmt_cv, 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(dbgfmt_cv->object, (void *)&info,
+ cv_generate_line_section);
+
+ /* Output line numbers for sections */
+ STAILQ_FOREACH(li, &info.cv8_lineinfos, link) {
+ head = cv8_add_symhead(dbgfmt_cv, info.debug_symline, CV8_LINE_NUMS,
+ 0);
+ bc = yasm_bc_create_common(&cv8_lineinfo_bc_callback, li, 0);
+ bc->len = 24+li->num_linenums*8;
+ yasm_cv__append_bc(info.debug_symline, bc);
+ cv8_set_symhead_end(head, yasm_section_bcs_last(info.debug_symline));
+ }
+
+ /* Already aligned 4 */
+
+ /* Output debugging symbols */
+ head = cv8_add_symhead(dbgfmt_cv, info.debug_symline, CV8_DEBUG_SYMS, 0);
+ /* add object and compile flag first */
+ cv8_add_sym_objname(dbgfmt_cv, info.debug_symline,
+ cv_make_pathname(yasm_object_get_object_fn(dbgfmt_cv->object)));
+ cv8_add_sym_compile(dbgfmt_cv, info.debug_symline,
+ yasm__xstrdup(PACKAGE_STRING));
+ /* then iterate through symbol table */
+ yasm_symtab_traverse(dbgfmt_cv->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_resolve(bc, 0, 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);
+ val.section_rel = 1;
+ output_value(&val, *bufp, 4, 32, 0, off, bc, 0, d);
+ *bufp += 4;
+
+ /* section index */
+ yasm_value_init_sym(&val, sym);
+ val.seg_of = 1;
+ output_value(&val, *bufp, 2, 16, 0, off+4, bc, 0, d);
+ *bufp += 2;
+}
+
+static cv8_symhead *
+cv8_add_symhead(yasm_dbgfmt_cv *dbgfmt_cv, yasm_section *sect,
+ unsigned long type, int first)
+{
+ cv8_symhead *head;
+ yasm_bytecode *bc;
+
+ head = yasm_xmalloc(sizeof(cv8_symhead));
+ head->dbgfmt_cv = dbgfmt_cv;
+ 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 yasm_bc_resolve_flags
+cv8_symhead_bc_resolve(yasm_bytecode *bc, int save,
+ yasm_calc_bc_dist_func calc_bc_dist)
+{
+ yasm_internal_error(N_("tried to resolve a codeview symhead bytecode"));
+ /*@notreached@*/
+ return YASM_BC_RESOLVE_MIN_LEN;
+}
+
+static int
+cv8_symhead_bc_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
+ yasm_output_value_func output_value,
+ yasm_output_reloc_func output_reloc)
+{
+ cv8_symhead *head = (cv8_symhead *)bc->contents;
+ yasm_dbgfmt_cv *dbgfmt_cv = head->dbgfmt_cv;
+ 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(dbgfmt_cv->arch, cval, buf, 4, 32, 0, bc, 0,
+ 0);
+ buf += 4;
+ }
+
+ /* Type contained - 4 bytes */
+ yasm_intnum_set_uint(cval, head->type);
+ yasm_arch_intnum_tobytes(dbgfmt_cv->arch, cval, buf, 4, 32, 0, bc, 0, 0);
+ buf += 4;
+
+ /* Total length of info (following this field) - 4 bytes */
+ yasm_intnum_set_uint(cval, bc->len);
+ intn = yasm_common_calc_bc_dist(head->start_prevbc, head->end_prevbc);
+ yasm_intnum_calc(intn, YASM_EXPR_SUB, cval, bc->line);
+ yasm_arch_intnum_tobytes(dbgfmt_cv->arch, intn, buf, 4, 32, 0, bc, 0, 0);
+ buf += 4;
+ yasm_intnum_destroy(intn);
+
+ *bufp = buf;
+
+ yasm_intnum_destroy(cval);
+ return 0;
+}
+
+static yasm_bytecode *
+cv8_add_fileinfo(yasm_dbgfmt_cv *dbgfmt_cv, yasm_section *sect,
+ const cv_filename *fn)
+{
+ cv8_fileinfo *fi;
+ yasm_bytecode *bc;
+
+ fi = yasm_xmalloc(sizeof(cv8_fileinfo));
+ fi->dbgfmt_cv = dbgfmt_cv;
+ 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 yasm_bc_resolve_flags
+cv8_fileinfo_bc_resolve(yasm_bytecode *bc, int save,
+ yasm_calc_bc_dist_func calc_bc_dist)
+{
+ yasm_internal_error(N_("tried to resolve a codeview fileinfo bytecode"));
+ /*@notreached@*/
+ return YASM_BC_RESOLVE_MIN_LEN;
+}
+
+static int
+cv8_fileinfo_bc_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
+ yasm_output_value_func output_value,
+ yasm_output_reloc_func output_reloc)
+{
+ cv8_fileinfo *fi = (cv8_fileinfo *)bc->contents;
+ yasm_dbgfmt_cv *dbgfmt_cv = fi->dbgfmt_cv;
+ unsigned char *buf = *bufp;
+ yasm_intnum *intn, *cval;
+ int i;
+
+ /* Offset in filename string table */
+ cval = yasm_intnum_create_uint(fi->fn->str_off);
+ yasm_arch_intnum_tobytes(dbgfmt_cv->arch, cval, buf, 4, 32, 0, bc, 0, 0);
+ buf += 4;
+
+ /* Checksum type/length */
+ yasm_intnum_set_uint(cval, 0x0110);
+ yasm_arch_intnum_tobytes(dbgfmt_cv->arch, cval, buf, 2, 16, 0, bc, 0, 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 yasm_bc_resolve_flags
+cv8_lineinfo_bc_resolve(yasm_bytecode *bc, int save,
+ yasm_calc_bc_dist_func calc_bc_dist)
+{
+ yasm_internal_error(N_("tried to resolve a codeview linehead bytecode"));
+ /*@notreached@*/
+ return YASM_BC_RESOLVE_MIN_LEN;
+}
+
+static int
+cv8_lineinfo_bc_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
+ yasm_output_value_func output_value,
+ yasm_output_reloc_func output_reloc)
+{
+ cv8_lineinfo *li = (cv8_lineinfo *)bc->contents;
+ yasm_dbgfmt_cv *dbgfmt_cv = li->dbgfmt_cv;
+ unsigned char *buf = *bufp;
+ yasm_intnum *cval;
+ unsigned long i;
+ cv8_lineset *ls;
+
+ /* start offset and section */
+ cv_out_sym(li->sectsym, 0, 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_common_calc_bc_dist(yasm_section_bcs_first(li->sect),
+ yasm_section_bcs_last(li->sect));
+ yasm_arch_intnum_tobytes(dbgfmt_cv->arch, cval, buf, 4, 32, 0, bc, 0, 0);
+ buf += 4;
+
+ /* Offset of source file in info table */
+ yasm_intnum_set_uint(cval, li->fn->info_off);
+ yasm_arch_intnum_tobytes(dbgfmt_cv->arch, cval, buf, 4, 32, 0, bc, 0, 0);
+ buf += 4;
+
+ /* Number of line number pairs */
+ yasm_intnum_set_uint(cval, li->num_linenums);
+ yasm_arch_intnum_tobytes(dbgfmt_cv->arch, cval, buf, 4, 32, 0, bc, 0, 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(dbgfmt_cv->arch, cval, buf, 4, 32, 0, bc, 0, 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(dbgfmt_cv->arch, cval, buf, 4, 32, 0, bc,
+ 0, 0);
+ buf += 4;
+
+ /* line number in file */
+ yasm_intnum_set_uint(cval, ls->pairs[j].line);
+ yasm_arch_intnum_tobytes(dbgfmt_cv->arch, cval, buf, 4, 32, 0, bc,
+ 0, 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 = strlen((const char *)cvs->args[arg++].p);
+ len += slen <= 0xff ? slen : 0xff;
+ break;
+ case 'Z':
+ len += 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 yasm_bc_resolve_flags
+cv_sym_bc_resolve(yasm_bytecode *bc, int save,
+ yasm_calc_bc_dist_func calc_bc_dist)
+{
+ yasm_internal_error(N_("tried to resolve a codeview sym bytecode"));
+ /*@notreached@*/
+ return YASM_BC_RESOLVE_MIN_LEN;
+}
+
+static int
+cv_sym_bc_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
+ yasm_output_value_func output_value,
+ yasm_output_reloc_func output_reloc)
+{
+ cv_sym *cvs = (cv_sym *)bc->contents;
+ yasm_dbgfmt_cv *dbgfmt_cv = cvs->dbgfmt_cv;
+ 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(dbgfmt_cv->arch, cval, buf, 2, 16, 0, bc, 1, 0);
+ buf += 2;
+
+ /* Type contained - 2 bytes */
+ yasm_intnum_set_uint(cval, cvs->type);
+ yasm_arch_intnum_tobytes(dbgfmt_cv->arch, cval, buf, 2, 16, 0, bc, 0, 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(dbgfmt_cv->arch, cval, buf, 2, 16, 0,
+ bc, 0, 0);
+ buf += 2;
+ break;
+ case 'w':
+ yasm_intnum_set_uint(cval, cvs->args[arg++].i);
+ yasm_arch_intnum_tobytes(dbgfmt_cv->arch, cval, buf, 4, 32, 0,
+ bc, 0, 0);
+ buf += 4;
+ break;
+ case 'Y':
+ cv_out_sym((yasm_symrec *)cvs->args[arg++].p, 4, bc, &buf, d,
+ output_value);
+ break;
+ case 'T':
+ yasm_intnum_set_uint(cval, cvs->args[arg++].i);
+ yasm_arch_intnum_tobytes(dbgfmt_cv->arch, cval, buf, 4, 32, 0,
+ bc, 0, 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;
+}
--- /dev/null
+/*
+ * CodeView debugging format - type information
+ *
+ * Copyright (C) 2006 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>
+/*@unused@*/ RCSID("$Id$");
+
+#define YASM_LIB_INTERNAL
+#define YASM_BC_INTERNAL
+#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_PFBOOL32 = 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 {
+ yasm_dbgfmt_cv *dbgfmt_cv;
+ 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 yasm_bc_resolve_flags cv_type_bc_resolve
+ (yasm_bytecode *bc, int save, yasm_calc_bc_dist_func calc_bc_dist);
+static int cv_type_bc_tobytes
+ (yasm_bytecode *bc, unsigned char **bufp, 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,
+ cv_type_bc_resolve,
+ cv_type_bc_tobytes
+};
+
+static cv_type *cv_type_create(yasm_dbgfmt_cv *dbgfmt_cv, 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_dbgfmt_cv *dbgfmt_cv)
+{
+ int new;
+ unsigned long indx = CV_FIRST_NONPRIM;
+ yasm_section *debug_type;
+ yasm_bytecode *bc;
+ cv_type *type;
+
+ debug_type = yasm_object_get_general(dbgfmt_cv->object, ".debug$T", 0, 1,
+ 0, 0, &new, 0);
+
+ /* Add label type */
+ type = cv_type_create(dbgfmt_cv, 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_resolve(bc, 0, 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 = 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, 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, 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, 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, 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(yasm_dbgfmt_cv *dbgfmt_cv, unsigned long indx)
+{
+ cv_type *type = yasm_xmalloc(sizeof(cv_type));
+
+ type->dbgfmt_cv = dbgfmt_cv;
+ type->indx = indx;
+ type->num_leaves = 0;
+
+ 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 yasm_bc_resolve_flags
+cv_type_bc_resolve(yasm_bytecode *bc, int save,
+ yasm_calc_bc_dist_func calc_bc_dist)
+{
+ 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 YASM_BC_RESOLVE_MIN_LEN;
+}
+
+static int
+cv_type_bc_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
+ yasm_output_value_func output_value,
+ yasm_output_reloc_func output_reloc)
+{
+ cv_type *type = (cv_type *)bc->contents;
+ yasm_dbgfmt_cv *dbgfmt_cv = type->dbgfmt_cv;
+ 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(dbgfmt_cv->arch, cval, buf, 4, 32, 0, bc, 1,
+ 0);
+ buf += 4;
+ reclen -= 4;
+ }
+
+ /* Total length of record (following this field) - 2 bytes */
+ yasm_intnum_set_uint(cval, reclen);
+ yasm_arch_intnum_tobytes(dbgfmt_cv->arch, cval, buf, 2, 16, 0, bc, 1, 0);
+ buf += 2;
+
+ /* Leaves */
+ for (i=0; i<type->num_leaves; i++)
+ cv_leaf_tobytes(type->leaves[i], bc, dbgfmt_cv->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;
+}
--- /dev/null
+ CV8 structures (for x86 and AMD64) - used by MSVC 8 (2005)
+ Everything listed in the order MASM seems to output it in.
+
+.debug$S: symbol and line number information
+ 4 bytes - version (4)
+
+Each major portion of DEBUG$S starts with 4 byte type, 4 byte length
+(in bytes following the length field). Each set is 4-byte aligned with 0s at
+the end (not included in length).
+
+0x000000F3: source filename string table
+ 1 byte - 0 (0th filename)
+ 0-terminated filename strings, 1 for each source file
+
+0x000000F4: source file info
+ for each source file:
+ 4 bytes - offset of filename in source filename string table
+ {2 bytes - checksum type/length? (0x0110)
+ 16 bytes - MD5 checksum of source file} OR
+ {2 bytes - no checksum (0)}
+ 2 bytes - 0 (padding?)
+
+0x000000F2: line numbers for section
+ 4 bytes - start offset in section (SECREL to section start)
+ 2 bytes - section index (SECTION to section start)
+ 2 bytes - pad/align (0)
+ 4 bytes - section length covered by line number info
+ 4 bytes - offset of source file in source file info table
+ 4 bytes - number of line number pairs
+ 4 bytes - number of bytes of line number pairs + 12
+
+ followed by pairs of:
+ 4 bytes - offset in section
+ 4 bytes - line number; if high bit is set,
+ end of statement/breakpointable (?) - e.g. lines containing
+ just labels should have line numbers
+
+0x000000F1: symbol information
+ enclosed data per below
+ (each element starts with 2 byte length, 2 byte type)
+ basically slightly updated versions of CV5 symbol info with 0-terminated
+ rather than length-prefixed strings
+
+0x1101 : Name of object file
+ 4 byte signature (0 for asm)
+ 0-terminated object filename
+0x1116 : creator signature (compile flag)
+ 4 bytes - language (3=Masm)
+ 4 bytes - target processor (0xD0 = AMD64)
+ 4 bytes - flags
+ 4 bytes - version
+ 2 bytes - ?
+ 0-terminated string containing creator name
+ 2 alignment bytes? (0)
+0x1105 : Code Label 16:32/64
+ 4 bytes SECREL of symbol
+ 2 bytes SECTION of symbol
+ 1 byte - flags
+ 0-terminated string containing symbol name
+0x110C : local data 16:32/64
+ 4 bytes type index of symbol
+ 4 bytes SECREL of symbol
+ 2 bytes SECTION of symbol
+ 0-terminated string containing symbol name
+0x110D : global data 16:32/64
+ 4 bytes type index of symbol
+ 4 bytes SECREL of symbol
+ 2 bytes SECTION of symbol
+ 0-terminated string containing symbol name
+0x1110 : local/global (?) procedure start 16:32/64
+ 4 bytes - parent
+ 4 bytes - pend
+ 4 bytes - pnext
+ 4 bytes - procedure length (bytes)
+ 4 bytes - debug start (offset from procedure start to frame setup)
+ 4 bytes - debug end (offset from procedure start to frame cleanup)
+ 4 bytes - type index of procedure type
+ 4 bytes - offset of procedure (SECREL of symbol)
+ 2 bytes - segment of procedure (SECTION of symbol)
+ 1 byte - flags
+ 0-terminated string containing procedure name
+
+.debug$T: type information
+ 4 bytes - version (4)
+ followed by type information per CV5 spec, padded to 4-byte boundaries
+
00
00
00
-04
+00
00
2e
74
unsigned long nreloc; /* number of relocation entries >64k -> error */
unsigned long flags2; /* internal flags (see COFF_FLAG_* above) */
unsigned long strtab_name; /* strtab offset of name if name > 8 chars */
+ int isdebug; /* is a debug section? */
} coff_section_data;
typedef enum coff_symrec_sclass {
data->nreloc = 0;
data->flags2 = 0;
data->strtab_name = 0;
+ data->isdebug = 0;
yasm_section_add_data(sect, &coff_section_data_cb, data);
sym = yasm_symtab_define_label(objfmt_coff->symtab, sectname,
csd = yasm_section_get_data(sect, &coff_section_data_cb);
if (!csd) {
/* Initialize new one */
- csd = coff_objfmt_init_new_section(info->objfmt_coff, sect,
- yasm_section_get_name(sect), 0);
- csd->flags = COFF_STYP_TEXT;
+ const char *sectname = yasm_section_get_name(sect);
+ csd = coff_objfmt_init_new_section(info->objfmt_coff, sect, sectname,
+ 0);
+ if (yasm__strncasecmp(sectname, ".debug", 6)==0) {
+ csd->flags = COFF_STYP_DATA;
+ if (info->objfmt_coff->win32)
+ csd->flags |= COFF_STYP_DISCARD|COFF_STYP_READ;
+ csd->isdebug = 1;
+ } else
+ csd->flags = COFF_STYP_TEXT;
}
return 0;
/* Handle other expressions, with relocation if necessary */
if (value->rshift > 0
- || (value->seg_of && (value->wrt || value->curpos_rel))) {
+ || (value->seg_of && (value->wrt || value->curpos_rel))
+ || (value->section_rel && (value->wrt || value->curpos_rel))) {
yasm__error(bc->line, N_("coff: relocation too complex"));
return 1;
}
intn_minus = bc->offset;
}
- if (value->seg_of) {
- /* Segment generation; zero value. */
+ if (value->seg_of || value->section_rel) {
+ /* Segment or section-relative generation; zero value. */
intn_val = 0;
intn_minus = 0;
}
reloc->type = COFF_RELOC_AMD64_SECTION;
else
yasm_internal_error(N_("coff objfmt: unrecognized machine"));
+ } else if (value->section_rel) {
+ if (objfmt_coff->machine == COFF_MACHINE_I386)
+ reloc->type = COFF_RELOC_I386_SECREL;
+ else if (objfmt_coff->machine == COFF_MACHINE_AMD64)
+ reloc->type = COFF_RELOC_AMD64_SECREL;
+ else
+ yasm_internal_error(N_("coff objfmt: unrecognized machine"));
} else {
if (objfmt_coff->machine == COFF_MACHINE_I386) {
if (info->csd->flags2 & COFF_FLAG_NOBASE)
}
}
- csd->addr = info->addr;
+ if (!csd->isdebug)
+ csd->addr = info->addr;
if ((csd->flags & COFF_STYP_STD_MASK) == COFF_STYP_BSS) {
yasm_bytecode *last = yasm_section_bcs_last(sect);
if (csd->size == 0)
return 0;
- info->addr += csd->size;
+ if (!csd->isdebug)
+ info->addr += csd->size;
csd->scnptr = (unsigned long)pos;
/* No relocations to output? Go on to next section */
} else
strncpy((char *)localbuf, yasm_section_get_name(sect), 8);
localbuf += 8;
- YASM_WRITE_32_L(localbuf, csd->addr); /* physical address */
- if (COFF_SET_VMA)
- YASM_WRITE_32_L(localbuf, csd->addr); /* virtual address */
- else
+ if (csd->isdebug) {
+ YASM_WRITE_32_L(localbuf, 0); /* physical address */
YASM_WRITE_32_L(localbuf, 0); /* virtual address */
+ } else {
+ YASM_WRITE_32_L(localbuf, csd->addr); /* physical address */
+ if (COFF_SET_VMA)
+ YASM_WRITE_32_L(localbuf, csd->addr);/* virtual address */
+ else
+ YASM_WRITE_32_L(localbuf, 0); /* virtual address */
+ }
YASM_WRITE_32_L(localbuf, csd->size); /* section size */
YASM_WRITE_32_L(localbuf, csd->scnptr); /* file ptr to data */
YASM_WRITE_32_L(localbuf, csd->relptr); /* file ptr to relocs */
}
static void
-coff_objfmt_output(yasm_objfmt *objfmt, FILE *f, int all_syms,
- /*@unused@*/ yasm_dbgfmt *df)
+coff_objfmt_output(yasm_objfmt *objfmt, FILE *f, int all_syms, yasm_dbgfmt *df)
{
yasm_objfmt_coff *objfmt_coff = (yasm_objfmt_coff *)objfmt;
coff_objfmt_output_info info;
YASM_WRITE_32_L(localbuf, symtab_count); /* number of symtabs */
YASM_WRITE_16_L(localbuf, 0); /* size of optional header (none) */
/* flags */
- flags = COFF_F_LNNO;
+ flags = 0;
+ if (strcmp(yasm_dbgfmt_keyword(df), "null")==0)
+ flags = COFF_F_LNNO;
if (!all_syms)
flags |= COFF_F_LSYMS;
if (objfmt_coff->machine != COFF_MACHINE_AMD64)
coff_objfmt_directive
};
+/* Define valid debug formats to use with this object format */
+static const char *winXX_objfmt_dbgfmt_keywords[] = {
+ "null",
+ "dwarf2",
+ "cv8",
+ NULL
+};
+
/* Define objfmt structure -- see objfmt.h for details */
yasm_objfmt_module yasm_win32_LTX_objfmt = {
"Win32",
"win32",
"obj",
32,
- coff_objfmt_dbgfmt_keywords,
+ winXX_objfmt_dbgfmt_keywords,
"null",
win32_objfmt_create,
coff_objfmt_output,
"win64",
"obj",
64,
- coff_objfmt_dbgfmt_keywords,
+ winXX_objfmt_dbgfmt_keywords,
"null",
win64_objfmt_create,
coff_objfmt_output,
}
/* Handle other expressions, with relocation if necessary */
- if (value->seg_of || value->rshift > 0) {
+ if (value->seg_of || value->section_rel || value->rshift > 0) {
yasm__error(bc->line, N_("elf: relocation too complex"));
return 1;
}
return 0;
}
+ if (value->section_rel) {
+ yasm__error(bc->line, N_("xdf: relocation too complex"));
+ return 1;
+ }
+
intn_minus = 0;
if (value->rel) {
xdf_reloc *reloc;