]> granicus.if.org Git - yasm/commitdiff
Add support for RDOFF2 object format (#73).
authorPeter Johnson <peter@tortall.net>
Tue, 17 Oct 2006 05:48:42 +0000 (05:48 -0000)
committerPeter Johnson <peter@tortall.net>
Tue, 17 Oct 2006 05:48:42 +0000 (05:48 -0000)
svn path=/trunk/yasm/; revision=1650

27 files changed:
libyasm/symrec.c
libyasm/symrec.h
modules/objfmts/Makefile.inc
modules/objfmts/rdf/Makefile.inc [new file with mode: 0644]
modules/objfmts/rdf/rdf-objfmt.c [new file with mode: 0644]
modules/objfmts/rdf/tests/Makefile.inc [new file with mode: 0644]
modules/objfmts/rdf/tests/rdf_test.sh [new file with mode: 0755]
modules/objfmts/rdf/tests/rdfabs.asm [new file with mode: 0644]
modules/objfmts/rdf/tests/rdfabs.errwarn [new file with mode: 0644]
modules/objfmts/rdf/tests/rdfabs.hex [new file with mode: 0644]
modules/objfmts/rdf/tests/rdfext.asm [new file with mode: 0644]
modules/objfmts/rdf/tests/rdfext.hex [new file with mode: 0644]
modules/objfmts/rdf/tests/rdfseg.asm [new file with mode: 0644]
modules/objfmts/rdf/tests/rdfseg.hex [new file with mode: 0644]
modules/objfmts/rdf/tests/rdfseg2.asm [new file with mode: 0644]
modules/objfmts/rdf/tests/rdfseg2.hex [new file with mode: 0644]
modules/objfmts/rdf/tests/rdftest1.asm [new file with mode: 0644]
modules/objfmts/rdf/tests/rdftest1.hex [new file with mode: 0644]
modules/objfmts/rdf/tests/rdftest2.asm [new file with mode: 0644]
modules/objfmts/rdf/tests/rdftest2.hex [new file with mode: 0644]
modules/objfmts/rdf/tests/rdtlib.asm [new file with mode: 0644]
modules/objfmts/rdf/tests/rdtlib.hex [new file with mode: 0644]
modules/objfmts/rdf/tests/rdtmain.asm [new file with mode: 0644]
modules/objfmts/rdf/tests/rdtmain.hex [new file with mode: 0644]
modules/objfmts/rdf/tests/testlib.asm [new file with mode: 0644]
modules/objfmts/rdf/tests/testlib.hex [new file with mode: 0644]
modules/preprocs/nasm/standard.mac

index 6028c4bc4902b06a514266fae1fe56c403baaffc..2fbf6d2a51d67db49a50950b45aeaaf5482d778c 100644 (file)
@@ -442,6 +442,12 @@ yasm_symrec_get_visibility(const yasm_symrec *sym)
     return sym->visibility;
 }
 
+unsigned long
+yasm_symrec_get_line(const yasm_symrec *sym)
+{
+    return sym->line;
+}
+
 const yasm_expr *
 yasm_symrec_get_equ(const yasm_symrec *sym)
 {
index 04ec321b517f25f872cc1e98c829e0a912913f21..a734a30f6dbf47c28fe53417fc35c17a684eddd5 100644 (file)
@@ -217,6 +217,12 @@ void yasm_symtab_print(yasm_symtab *symtab, FILE *f, int indent_level);
  */
 yasm_sym_vis yasm_symrec_get_visibility(const yasm_symrec *sym);
 
+/** Get the virtual line of a symbol (where it was first declared or used).
+ * \param sym      symbol
+ * \return line            virtual line
+ */
+unsigned long yasm_symrec_get_line(const yasm_symrec *sym);
+
 /** Get EQU value of a symbol.
  * \param sym      symbol
  * \return EQU value, or NULL if symbol is not an EQU or is not defined.
index b5b899455aea8abf443508459769ad70c17dc7a2..c4e562b5a9f93960ac245aaa02ff7c222041e4ca 100644 (file)
@@ -5,6 +5,7 @@ EXTRA_DIST += modules/objfmts/bin/Makefile.inc
 EXTRA_DIST += modules/objfmts/elf/Makefile.inc
 #!EXTRA_DIST += modules/objfmts/omf/Makefile.inc
 EXTRA_DIST += modules/objfmts/coff/Makefile.inc
+EXTRA_DIST += modules/objfmts/rdf/Makefile.inc
 EXTRA_DIST += modules/objfmts/win32/Makefile.inc
 EXTRA_DIST += modules/objfmts/win64/Makefile.inc
 EXTRA_DIST += modules/objfmts/xdf/Makefile.inc
@@ -14,6 +15,7 @@ include modules/objfmts/bin/Makefile.inc
 include modules/objfmts/elf/Makefile.inc
 #!include modules/objfmts/omf/Makefile.inc
 include modules/objfmts/coff/Makefile.inc
+include modules/objfmts/rdf/Makefile.inc
 include modules/objfmts/win32/Makefile.inc
 include modules/objfmts/win64/Makefile.inc
 include modules/objfmts/xdf/Makefile.inc
diff --git a/modules/objfmts/rdf/Makefile.inc b/modules/objfmts/rdf/Makefile.inc
new file mode 100644 (file)
index 0000000..ef33dff
--- /dev/null
@@ -0,0 +1,9 @@
+# $Id$
+
+libyasm_a_SOURCES += modules/objfmts/rdf/rdf-objfmt.c
+
+YASM_MODULES += objfmt_rdf
+
+EXTRA_DIST += modules/objfmts/rdf/tests/Makefile.inc
+
+include modules/objfmts/rdf/tests/Makefile.inc
diff --git a/modules/objfmts/rdf/rdf-objfmt.c b/modules/objfmts/rdf/rdf-objfmt.c
new file mode 100644 (file)
index 0000000..0059f6c
--- /dev/null
@@ -0,0 +1,1178 @@
+/*
+ * Relocatable Dynamic Object File Format (RDOFF) version 2 format
+ *
+ *  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
+#define YASM_EXPR_INTERNAL
+#include <libyasm.h>
+
+
+#define REGULAR_OUTBUF_SIZE    1024
+
+#define RDF_MAGIC      "RDOFF2"
+
+/* Maximum size of an import/export label (including trailing zero) */
+#define EXIM_LABEL_MAX         64
+
+/* Maximum size of library or module name (including trailing zero) */
+#define MODLIB_NAME_MAX                128
+
+/* Maximum number of segments that we can handle in one file */
+#define RDF_MAXSEGS            64
+
+/* Record types that may present the RDOFF header */
+#define RDFREC_GENERIC         0
+#define RDFREC_RELOC           1
+#define RDFREC_IMPORT          2
+#define RDFREC_GLOBAL          3
+#define RDFREC_DLL             4
+#define RDFREC_BSS             5
+#define RDFREC_SEGRELOC                6
+#define RDFREC_FARIMPORT       7
+#define RDFREC_MODNAME         8
+#define RDFREC_COMMON          10
+
+/* Flags for ExportRec/ImportRec */
+#define SYM_DATA       1
+#define SYM_FUNCTION   2
+
+/* Flags for ExportRec */
+#define SYM_GLOBAL     4
+
+/* Flags for ImportRec */
+#define SYM_IMPORT     8
+#define SYM_FAR                16
+
+typedef struct rdf_reloc {
+    yasm_reloc reloc;
+    enum {
+       RDF_RELOC_NORM,     /* normal */
+       RDF_RELOC_REL,      /* relative to current position */
+       RDF_RELOC_SEG       /* segment containing symbol */
+    } type;                        /* type of relocation */
+    unsigned int size;
+    unsigned int refseg;
+} rdf_reloc;
+
+typedef struct rdf_section_data {
+    /*@dependent@*/ yasm_symrec *sym;  /* symbol created for this section */
+    long scnum;                    /* section number (0=first section) */
+    enum {
+       RDF_SECT_BSS = 0,
+       RDF_SECT_CODE = 1,
+       RDF_SECT_DATA = 2,
+       RDF_SECT_COMMENT = 3,
+       RDF_SECT_LCOMMENT = 4,
+       RDF_SECT_PCOMMENT = 5,
+       RDF_SECT_SYMDEBUG = 6,
+       RDF_SECT_LINEDEBUG = 7
+    } type;                /* section type */
+    unsigned int reserved;  /* reserved data */
+    unsigned long size;            /* size of raw data (section data) in bytes */
+
+    unsigned char *raw_data;   /* raw section data, only used during output */
+} rdf_section_data;
+
+typedef struct rdf_symrec_data {
+    /*@owned@*/ /*@null@*/ yasm_expr *size; /* size if COMMON declaration */
+    unsigned long align;               /* alignment if COMMON declaration */
+
+    unsigned int flags;                        /* import/export/type flags */
+    unsigned int segment;              /* assigned RDF "segment" index */
+} rdf_symrec_data;
+
+typedef STAILQ_HEAD(xdf_str_head, xdf_str) xdf_str_head;
+typedef struct xdf_str {
+    STAILQ_ENTRY(xdf_str) link;
+    /*@owned@*/ char *str;
+} xdf_str;
+
+typedef struct yasm_objfmt_rdf {
+    yasm_objfmt_base objfmt;               /* base structure */
+
+    long parse_scnum;              /* sect numbering in parser */
+
+    yasm_object *object;
+    yasm_symtab *symtab;
+    /*@dependent@*/ yasm_arch *arch;
+
+    /*@owned@*/ xdf_str_head module_names;
+    /*@owned@*/ xdf_str_head library_names;
+} yasm_objfmt_rdf;
+
+typedef struct rdf_objfmt_output_info {
+    yasm_objfmt_rdf *objfmt_rdf;
+    yasm_errwarns *errwarns;
+    /*@dependent@*/ FILE *f;
+    /*@only@*/ unsigned char *buf;
+    yasm_section *sect;
+    /*@dependent@*/ rdf_section_data *rsd;
+
+    unsigned long indx;                    /* symbol "segment" (extern/common only) */
+
+    unsigned long bss_size;        /* total BSS size */
+} rdf_objfmt_output_info;
+
+static void rdf_section_data_destroy(/*@only@*/ void *d);
+static void rdf_section_data_print(void *data, FILE *f, int indent_level);
+
+static const yasm_assoc_data_callback rdf_section_data_cb = {
+    rdf_section_data_destroy,
+    rdf_section_data_print
+};
+
+static void rdf_symrec_data_destroy(/*@only@*/ void *d);
+static void rdf_symrec_data_print(void *data, FILE *f, int indent_level);
+
+static const yasm_assoc_data_callback rdf_symrec_data_cb = {
+    rdf_symrec_data_destroy,
+    rdf_symrec_data_print
+};
+
+yasm_objfmt_module yasm_rdf_LTX_objfmt;
+
+
+static /*@dependent@*/ rdf_symrec_data *
+rdf_objfmt_sym_set_data(yasm_symrec *sym,
+                       /*@only@*/ /*@null@*/ yasm_expr *size,
+                       unsigned long align, unsigned int flags)
+{
+    rdf_symrec_data *rsymd = yasm_xmalloc(sizeof(rdf_symrec_data));
+
+    rsymd->size = size;
+    rsymd->align = align;
+    rsymd->flags = flags;
+    rsymd->segment = 0;
+
+    yasm_symrec_add_data(sym, &rdf_symrec_data_cb, rsymd);
+    return rsymd;
+}
+
+static yasm_objfmt *
+rdf_objfmt_create(yasm_object *object, yasm_arch *a)
+{
+    yasm_objfmt_rdf *objfmt_rdf = yasm_xmalloc(sizeof(yasm_objfmt_rdf));
+
+    objfmt_rdf->object = object;
+    objfmt_rdf->symtab = yasm_object_get_symtab(object);
+    objfmt_rdf->arch = a;
+
+    /* We theoretically support all arches, so don't check.
+     * Really we only support byte-addressable ones.
+     */
+
+    objfmt_rdf->parse_scnum = 0;    /* section numbering starts at 0 */
+
+    STAILQ_INIT(&objfmt_rdf->module_names);
+    STAILQ_INIT(&objfmt_rdf->library_names);
+
+    objfmt_rdf->objfmt.module = &yasm_rdf_LTX_objfmt;
+
+    return (yasm_objfmt *)objfmt_rdf;
+}
+
+static int
+rdf_objfmt_output_value(yasm_value *value, unsigned char *buf, size_t destsize,
+                       unsigned long offset, yasm_bytecode *bc, int warn,
+                       /*@null@*/ void *d)
+{
+    /*@null@*/ rdf_objfmt_output_info *info = (rdf_objfmt_output_info *)d;
+    yasm_objfmt_rdf *objfmt_rdf;
+    /*@dependent@*/ /*@null@*/ yasm_intnum *intn;
+    unsigned long intn_minus;
+    unsigned long intn_plus;
+    int retval;
+    unsigned int valsize = value->size;
+
+    assert(info != NULL);
+    objfmt_rdf = info->objfmt_rdf;
+
+    if (value->abs)
+       value->abs = yasm_expr_simplify(value->abs, 1);
+
+    /* Try to output constant and PC-relative section-local first.
+     * Note this does NOT output any value with a SEG, WRT, external,
+     * cross-section, or non-PC-relative reference (those are handled below).
+     */
+    switch (yasm_value_output_basic(value, buf, destsize, bc, warn,
+                                   info->objfmt_rdf->arch)) {
+       case -1:
+           return 1;
+       case 0:
+           break;
+       default:
+           return 0;
+    }
+
+    if (value->section_rel) {
+       yasm_error_set(YASM_ERROR_TOO_COMPLEX,
+                      N_("rdf: relocation too complex"));
+       return 1;
+    }
+
+    if (value->rel && value->wrt) {
+       yasm_error_set(YASM_ERROR_TOO_COMPLEX,
+                      N_("rdf: WRT not supported"));
+       return 1;
+    }
+
+    intn_minus = 0;
+    intn_plus = 0;
+    if (value->rel) {
+       rdf_reloc *reloc;
+       /*@null@*/ rdf_symrec_data *rsymd;
+       /*@dependent@*/ yasm_bytecode *precbc;
+
+       reloc = yasm_xmalloc(sizeof(rdf_reloc));
+       reloc->reloc.addr = yasm_intnum_create_uint(bc->offset + offset);
+       reloc->reloc.sym = value->rel;
+       reloc->size = valsize/8;
+
+       if (value->seg_of)
+           reloc->type = RDF_RELOC_SEG;
+       else if (value->curpos_rel) {
+           reloc->type = RDF_RELOC_REL;
+           /* Adjust to start of section, so subtract out the bytecode
+            * offset.
+            */
+           intn_minus = bc->offset;
+       } else
+           reloc->type = RDF_RELOC_NORM;
+
+       if (yasm_symrec_get_label(value->rel, &precbc)) {
+           /* local, set the value to be the offset, and the refseg to the
+            * segment number.
+            */
+           /*@dependent@*/ /*@null@*/ rdf_section_data *csectd;
+           /*@dependent@*/ yasm_section *sect;
+
+           sect = yasm_bc_get_section(precbc);
+           csectd = yasm_section_get_data(sect, &rdf_section_data_cb);
+           if (!csectd)
+               yasm_internal_error(N_("didn't understand section"));
+           reloc->refseg = csectd->scnum;
+           intn_plus = yasm_bc_next_offset(precbc);
+       } else {
+           /* must be common/external */
+           rsymd = yasm_symrec_get_data(reloc->reloc.sym,
+                                        &rdf_symrec_data_cb);
+           if (!rsymd)
+               yasm_internal_error(
+                   N_("rdf: no symbol data for relocated symbol"));
+           reloc->refseg = rsymd->segment;
+       }
+
+       yasm_section_add_reloc(info->sect, (yasm_reloc *)reloc, yasm_xfree);
+    }
+
+    if (intn_minus > 0) {
+       intn = yasm_intnum_create_uint(intn_minus);
+       yasm_intnum_calc(intn, YASM_EXPR_NEG, NULL);
+    } else
+       intn = yasm_intnum_create_uint(intn_plus);
+
+    if (value->abs) {
+       yasm_intnum *intn2 = yasm_expr_get_intnum(&value->abs, 0);
+       if (!intn2) {
+           yasm_error_set(YASM_ERROR_TOO_COMPLEX,
+                          N_("rdf: relocation too complex"));
+           yasm_intnum_destroy(intn);
+           return 1;
+       }
+       yasm_intnum_calc(intn, YASM_EXPR_ADD, intn2);
+    }
+
+    retval = yasm_arch_intnum_tobytes(objfmt_rdf->arch, intn, buf, destsize,
+                                     valsize, 0, bc, warn);
+    yasm_intnum_destroy(intn);
+    return retval;
+}
+
+static int
+rdf_objfmt_output_bytecode(yasm_bytecode *bc, /*@null@*/ void *d)
+{
+    /*@null@*/ rdf_objfmt_output_info *info = (rdf_objfmt_output_info *)d;
+    /*@null@*/ /*@only@*/ unsigned char *bigbuf;
+    unsigned long size = REGULAR_OUTBUF_SIZE;
+    int gap;
+
+    assert(info != NULL);
+
+    bigbuf = yasm_bc_tobytes(bc, info->buf, &size, &gap, info,
+                            rdf_objfmt_output_value, NULL);
+
+    /* Don't bother doing anything else if size ended up being 0. */
+    if (size == 0) {
+       if (bigbuf)
+           yasm_xfree(bigbuf);
+       return 0;
+    }
+
+    /* Warn that gaps are converted to 0 and write out the 0's. */
+    if (gap) {
+       unsigned long left;
+       yasm_warn_set(YASM_WARN_UNINIT_CONTENTS,
+                     N_("uninitialized space: zeroing"));
+       /* Write out in chunks */
+       memset(&info->rsd->raw_data[info->rsd->size], 0, size);
+    } else {
+       /* Output buf (or bigbuf if non-NULL) to file */
+       memcpy(&info->rsd->raw_data[info->rsd->size],
+              bigbuf ? bigbuf : info->buf, (size_t)size);
+    }
+
+    info->rsd->size += size;
+
+    /* If bigbuf was allocated, free it */
+    if (bigbuf)
+       yasm_xfree(bigbuf);
+
+    return 0;
+}
+
+static int
+rdf_objfmt_output_section_mem(yasm_section *sect, /*@null@*/ void *d)
+{
+    /*@null@*/ rdf_objfmt_output_info *info = (rdf_objfmt_output_info *)d;
+    /*@dependent@*/ /*@null@*/ rdf_section_data *rsd;
+    unsigned long size;
+    rdf_reloc *reloc;
+
+    /* Don't output absolute sections */
+    if (yasm_section_is_absolute(sect))
+       return 0;
+
+    assert(info != NULL);
+    rsd = yasm_section_get_data(sect, &rdf_section_data_cb);
+    assert(rsd != NULL);
+
+    size = yasm_bc_next_offset(yasm_section_bcs_last(sect));
+
+    if (rsd->type == RDF_SECT_BSS) {
+       /* Don't output BSS sections, but remember length
+        * TODO: Check for non-reserve bytecodes?
+        */
+       info->bss_size += size;
+       return 0;
+    }
+
+    /* Empty?  Go on to next section */
+    if (size == 0)
+       return 0;
+
+    /* See UGH comment in output() for why we're doing this */
+    rsd->raw_data = yasm_xmalloc(size);
+    rsd->size = 0;
+
+    info->sect = sect;
+    info->rsd = rsd;
+    yasm_section_bcs_traverse(sect, info->errwarns, info,
+                             rdf_objfmt_output_bytecode);
+
+    /* Sanity check final section size */
+    if (rsd->size != size)
+       yasm_internal_error(
+           N_("rdf: section computed size did not match actual size"));
+
+    return 0;
+}
+
+static int
+rdf_objfmt_output_section_reloc(yasm_section *sect, /*@null@*/ void *d)
+{
+    /*@null@*/ rdf_objfmt_output_info *info = (rdf_objfmt_output_info *)d;
+    /*@dependent@*/ /*@null@*/ rdf_section_data *rsd;
+    long pos;
+    rdf_reloc *reloc;
+
+    /* Don't output absolute sections */
+    if (yasm_section_is_absolute(sect))
+       return 0;
+
+    assert(info != NULL);
+    rsd = yasm_section_get_data(sect, &rdf_section_data_cb);
+    assert(rsd != NULL);
+
+    if (rsd->type == RDF_SECT_BSS) {
+       /* Don't output BSS sections. */
+       return 0;
+    }
+
+    /* Empty?  Go on to next section */
+    if (rsd->size == 0)
+       return 0;
+
+    reloc = (rdf_reloc *)yasm_section_relocs_first(sect);
+    while (reloc) {
+       unsigned char *localbuf = info->buf;
+
+       if (reloc->type == RDF_RELOC_SEG)
+           YASM_WRITE_8(localbuf, RDFREC_SEGRELOC);
+       else
+           YASM_WRITE_8(localbuf, RDFREC_RELOC);
+       YASM_WRITE_8(localbuf, 8);              /* record length */
+       /* Section number, +0x40 if relative reloc */
+       YASM_WRITE_8(localbuf, rsd->scnum +
+                    (reloc->type == RDF_RELOC_REL ? 0x40 : 0));
+       yasm_intnum_get_sized(reloc->reloc.addr, localbuf, 4, 32, 0, 0, 0);
+       localbuf += 4;                          /* offset of relocation */
+       YASM_WRITE_8(localbuf, reloc->size);        /* size of relocation */
+       YASM_WRITE_16_L(localbuf, reloc->refseg);   /* relocated symbol */
+       fwrite(info->buf, 10, 1, info->f);
+
+       reloc = (rdf_reloc *)yasm_section_reloc_next((yasm_reloc *)reloc);
+    }
+
+    return 0;
+}
+
+static int
+rdf_objfmt_output_section_file(yasm_section *sect, /*@null@*/ void *d)
+{
+    /*@null@*/ rdf_objfmt_output_info *info = (rdf_objfmt_output_info *)d;
+    /*@dependent@*/ /*@null@*/ rdf_section_data *rsd;
+    unsigned char *localbuf;
+
+    /* Don't output absolute sections */
+    if (yasm_section_is_absolute(sect))
+       return 0;
+
+    assert(info != NULL);
+    rsd = yasm_section_get_data(sect, &rdf_section_data_cb);
+    assert(rsd != NULL);
+
+    if (rsd->type == RDF_SECT_BSS) {
+       /* Don't output BSS sections. */
+       return 0;
+    }
+
+    /* Empty?  Go on to next section */
+    if (rsd->size == 0)
+       return 0;
+
+    /* Section header */
+    localbuf = info->buf;
+    YASM_WRITE_16_L(localbuf, rsd->type);      /* type */
+    YASM_WRITE_16_L(localbuf, rsd->scnum);     /* number */
+    YASM_WRITE_16_L(localbuf, rsd->reserved);  /* reserved */
+    YASM_WRITE_32_L(localbuf, rsd->size);      /* length */
+    fwrite(info->buf, 10, 1, info->f);
+
+    /* Section data */
+    fwrite(rsd->raw_data, rsd->size, 1, info->f);
+
+    /* Free section data */
+    yasm_xfree(rsd->raw_data);
+    rsd->raw_data = NULL;
+
+    return 0;
+}
+
+static int
+rdf_objfmt_output_sym(yasm_symrec *sym, /*@null@*/ void *d)
+{
+    /*@null@*/ rdf_objfmt_output_info *info = (rdf_objfmt_output_info *)d;
+    yasm_sym_vis vis = yasm_symrec_get_visibility(sym);
+    const char *name;
+    size_t len;
+    unsigned long value = 0;
+    unsigned int scnum = 0;
+    /*@dependent@*/ /*@null@*/ yasm_section *sect;
+    /*@dependent@*/ /*@null@*/ yasm_bytecode *precbc;
+    unsigned char *localbuf;
+    unsigned int rectype = RDFREC_GENERIC;
+    rdf_symrec_data *rsymd;
+
+    assert(info != NULL);
+
+    if (vis == YASM_SYM_LOCAL || vis == YASM_SYM_DLOCAL)
+       return 0;   /* skip local syms */
+
+    /* Look at symrec for value/scnum/etc. */
+    if (yasm_symrec_get_label(sym, &precbc)) {
+       /*@dependent@*/ /*@null@*/ rdf_section_data *csectd;
+
+       if (precbc)
+           sect = yasm_bc_get_section(precbc);
+       else
+           sect = NULL;
+       if (!sect)
+           return 0;
+
+       /* it's a label: get value and offset. */
+       csectd = yasm_section_get_data(sect, &rdf_section_data_cb);
+       if (csectd) {
+           scnum = csectd->scnum;
+       } else if (yasm_section_is_absolute(sect)) {
+           yasm_warn_set(YASM_WARN_GENERAL,
+                         N_("rdf does not support exporting absolutes"));
+           yasm_errwarn_propagate(info->errwarns, yasm_symrec_get_line(sym));
+           return 0;
+       } else
+           yasm_internal_error(N_("didn't understand section"));
+       value = yasm_bc_next_offset(precbc);
+    } else if (yasm_symrec_get_equ(sym)) {
+       yasm_warn_set(YASM_WARN_GENERAL,
+                     N_("rdf does not support exporting EQU/absolute values"));
+       yasm_errwarn_propagate(info->errwarns, yasm_symrec_get_line(sym));
+       return 0;
+    }
+
+    name = yasm_symrec_get_name(sym);
+    len = strlen(name);
+
+    if (len > EXIM_LABEL_MAX-1) {
+       yasm_warn_set(YASM_WARN_GENERAL,
+                     N_("label name too long, truncating to %d bytes"),
+                     EXIM_LABEL_MAX);
+       yasm_errwarn_propagate(info->errwarns, yasm_symrec_get_line(sym));
+       len = EXIM_LABEL_MAX-1;
+    }
+
+    localbuf = info->buf;
+    if (vis & YASM_SYM_GLOBAL) {
+       rsymd = yasm_symrec_get_data(sym, &rdf_symrec_data_cb);
+       if (!rsymd)
+           yasm_internal_error(N_("rdf: no symbol data for global symbol"));
+       YASM_WRITE_8(localbuf, RDFREC_GLOBAL);
+       YASM_WRITE_8(localbuf, 6+len+1);        /* record length */
+       YASM_WRITE_8(localbuf, rsymd->flags);   /* flags */
+       YASM_WRITE_8(localbuf, scnum);          /* segment referred to */
+       YASM_WRITE_32_L(localbuf, value);       /* offset */
+    } else {
+       /* Create new symrec data if it doesn't already exist */
+       rsymd = yasm_symrec_get_data(sym, &rdf_symrec_data_cb);
+       if (!rsymd)
+           rsymd = rdf_objfmt_sym_set_data(sym, NULL, 0, 0);
+
+       /* Save symbol segment in symrec data (for later reloc gen) */
+       rsymd->segment = info->indx++;
+       scnum = rsymd->segment;
+
+       if (vis & YASM_SYM_COMMON) {
+           const yasm_intnum *intn;
+
+           YASM_WRITE_8(localbuf, RDFREC_COMMON);
+           YASM_WRITE_8(localbuf, 8+len+1);    /* record length */
+           YASM_WRITE_16_L(localbuf, scnum);   /* segment allocated */
+
+           /* size */
+           intn = yasm_expr_get_intnum(&rsymd->size, 1);
+           if (!intn) {
+               yasm_error_set(YASM_ERROR_NOT_CONSTANT,
+                   N_("COMMON data size not an integer expression"));
+               yasm_errwarn_propagate(info->errwarns,
+                                      yasm_symrec_get_line(sym));
+           } else
+               value = yasm_intnum_get_uint(intn);
+           YASM_WRITE_32_L(localbuf, value);
+           YASM_WRITE_16_L(localbuf, rsymd->align);    /* alignment */
+       } else if (vis & YASM_SYM_EXTERN) {
+           unsigned int flags = rsymd->flags;
+           if (flags & SYM_FAR) {
+               YASM_WRITE_8(localbuf, RDFREC_FARIMPORT);
+               flags &= ~SYM_FAR;
+           } else
+               YASM_WRITE_8(localbuf, RDFREC_IMPORT);
+           YASM_WRITE_8(localbuf, 3+len+1);    /* record length */
+           YASM_WRITE_8(localbuf, flags);      /* flags */
+           YASM_WRITE_16_L(localbuf, scnum);   /* segment allocated */
+       }
+    }
+
+    /* Symbol name */
+    memcpy(localbuf, name, len);
+    localbuf += len;
+    YASM_WRITE_8(localbuf, 0);         /* 0-terminated name */
+
+    fwrite(info->buf, (unsigned long)(localbuf-info->buf), 1, info->f);
+    return 0;
+}
+
+static void
+rdf_objfmt_output(yasm_objfmt *objfmt, FILE *f, int all_syms,
+                 /*@unused@*/ yasm_dbgfmt *df, yasm_errwarns *errwarns)
+{
+    yasm_objfmt_rdf *objfmt_rdf = (yasm_objfmt_rdf *)objfmt;
+    rdf_objfmt_output_info info;
+    unsigned char *localbuf;
+    long headerlen, filelen;
+    xdf_str *cur;
+    size_t len;
+
+    info.objfmt_rdf = objfmt_rdf;
+    info.errwarns = errwarns;
+    info.f = f;
+    info.buf = yasm_xmalloc(REGULAR_OUTBUF_SIZE);
+    info.bss_size = 0;
+
+    /* Allocate space for file header by seeking forward */
+    if (fseek(f, (long)strlen(RDF_MAGIC)+8, SEEK_SET) < 0) {
+       yasm__fatal(N_("could not seek on output file"));
+       /*@notreached@*/
+       return;
+    }
+
+    /* Output custom header records (library and module, etc) */
+    cur = STAILQ_FIRST(&objfmt_rdf->module_names);
+    while (cur) {
+       len = strlen(cur->str)+1;
+       localbuf = info.buf;
+       YASM_WRITE_8(localbuf, RDFREC_MODNAME);         /* record type */
+       YASM_WRITE_8(localbuf, len);                    /* record length */
+       fwrite(info.buf, 2, 1, f);
+       fwrite(cur->str, len, 1, f);
+       cur = STAILQ_NEXT(cur, link);
+    }
+
+    cur = STAILQ_FIRST(&objfmt_rdf->library_names);
+    while (cur) {
+       len = strlen(cur->str)+1;
+       localbuf = info.buf;
+       YASM_WRITE_8(localbuf, RDFREC_DLL);             /* record type */
+       YASM_WRITE_8(localbuf, len);                    /* record length */
+       fwrite(info.buf, 2, 1, f);
+       fwrite(cur->str, len, 1, f);
+       cur = STAILQ_NEXT(cur, link);
+    }
+
+    /* Output symbol table */
+    info.indx = objfmt_rdf->parse_scnum;
+    yasm_symtab_traverse(objfmt_rdf->symtab, &info, rdf_objfmt_output_sym);
+
+    /* UGH! Due to the fact the relocs go at the beginning of the file, and
+     * we only know if we have relocs when we output the sections, we have
+     * to output the section data before we have output the relocs.  But
+     * we also don't know how much space to preallocate for relocs, so....
+     * we output into memory buffers first (thus the UGH).
+     *
+     * Stupid object format design, if you ask me (basically all other
+     * object formats put the relocs *after* the section data to avoid this
+     * exact problem).
+     *
+     * We also calculate the total size of all BSS sections here.
+     */
+    if (yasm_object_sections_traverse(objfmt_rdf->object, &info,
+                                     rdf_objfmt_output_section_mem))
+       return;
+
+    /* Output all relocs */
+    if (yasm_object_sections_traverse(objfmt_rdf->object, &info,
+                                     rdf_objfmt_output_section_reloc))
+       return;
+
+    /* Output BSS record */
+    if (info.bss_size > 0) {
+       localbuf = info.buf;
+       YASM_WRITE_8(localbuf, RDFREC_BSS);             /* record type */
+       YASM_WRITE_8(localbuf, 4);                      /* record length */
+       YASM_WRITE_32_L(localbuf, info.bss_size);       /* total BSS size */
+       fwrite(info.buf, 6, 1, f);
+    }
+
+    /* Determine header length */
+    headerlen = ftell(f);
+    if (headerlen == -1) {
+       yasm__fatal(N_("could not get file position on output file"));
+       /*@notreached@*/
+       return;
+    }
+
+    /* Section data (to file) */
+    if (yasm_object_sections_traverse(objfmt_rdf->object, &info,
+                                     rdf_objfmt_output_section_file))
+       return;
+
+    /* NULL section to end file */
+    memset(info.buf, 0, 10);
+    fwrite(info.buf, 10, 1, f);
+
+    /* Determine object length */
+    filelen = ftell(f);
+    if (filelen == -1) {
+       yasm__fatal(N_("could not get file position on output file"));
+       /*@notreached@*/
+       return;
+    }
+
+    /* Write file header */
+    if (fseek(f, 0, SEEK_SET) < 0) {
+       yasm__fatal(N_("could not seek on output file"));
+       /*@notreached@*/
+       return;
+    }
+
+    fwrite(RDF_MAGIC, strlen(RDF_MAGIC), 1, f);
+    localbuf = info.buf;
+    YASM_WRITE_32_L(localbuf, filelen-10);             /* object size */
+    YASM_WRITE_32_L(localbuf, headerlen-14);           /* header size */
+    fwrite(info.buf, 8, 1, f);
+
+    yasm_xfree(info.buf);
+}
+
+static void
+rdf_objfmt_destroy(yasm_objfmt *objfmt)
+{
+    yasm_objfmt_rdf *objfmt_rdf = (yasm_objfmt_rdf *)objfmt;
+    xdf_str *cur, *next;
+
+    cur = STAILQ_FIRST(&objfmt_rdf->module_names);
+    while (cur) {
+       next = STAILQ_NEXT(cur, link);
+       yasm_xfree(cur->str);
+       yasm_xfree(cur);
+       cur = next;
+    }
+
+    cur = STAILQ_FIRST(&objfmt_rdf->library_names);
+    while (cur) {
+       next = STAILQ_NEXT(cur, link);
+       yasm_xfree(cur->str);
+       yasm_xfree(cur);
+       cur = next;
+    }
+
+    yasm_xfree(objfmt);
+}
+
+static rdf_section_data *
+rdf_objfmt_init_new_section(yasm_objfmt_rdf *objfmt_rdf, yasm_section *sect,
+                           const char *sectname, unsigned long line)
+{
+    rdf_section_data *data;
+    yasm_symrec *sym;
+
+    data = yasm_xmalloc(sizeof(rdf_section_data));
+    data->scnum = objfmt_rdf->parse_scnum++;
+    data->type = 0;
+    data->reserved = 0;
+    data->size = 0;
+    data->raw_data = NULL;
+    yasm_section_add_data(sect, &rdf_section_data_cb, data);
+
+    sym = yasm_symtab_define_label(objfmt_rdf->symtab, sectname,
+                                  yasm_section_bcs_first(sect), 1, line);
+    data->sym = sym;
+    return data;
+}
+
+static yasm_section *
+rdf_objfmt_add_default_section(yasm_objfmt *objfmt)
+{
+    yasm_objfmt_rdf *objfmt_rdf = (yasm_objfmt_rdf *)objfmt;
+    yasm_section *retval;
+    rdf_section_data *rsd;
+    int isnew;
+
+    retval = yasm_object_get_general(objfmt_rdf->object, ".text", 0, 0, 1, 0,
+                                    &isnew, 0);
+    if (isnew) {
+       rsd = rdf_objfmt_init_new_section(objfmt_rdf, retval, ".text", 0);
+       rsd->type = RDF_SECT_CODE;
+       rsd->reserved = 0;
+       yasm_section_set_default(retval, 1);
+    }
+    return retval;
+}
+
+static /*@observer@*/ /*@null@*/ yasm_section *
+rdf_objfmt_section_switch(yasm_objfmt *objfmt, yasm_valparamhead *valparams,
+                           /*@unused@*/ /*@null@*/
+                           yasm_valparamhead *objext_valparams,
+                           unsigned long line)
+{
+    yasm_objfmt_rdf *objfmt_rdf = (yasm_objfmt_rdf *)objfmt;
+    yasm_valparam *vp = yasm_vps_first(valparams);
+    yasm_section *retval;
+    int isnew;
+    unsigned int type = 0xffff;
+    unsigned int reserved = 0;
+    int flags_override = 0;
+    char *sectname;
+    rdf_section_data *rsd;
+
+    static const struct {
+       const char *name;
+       unsigned int type;
+    } typenames[] = {
+       { "bss", RDF_SECT_BSS },
+       { "code", RDF_SECT_CODE },
+       { "text", RDF_SECT_CODE },
+       { "data", RDF_SECT_DATA },
+       { "comment", RDF_SECT_COMMENT },
+       { "lcomment", RDF_SECT_LCOMMENT },
+       { "pcomment", RDF_SECT_PCOMMENT },
+       { "symdebug", RDF_SECT_SYMDEBUG },
+       { "linedebug", RDF_SECT_LINEDEBUG },
+    };
+
+    if (!vp || vp->param || !vp->val)
+       return NULL;
+
+    sectname = vp->val;
+
+    if (strcmp(sectname, ".text") == 0)
+       type = RDF_SECT_CODE;
+    else if (strcmp(sectname, ".data") == 0)
+       type = RDF_SECT_DATA;
+    else if (strcmp(sectname, ".bss") == 0)
+       type = RDF_SECT_BSS;
+
+    /* Look for section type */
+    if ((vp = yasm_vps_next(vp))) {
+       size_t i;
+       int match;
+       if (vp->val) {
+           match = 0;
+           for (i=0; i<NELEMS(typenames) && !match; i++) {
+               if (yasm__strcasecmp(vp->val, typenames[i].name) == 0) {
+                   type = typenames[i].type;
+                   flags_override = 1;
+                   match = 1;
+               }
+           }
+           if (!match)
+               yasm_warn_set(YASM_WARN_GENERAL,
+                             N_("Unrecognized RDF segment type `%s'"),
+                             vp->val);
+       } else
+           yasm_warn_set(YASM_WARN_GENERAL,
+                         N_("Unrecognized numeric qualifier"));
+    }
+
+    if (type == 0xffff) {
+       yasm_error_set(YASM_ERROR_VALUE,
+                      N_("new segment declared without type code"));
+       type = RDF_SECT_DATA;
+    }
+
+    /* Look for reserved value */
+    if (vp && (vp = yasm_vps_next(vp))) {
+        if (!vp->val && vp->param) {
+            /*@dependent@*/ /*@null@*/ const yasm_intnum *reserved_expr;
+
+            reserved_expr = yasm_expr_get_intnum(&vp->param, 0);
+            if (!reserved_expr)
+                yasm_error_set(YASM_ERROR_VALUE,
+                   N_("reserved value must be numeric"));
+            else
+                reserved = yasm_intnum_get_uint(reserved_expr);
+       } else if (vp->val)
+            yasm_warn_set(YASM_WARN_GENERAL, N_("Unrecognized qualifier `%s'"),
+                         vp->val);
+    }
+
+    retval = yasm_object_get_general(objfmt_rdf->object, sectname, 0, 0, 1,
+                                    type == RDF_SECT_BSS, &isnew, line);
+
+    if (isnew)
+       rsd = rdf_objfmt_init_new_section(objfmt_rdf, retval, sectname, line);
+    else
+       rsd = yasm_section_get_data(retval, &rdf_section_data_cb);
+
+    if (isnew || yasm_section_is_default(retval)) {
+       yasm_section_set_default(retval, 0);
+       rsd->type = type;
+       rsd->reserved = reserved;
+    } else if (flags_override)
+       yasm_warn_set(YASM_WARN_GENERAL,
+                     N_("section flags ignored on section redeclaration"));
+    return retval;
+}
+
+static void
+rdf_section_data_destroy(void *data)
+{
+    rdf_section_data *rsd = (rdf_section_data *)data;
+    if (rsd->raw_data)
+       yasm_xfree(rsd->raw_data);
+    yasm_xfree(data);
+}
+
+static void
+rdf_section_data_print(void *data, FILE *f, int indent_level)
+{
+    rdf_section_data *rsd = (rdf_section_data *)data;
+
+    fprintf(f, "%*ssym=\n", indent_level, "");
+    yasm_symrec_print(rsd->sym, f, indent_level+1);
+    fprintf(f, "%*sscnum=%ld\n", indent_level, "", rsd->scnum);
+    fprintf(f, "%*stype=0x%x\n", indent_level, "", rsd->type);
+    fprintf(f, "%*sreserved=0x%x\n", indent_level, "", rsd->reserved);
+    fprintf(f, "%*ssize=%ld\n", indent_level, "", rsd->size);
+}
+
+static yasm_symrec *
+rdf_objfmt_extern_declare(yasm_objfmt *objfmt, const char *name, /*@unused@*/
+                          /*@null@*/ yasm_valparamhead *objext_valparams,
+                          unsigned long line)
+{
+    yasm_objfmt_rdf *objfmt_rdf = (yasm_objfmt_rdf *)objfmt;
+    yasm_symrec *sym;
+    unsigned int flags = 0;
+
+    static const struct {
+       const char *name;
+       unsigned int flags;
+    } flagnames[] = {
+       { "data", SYM_DATA },
+       { "object", SYM_DATA },
+       { "proc", SYM_FUNCTION },
+       { "function", SYM_FUNCTION },
+       { "import", SYM_IMPORT },
+       { "far", SYM_FAR },
+    };
+
+    sym = yasm_symtab_declare(objfmt_rdf->symtab, name, YASM_SYM_EXTERN, line);
+
+    if (objext_valparams) {
+       yasm_valparam *vp = yasm_vps_first(objext_valparams);
+        for (; vp; vp = yasm_vps_next(vp)) {
+           size_t i;
+           int match;
+
+           if (!vp->val) {
+               yasm_warn_set(YASM_WARN_GENERAL,
+                             N_("Unrecognized numeric qualifier"));
+               continue;
+           }
+
+           match = 0;
+           for (i=0; i<NELEMS(flagnames) && !match; i++) {
+               if (yasm__strcasecmp(vp->val, flagnames[i].name) == 0) {
+                   flags |= flagnames[i].flags;
+                   match = 1;
+               }
+           }
+
+           if (yasm__strcasecmp(vp->val, "near") == 0) {
+               flags &= ~SYM_FAR;
+               match = 1;
+           }
+
+           if (!match)
+               yasm_warn_set(YASM_WARN_GENERAL,
+                             N_("Unrecognized qualifier `%s'"), vp->val);
+       }
+    }
+
+    /* Remember flags */
+    rdf_objfmt_sym_set_data(sym, NULL, 0, flags);
+    return sym;
+}
+
+static yasm_symrec *
+rdf_objfmt_global_declare(yasm_objfmt *objfmt, const char *name, /*@unused@*/
+                          /*@null@*/ yasm_valparamhead *objext_valparams,
+                          unsigned long line)
+{
+    yasm_objfmt_rdf *objfmt_rdf = (yasm_objfmt_rdf *)objfmt;
+    yasm_symrec *sym;
+    unsigned int flags = 0;
+
+    static const struct {
+       const char *name;
+       unsigned int flags;
+    } flagnames[] = {
+       { "data", SYM_DATA },
+       { "object", SYM_DATA },
+       { "proc", SYM_FUNCTION },
+       { "function", SYM_FUNCTION },
+       { "export", SYM_GLOBAL },
+    };
+
+    sym = yasm_symtab_declare(objfmt_rdf->symtab, name, YASM_SYM_GLOBAL, line);
+
+    if (objext_valparams) {
+       yasm_valparam *vp = yasm_vps_first(objext_valparams);
+        for (; vp; vp = yasm_vps_next(vp)) {
+           size_t i;
+           int match;
+
+           if (!vp->val) {
+               yasm_warn_set(YASM_WARN_GENERAL,
+                             N_("Unrecognized numeric qualifier"));
+               continue;
+           }
+
+           match = 0;
+           for (i=0; i<NELEMS(flagnames) && !match; i++) {
+               if (yasm__strcasecmp(vp->val, flagnames[i].name) == 0) {
+                   flags |= flagnames[i].flags;
+                   match = 1;
+               }
+           }
+           if (!match)
+               yasm_warn_set(YASM_WARN_GENERAL,
+                             N_("Unrecognized qualifier `%s'"), vp->val);
+       }
+    }
+
+    /* Remember flags */
+    rdf_objfmt_sym_set_data(sym, NULL, 0, flags);
+    return sym;
+}
+
+static yasm_symrec *
+rdf_objfmt_common_declare(yasm_objfmt *objfmt, const char *name,
+                          /*@only@*/ yasm_expr *size,
+                          yasm_valparamhead *objext_valparams,
+                          unsigned long line)
+{
+    yasm_objfmt_rdf *objfmt_rdf = (yasm_objfmt_rdf *)objfmt;
+    yasm_symrec *sym;
+    rdf_symrec_data *rsymd;
+    unsigned long addralign = 0;
+
+    sym = yasm_symtab_declare(objfmt_rdf->symtab, name, YASM_SYM_COMMON, line);
+
+    if (objext_valparams) {
+       yasm_valparam *vp = yasm_vps_first(objext_valparams);
+        for (; vp; vp = yasm_vps_next(vp)) {
+            if (!vp->val && vp->param) {
+                /*@dependent@*/ /*@null@*/ const yasm_intnum *align_expr;
+
+                align_expr = yasm_expr_get_intnum(&vp->param, 0);
+                if (!align_expr) {
+                    yasm_error_set(YASM_ERROR_VALUE,
+                       N_("alignment constraint is not a power of two"));
+                    return sym;
+                }
+                addralign = yasm_intnum_get_uint(align_expr);
+
+                /* Alignments must be a power of two. */
+                if ((addralign & (addralign - 1)) != 0) {
+                    yasm_error_set(YASM_ERROR_VALUE,
+                        N_("alignment constraint is not a power of two"));
+                    return sym;
+                }
+            } else if (vp->val)
+                yasm_warn_set(YASM_WARN_GENERAL,
+                              N_("Unrecognized qualifier `%s'"), vp->val);
+        }
+    }
+
+    /* Remember size and alignment */
+    rdf_objfmt_sym_set_data(sym, size, addralign, 0);
+    return sym;
+}
+
+static void
+rdf_symrec_data_destroy(void *data)
+{
+    rdf_symrec_data *rsymd = (rdf_symrec_data *)data;
+    if (rsymd->size)
+       yasm_expr_destroy(rsymd->size);
+    yasm_xfree(data);
+}
+
+static void
+rdf_symrec_data_print(void *data, FILE *f, int indent_level)
+{
+    rdf_symrec_data *rsymd = (rdf_symrec_data *)data;
+
+    fprintf(f, "%*ssymtab segment=%u\n", indent_level, "", rsymd->segment);
+    fprintf(f, "%*ssize=", indent_level, "");
+    if (rsymd->size)
+       yasm_expr_print(rsymd->size, f);
+    else
+       fprintf(f, "nil");
+    fprintf(f, "%*salign=%lu\n", indent_level, "", rsymd->align);
+}
+
+static int
+rdf_objfmt_directive(yasm_objfmt *objfmt, const char *name,
+                    yasm_valparamhead *valparams,
+                    /*@unused@*/ /*@null@*/
+                    yasm_valparamhead *objext_valparams, unsigned long line)
+{
+    yasm_objfmt_rdf *objfmt_rdf = (yasm_objfmt_rdf *)objfmt;
+    int lib;
+    yasm_valparam *vp;
+    xdf_str *str;
+
+    if (yasm__strcasecmp(name, "library") == 0)
+       lib = 1;
+    else if (yasm__strcasecmp(name, "module") == 0)
+       lib = 0;
+    else
+       return 1;
+
+    vp = yasm_vps_first(valparams);
+    if (!vp->val) {
+       yasm_error_set(YASM_ERROR_SYNTAX, N_("argument to [%s] must be name"),
+                      name);
+       return 0;
+    }
+
+    /* Add to list */
+    str = yasm_xmalloc(sizeof(xdf_str));
+    str->str = vp->val;
+    if (lib)
+       STAILQ_INSERT_TAIL(&objfmt_rdf->library_names, str, link);
+    else
+       STAILQ_INSERT_TAIL(&objfmt_rdf->module_names, str, link);
+
+    if (strlen(str->str) > MODLIB_NAME_MAX-1) {
+       yasm_warn_set(YASM_WARN_GENERAL,
+                     N_("name too long, truncating to %d bytes"),
+                     MODLIB_NAME_MAX);
+       str->str[MODLIB_NAME_MAX-1] = '\0';
+    }
+
+    vp->val = NULL;    /* don't free it */
+    return 0;
+}
+
+
+/* Define valid debug formats to use with this object format */
+static const char *rdf_objfmt_dbgfmt_keywords[] = {
+    "null",
+    NULL
+};
+
+/* Define objfmt structure -- see objfmt.h for details */
+yasm_objfmt_module yasm_rdf_LTX_objfmt = {
+    "Relocatable Dynamic Object File Format (RDOFF) v2.0",
+    "rdf",
+    "rdf",
+    32,
+    rdf_objfmt_dbgfmt_keywords,
+    "null",
+    rdf_objfmt_create,
+    rdf_objfmt_output,
+    rdf_objfmt_destroy,
+    rdf_objfmt_add_default_section,
+    rdf_objfmt_section_switch,
+    rdf_objfmt_extern_declare,
+    rdf_objfmt_global_declare,
+    rdf_objfmt_common_declare,
+    rdf_objfmt_directive
+};
diff --git a/modules/objfmts/rdf/tests/Makefile.inc b/modules/objfmts/rdf/tests/Makefile.inc
new file mode 100644 (file)
index 0000000..39f6aab
--- /dev/null
@@ -0,0 +1,25 @@
+# $Id$
+
+TESTS += modules/objfmts/rdf/tests/rdf_test.sh
+
+EXTRA_DIST += modules/objfmts/rdf/tests/rdf_test.sh
+EXTRA_DIST += modules/objfmts/rdf/tests/rdfabs.asm
+EXTRA_DIST += modules/objfmts/rdf/tests/rdfabs.errwarn
+EXTRA_DIST += modules/objfmts/rdf/tests/rdfabs.hex
+EXTRA_DIST += modules/objfmts/rdf/tests/rdfext.asm
+EXTRA_DIST += modules/objfmts/rdf/tests/rdfext.hex
+EXTRA_DIST += modules/objfmts/rdf/tests/rdfseg.asm
+EXTRA_DIST += modules/objfmts/rdf/tests/rdfseg.hex
+EXTRA_DIST += modules/objfmts/rdf/tests/rdfseg2.asm
+EXTRA_DIST += modules/objfmts/rdf/tests/rdfseg2.hex
+EXTRA_DIST += modules/objfmts/rdf/tests/rdftest1.asm
+EXTRA_DIST += modules/objfmts/rdf/tests/rdftest1.hex
+EXTRA_DIST += modules/objfmts/rdf/tests/rdftest2.asm
+EXTRA_DIST += modules/objfmts/rdf/tests/rdftest2.hex
+EXTRA_DIST += modules/objfmts/rdf/tests/rdtlib.asm
+EXTRA_DIST += modules/objfmts/rdf/tests/rdtlib.hex
+EXTRA_DIST += modules/objfmts/rdf/tests/rdtmain.asm
+EXTRA_DIST += modules/objfmts/rdf/tests/rdtmain.hex
+EXTRA_DIST += modules/objfmts/rdf/tests/testlib.asm
+EXTRA_DIST += modules/objfmts/rdf/tests/testlib.hex
+
diff --git a/modules/objfmts/rdf/tests/rdf_test.sh b/modules/objfmts/rdf/tests/rdf_test.sh
new file mode 100755 (executable)
index 0000000..9161c37
--- /dev/null
@@ -0,0 +1,4 @@
+#! /bin/sh
+# $Id$
+${srcdir}/out_test.sh rdf_test modules/objfmts/rdf/tests "rdf objfmt" "-f rdf" ".rdf"
+exit $?
diff --git a/modules/objfmts/rdf/tests/rdfabs.asm b/modules/objfmts/rdf/tests/rdfabs.asm
new file mode 100644 (file)
index 0000000..c6de90d
--- /dev/null
@@ -0,0 +1,7 @@
+absolute 0x5000
+label
+
+label2 equ 0x9999
+
+global label
+global label2
diff --git a/modules/objfmts/rdf/tests/rdfabs.errwarn b/modules/objfmts/rdf/tests/rdfabs.errwarn
new file mode 100644 (file)
index 0000000..19ecde3
--- /dev/null
@@ -0,0 +1,2 @@
+-:2: warning: rdf does not support exporting EQU/absolute values
+-:4: warning: rdf does not support exporting EQU/absolute values
diff --git a/modules/objfmts/rdf/tests/rdfabs.hex b/modules/objfmts/rdf/tests/rdfabs.hex
new file mode 100644 (file)
index 0000000..ad42b02
--- /dev/null
@@ -0,0 +1,24 @@
+52 
+44 
+4f 
+46 
+46 
+32 
+0e 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
diff --git a/modules/objfmts/rdf/tests/rdfext.asm b/modules/objfmts/rdf/tests/rdfext.asm
new file mode 100644 (file)
index 0000000..8bf5ea0
--- /dev/null
@@ -0,0 +1,63 @@
+module thismodule
+module $thismodule
+global foo:export
+global bar:export proc
+global bar2:export function
+global baz:export data
+global baz2:export object
+extern extvar:import
+extern func:proc
+extern farfunc:far
+library alib.rdl
+common cvar 16:32
+
+foo:
+dd 0
+bar:
+dd 0
+bar2:
+dd 0
+call func
+call farfunc           ; generates a near call!
+call far farfunc
+
+mov ax, seg farfunc
+mov ax, farfunc
+mov eax, farfunc
+
+mov eax, cvar
+
+section .data
+baz:
+dd 0
+baz2:
+dd 0
+
+section .bss
+resb 4
+
+;section a null
+
+section b text
+dd 0
+
+section c code
+dd 0
+
+section d data
+dd 0
+
+section e comment,5            ; after comma is reserved value
+dd 0
+
+section f lcomment
+dd 0
+
+section g pcomment,8
+dd 0
+
+section h symdebug
+dd 0
+
+section i linedebug
+dd 0
diff --git a/modules/objfmts/rdf/tests/rdfext.hex b/modules/objfmts/rdf/tests/rdfext.hex
new file mode 100644 (file)
index 0000000..1369313
--- /dev/null
@@ -0,0 +1,447 @@
+52 
+44 
+4f 
+46 
+46 
+32 
+b5 
+01 
+00 
+00 
+ec 
+00 
+00 
+00 
+08 
+0b 
+74 
+68 
+69 
+73 
+6d 
+6f 
+64 
+75 
+6c 
+65 
+00 
+08 
+0c 
+24 
+74 
+68 
+69 
+73 
+6d 
+6f 
+64 
+75 
+6c 
+65 
+00 
+04 
+09 
+61 
+6c 
+69 
+62 
+2e 
+72 
+64 
+6c 
+00 
+03 
+0a 
+04 
+00 
+00 
+00 
+00 
+00 
+66 
+6f 
+6f 
+00 
+03 
+0a 
+06 
+00 
+04 
+00 
+00 
+00 
+62 
+61 
+72 
+00 
+03 
+0b 
+06 
+00 
+08 
+00 
+00 
+00 
+62 
+61 
+72 
+32 
+00 
+03 
+0a 
+05 
+01 
+00 
+00 
+00 
+00 
+62 
+61 
+7a 
+00 
+03 
+0b 
+05 
+01 
+04 
+00 
+00 
+00 
+62 
+61 
+7a 
+32 
+00 
+02 
+0a 
+08 
+0b 
+00 
+65 
+78 
+74 
+76 
+61 
+72 
+00 
+02 
+08 
+02 
+0c 
+00 
+66 
+75 
+6e 
+63 
+00 
+07 
+0b 
+00 
+0d 
+00 
+66 
+61 
+72 
+66 
+75 
+6e 
+63 
+00 
+0a 
+0d 
+0e 
+00 
+10 
+00 
+00 
+00 
+20 
+00 
+63 
+76 
+61 
+72 
+00 
+01 
+08 
+40 
+0d 
+00 
+00 
+00 
+04 
+0c 
+00 
+01 
+08 
+40 
+12 
+00 
+00 
+00 
+04 
+0d 
+00 
+01 
+08 
+00 
+17 
+00 
+00 
+00 
+04 
+0d 
+00 
+06 
+08 
+00 
+1b 
+00 
+00 
+00 
+02 
+0d 
+00 
+06 
+08 
+00 
+1f 
+00 
+00 
+00 
+02 
+0d 
+00 
+01 
+08 
+00 
+23 
+00 
+00 
+00 
+02 
+0d 
+00 
+01 
+08 
+00 
+26 
+00 
+00 
+00 
+04 
+0d 
+00 
+01 
+08 
+00 
+2b 
+00 
+00 
+00 
+04 
+0e 
+00 
+05 
+04 
+04 
+00 
+00 
+00 
+01 
+00 
+00 
+00 
+00 
+00 
+2f 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+e8 
+ef 
+ff 
+ff 
+ff 
+e8 
+ea 
+ff 
+ff 
+ff 
+9a 
+00 
+00 
+00 
+00 
+00 
+00 
+66 
+b8 
+00 
+00 
+66 
+b8 
+00 
+00 
+b8 
+00 
+00 
+00 
+00 
+b8 
+00 
+00 
+00 
+00 
+02 
+00 
+01 
+00 
+00 
+00 
+08 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+01 
+00 
+03 
+00 
+00 
+00 
+04 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+01 
+00 
+04 
+00 
+00 
+00 
+04 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+02 
+00 
+05 
+00 
+00 
+00 
+04 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+03 
+00 
+06 
+00 
+05 
+00 
+04 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+04 
+00 
+07 
+00 
+00 
+00 
+04 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+05 
+00 
+08 
+00 
+08 
+00 
+04 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+06 
+00 
+09 
+00 
+00 
+00 
+04 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+07 
+00 
+0a 
+00 
+00 
+00 
+04 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
diff --git a/modules/objfmts/rdf/tests/rdfseg.asm b/modules/objfmts/rdf/tests/rdfseg.asm
new file mode 100644 (file)
index 0000000..4c6f587
--- /dev/null
@@ -0,0 +1,20 @@
+       ;; program to test inter-segment production and linkage of RDF objects
+
+       ;; [1] should produce segment base ref
+       ;; [2] should produce standard relocation
+       
+[GLOBAL _main]
+[EXTERN _puts: far]
+[BITS 16]
+       
+_main:
+       mov ax, seg _message    ; 0000 [1]
+       mov ds, ax              ; 0003
+       mov dx, _message        ; 0005 [2]
+       call far _puts          ; 0008 [2][1]
+       xor ax,ax               ; 000D
+       int 21h                 ; 000F
+       
+[SECTION .data]
+_message:      db 'Hello, World', 10, 13, 0
+       
\ No newline at end of file
diff --git a/modules/objfmts/rdf/tests/rdfseg.hex b/modules/objfmts/rdf/tests/rdfseg.hex
new file mode 100644 (file)
index 0000000..302ceb5
--- /dev/null
@@ -0,0 +1,141 @@
+52 
+44 
+4f 
+46 
+46 
+32 
+83 
+00 
+00 
+00 
+41 
+00 
+00 
+00 
+03 
+0c 
+00 
+00 
+00 
+00 
+00 
+00 
+5f 
+6d 
+61 
+69 
+6e 
+00 
+07 
+09 
+00 
+02 
+00 
+5f 
+70 
+75 
+74 
+73 
+00 
+06 
+08 
+00 
+01 
+00 
+00 
+00 
+02 
+01 
+00 
+01 
+08 
+00 
+06 
+00 
+00 
+00 
+02 
+01 
+00 
+01 
+08 
+00 
+09 
+00 
+00 
+00 
+02 
+02 
+00 
+06 
+08 
+00 
+0b 
+00 
+00 
+00 
+02 
+02 
+00 
+01 
+00 
+00 
+00 
+00 
+00 
+11 
+00 
+00 
+00 
+b8 
+00 
+00 
+8e 
+d8 
+ba 
+00 
+00 
+9a 
+00 
+00 
+00 
+00 
+31 
+c0 
+cd 
+21 
+02 
+00 
+01 
+00 
+00 
+00 
+0f 
+00 
+00 
+00 
+48 
+65 
+6c 
+6c 
+6f 
+2c 
+20 
+57 
+6f 
+72 
+6c 
+64 
+0a 
+0d 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
diff --git a/modules/objfmts/rdf/tests/rdfseg2.asm b/modules/objfmts/rdf/tests/rdfseg2.asm
new file mode 100644 (file)
index 0000000..2b9e4fd
--- /dev/null
@@ -0,0 +1,12 @@
+       ;; library function for rdfseg - this file is linked as a far segment
+
+[BITS 16]
+[GLOBAL _puts]
+_puts:
+       ;; can't remember how to print a string in DOS, but if anyone wants
+       ;; to actually test this program, it should be fairly easy to put
+       ;; in here!
+
+       retf
+
+       
\ No newline at end of file
diff --git a/modules/objfmts/rdf/tests/rdfseg2.hex b/modules/objfmts/rdf/tests/rdfseg2.hex
new file mode 100644 (file)
index 0000000..157a99a
--- /dev/null
@@ -0,0 +1,49 @@
+52 
+44 
+4f 
+46 
+46 
+32 
+27 
+00 
+00 
+00 
+0e 
+00 
+00 
+00 
+03 
+0c 
+00 
+00 
+00 
+00 
+00 
+00 
+5f 
+70 
+75 
+74 
+73 
+00 
+01 
+00 
+00 
+00 
+00 
+00 
+01 
+00 
+00 
+00 
+cb 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
diff --git a/modules/objfmts/rdf/tests/rdftest1.asm b/modules/objfmts/rdf/tests/rdftest1.asm
new file mode 100644 (file)
index 0000000..76f1e43
--- /dev/null
@@ -0,0 +1,54 @@
+       ;; program to test RDOFF production and linkage
+
+       ;; items to test include:
+       ;;      [1] relocation within the same segment in each module
+       ;;      [2] relocation to different segments in same module
+       ;;      [3] relocation to same segment in different module
+       ;;      [4] relocation to different segment in different module
+       ;;      [5] relative relocation to same module
+       ;;      [6] relative relocation to different module
+       ;;      [7] correct generation of BSS addresses
+
+[SECTION .text]
+[BITS 32]
+       
+_main:
+       mov ax,localdata        ; [2] (16 bit) => 66 b8 0000
+       mov eax,localdata2      ; [2] (32 bit) => b8 0000000a
+
+[EXTERN _fardata]
+
+       mov eax,[_fardata]      ; [4] => a1 00000000 (+20)
+       mov cx,next             ; [1] => 66 b9 0012
+next:
+       call localproc          ; [5] => e8 00000019
+
+[EXTERN _farproc]
+       mov eax,_farproc        ; [3] => b8 00000000 (+40+0)
+       call _farproc           ; [6] => e8 -$ (-0+40+0) (=1f)
+
+       mov eax,localbss        ; [7] => b8 00000000
+
+[GLOBAL _term]
+_term: xor ax,ax               ; => 66 31 c0
+       int 21h                 ; => cd 21
+       jmp _term               ; => e9 -0a (=fffffff6)
+
+localproc:     
+       ret                     ; => c3
+
+[GLOBAL _test1proc]
+_test1proc:
+       call localproc          ; [5] => e8 -$ (-0+0+?) (=-6=fffffffa)
+       ret                     ; => c3
+                       
+[SECTION .data]
+[GLOBAL localdata2]
+localdata:     db 'localdata',0
+localdata2:    db 'localdata2',0
+farref:                dd _fardata     ; [3] => 0 (+20)
+localref:      dd _main        ; [2] => 0 (+0)
+
+[SECTION .bss]
+localbss:      resw 4          ; reserve 8 bytes BSS
+       
\ No newline at end of file
diff --git a/modules/objfmts/rdf/tests/rdftest1.hex b/modules/objfmts/rdf/tests/rdftest1.hex
new file mode 100644 (file)
index 0000000..a8a86bc
--- /dev/null
@@ -0,0 +1,301 @@
+52 
+44 
+4f 
+46 
+46 
+32 
+23 
+01 
+00 
+00 
+b0 
+00 
+00 
+00 
+03 
+11 
+00 
+01 
+0a 
+00 
+00 
+00 
+6c 
+6f 
+63 
+61 
+6c 
+64 
+61 
+74 
+61 
+32 
+00 
+02 
+0c 
+00 
+03 
+00 
+5f 
+66 
+61 
+72 
+64 
+61 
+74 
+61 
+00 
+02 
+0c 
+00 
+04 
+00 
+5f 
+66 
+61 
+72 
+70 
+72 
+6f 
+63 
+00 
+03 
+0c 
+00 
+00 
+26 
+00 
+00 
+00 
+5f 
+74 
+65 
+72 
+6d 
+00 
+03 
+11 
+00 
+00 
+2e 
+00 
+00 
+00 
+5f 
+74 
+65 
+73 
+74 
+31 
+70 
+72 
+6f 
+63 
+00 
+01 
+08 
+00 
+02 
+00 
+00 
+00 
+02 
+01 
+00 
+01 
+08 
+00 
+05 
+00 
+00 
+00 
+04 
+01 
+00 
+01 
+08 
+00 
+0a 
+00 
+00 
+00 
+04 
+03 
+00 
+01 
+08 
+00 
+10 
+00 
+00 
+00 
+02 
+00 
+00 
+01 
+08 
+00 
+18 
+00 
+00 
+00 
+04 
+04 
+00 
+01 
+08 
+40 
+1d 
+00 
+00 
+00 
+04 
+04 
+00 
+01 
+08 
+00 
+22 
+00 
+00 
+00 
+04 
+02 
+00 
+01 
+08 
+01 
+15 
+00 
+00 
+00 
+04 
+03 
+00 
+01 
+08 
+01 
+19 
+00 
+00 
+00 
+04 
+00 
+00 
+05 
+04 
+08 
+00 
+00 
+00 
+01 
+00 
+00 
+00 
+00 
+00 
+34 
+00 
+00 
+00 
+66 
+b8 
+00 
+00 
+b8 
+0a 
+00 
+00 
+00 
+a1 
+00 
+00 
+00 
+00 
+66 
+b9 
+12 
+00 
+e8 
+16 
+00 
+00 
+00 
+b8 
+00 
+00 
+00 
+00 
+e8 
+df 
+ff 
+ff 
+ff 
+b8 
+00 
+00 
+00 
+00 
+66 
+31 
+c0 
+cd 
+21 
+eb 
+f9 
+c3 
+e8 
+fa 
+ff 
+ff 
+ff 
+c3 
+02 
+00 
+01 
+00 
+00 
+00 
+1d 
+00 
+00 
+00 
+6c 
+6f 
+63 
+61 
+6c 
+64 
+61 
+74 
+61 
+00 
+6c 
+6f 
+63 
+61 
+6c 
+64 
+61 
+74 
+61 
+32 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
diff --git a/modules/objfmts/rdf/tests/rdftest2.asm b/modules/objfmts/rdf/tests/rdftest2.asm
new file mode 100644 (file)
index 0000000..25b8c18
--- /dev/null
@@ -0,0 +1,33 @@
+       ;; rdftest2.asm - test linkage and generation of RDOFF files
+
+[SECTION .text]
+[BITS 32]
+
+[GLOBAL _farproc]
+[EXTERN _test1proc]
+[EXTERN localdata2]
+[EXTERN _term]
+_farproc:
+       
+       mov bx,localdata2       ; [4] 0 => 66 bb 000a(+0)
+       mov eax,_term           ; [3] 5 => b8 00000000(+26+0)
+       call _test1proc         ; [6] A => e8 fffffff2(-40+0+31)(=ffffffe3)
+
+       mov eax,_farproc        ; [1] => b8 00000000(+40)
+       add eax,[_fardata]      ; [2] => 03 05 00000000(+20)
+
+       mov ebx,mybssdata       ; [7] => bb 00000000(+08)
+       call myproc             ; [5] => e8 00000001
+       ret
+
+myproc:
+       add eax,ebx
+       ret
+       
+[SECTION .data]
+[GLOBAL _fardata]
+_fardata:      dw _term        ; [4]
+_localref:     dd _farproc     ; [2]
+
+[SECTION .bss]
+mybssdata:     resw 1
diff --git a/modules/objfmts/rdf/tests/rdftest2.hex b/modules/objfmts/rdf/tests/rdftest2.hex
new file mode 100644 (file)
index 0000000..1e6b89f
--- /dev/null
@@ -0,0 +1,252 @@
+52 
+44 
+4f 
+46 
+46 
+32 
+f2 
+00 
+00 
+00 
+a3 
+00 
+00 
+00 
+03 
+0f 
+00 
+00 
+00 
+00 
+00 
+00 
+5f 
+66 
+61 
+72 
+70 
+72 
+6f 
+63 
+00 
+02 
+0e 
+00 
+03 
+00 
+5f 
+74 
+65 
+73 
+74 
+31 
+70 
+72 
+6f 
+63 
+00 
+02 
+0e 
+00 
+04 
+00 
+6c 
+6f 
+63 
+61 
+6c 
+64 
+61 
+74 
+61 
+32 
+00 
+02 
+09 
+00 
+05 
+00 
+5f 
+74 
+65 
+72 
+6d 
+00 
+03 
+0f 
+00 
+01 
+00 
+00 
+00 
+00 
+5f 
+66 
+61 
+72 
+64 
+61 
+74 
+61 
+00 
+01 
+08 
+00 
+02 
+00 
+00 
+00 
+02 
+04 
+00 
+01 
+08 
+00 
+05 
+00 
+00 
+00 
+04 
+05 
+00 
+01 
+08 
+40 
+0a 
+00 
+00 
+00 
+04 
+03 
+00 
+01 
+08 
+00 
+0f 
+00 
+00 
+00 
+04 
+00 
+00 
+01 
+08 
+00 
+15 
+00 
+00 
+00 
+04 
+01 
+00 
+01 
+08 
+00 
+1a 
+00 
+00 
+00 
+04 
+02 
+00 
+01 
+08 
+01 
+00 
+00 
+00 
+00 
+02 
+05 
+00 
+01 
+08 
+01 
+02 
+00 
+00 
+00 
+04 
+00 
+00 
+05 
+04 
+02 
+00 
+00 
+00 
+01 
+00 
+00 
+00 
+00 
+00 
+27 
+00 
+00 
+00 
+66 
+bb 
+00 
+00 
+b8 
+00 
+00 
+00 
+00 
+e8 
+f2 
+ff 
+ff 
+ff 
+b8 
+00 
+00 
+00 
+00 
+03 
+05 
+00 
+00 
+00 
+00 
+bb 
+00 
+00 
+00 
+00 
+e8 
+01 
+00 
+00 
+00 
+c3 
+01 
+d8 
+c3 
+02 
+00 
+01 
+00 
+00 
+00 
+06 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
diff --git a/modules/objfmts/rdf/tests/rdtlib.asm b/modules/objfmts/rdf/tests/rdtlib.asm
new file mode 100644 (file)
index 0000000..6c2b8ec
--- /dev/null
@@ -0,0 +1,48 @@
+       ;; library functions for rdtmain - test of rdx linking and execution
+
+       ;; library function = _strcmp, defined as in C
+
+[SECTION .text]
+[BITS 32]
+
+[GLOBAL _strcmp]
+_strcmp:
+       push ebp
+       mov ebp,esp
+
+       ;; ebp+8 = first paramater, ebp+12 = second
+
+       mov esi,[ebp+8]
+       mov edi,[ebp+12]
+
+.loop:
+       mov cl,byte [esi]
+       mov dl,byte [edi]
+       cmp cl,dl
+       jb .below
+       ja .above
+       or cl,cl
+       jz .match
+       inc esi
+       inc edi
+       jmp .loop
+
+.below:        
+       mov eax,-1
+       pop ebp
+       ret
+       
+.above:
+       mov eax,1
+       pop ebp
+       ret
+
+.match:
+       xor eax,eax
+       pop ebp
+       ret
+
+[SECTION .data]
+[GLOBAL _message]
+
+_message:      db 'hello',0
\ No newline at end of file
diff --git a/modules/objfmts/rdf/tests/rdtlib.hex b/modules/objfmts/rdf/tests/rdtlib.hex
new file mode 100644 (file)
index 0000000..107b0ab
--- /dev/null
@@ -0,0 +1,128 @@
+52 
+44 
+4f 
+46 
+46 
+32 
+76 
+00 
+00 
+00 
+21 
+00 
+00 
+00 
+03 
+0e 
+00 
+00 
+00 
+00 
+00 
+00 
+5f 
+73 
+74 
+72 
+63 
+6d 
+70 
+00 
+03 
+0f 
+00 
+01 
+00 
+00 
+00 
+00 
+5f 
+6d 
+65 
+73 
+73 
+61 
+67 
+65 
+00 
+01 
+00 
+00 
+00 
+00 
+00 
+2d 
+00 
+00 
+00 
+55 
+89 
+e5 
+8b 
+75 
+08 
+8b 
+7d 
+0c 
+8a 
+0e 
+8a 
+17 
+38 
+d1 
+72 
+0a 
+77 
+0f 
+08 
+c9 
+74 
+12 
+46 
+47 
+eb 
+ee 
+b8 
+ff 
+ff 
+ff 
+ff 
+5d 
+c3 
+b8 
+01 
+00 
+00 
+00 
+5d 
+c3 
+31 
+c0 
+5d 
+c3 
+02 
+00 
+01 
+00 
+00 
+00 
+06 
+00 
+00 
+00 
+68 
+65 
+6c 
+6c 
+6f 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
diff --git a/modules/objfmts/rdf/tests/rdtmain.asm b/modules/objfmts/rdf/tests/rdtmain.asm
new file mode 100644 (file)
index 0000000..626a2e2
--- /dev/null
@@ -0,0 +1,47 @@
+       ;; rdtmain - main part of test program for RDX execution.
+       ;; returns true (0) if its parameter equals the phrase "hello"
+       ;; "hello" is stored in the library part, to complicate the
+       ;; linkage.
+
+       ;; assemble and link with the following commands:
+       ;; nasm -f rdf rdtmain.asm
+       ;; nasm -f rdf rdtlib.asm
+       ;; ldrdf rdtmain.rdf rdtlib.rdf -o rdxtest.rdx
+
+       ;; run with 'rdx rdxtest.rdx [parameters]' on a Linux (or possibly
+       ;; other 32 bit OS) systems (x86 architectures only!)
+       ;; try using '&& echo Yes' afterwards to find out when it returns 0.
+       
+[EXTERN _strcmp]               ; strcmp is an imported function
+[EXTERN _message]              ; imported data
+[SECTION .text]
+[BITS 32]
+
+       ;; main(int argc,char **argv)
+[GLOBAL _main]
+_main:
+       push ebp
+       mov ebp,esp
+
+       ;; ebp+8 = argc, ebp+12 = argv
+
+       cmp dword [ebp+8],2
+       jb error                ; cause error if < 1 parameters
+
+       mov eax, [ebp+12]       ; eax = argv
+
+       mov ebx, [eax+4]        ; ebx = argv[1]
+       mov ecx, _message       ; ecx = "hello"
+
+       push ecx
+       push ebx
+       call _strcmp            ; compare strings
+       add esp,8               ; caller clears stack
+       
+       pop ebp
+       ret                     ; return return value of _strcmp
+       
+error:
+       mov eax,2               ; return 2 on error
+       pop ebp
+       ret
diff --git a/modules/objfmts/rdf/tests/rdtmain.hex b/modules/objfmts/rdf/tests/rdtmain.hex
new file mode 100644 (file)
index 0000000..5af817d
--- /dev/null
@@ -0,0 +1,134 @@
+52 
+44 
+4f 
+46 
+46 
+32 
+7c 
+00 
+00 
+00 
+3d 
+00 
+00 
+00 
+02 
+0b 
+00 
+01 
+00 
+5f 
+73 
+74 
+72 
+63 
+6d 
+70 
+00 
+02 
+0c 
+00 
+02 
+00 
+5f 
+6d 
+65 
+73 
+73 
+61 
+67 
+65 
+00 
+03 
+0c 
+00 
+00 
+00 
+00 
+00 
+00 
+5f 
+6d 
+61 
+69 
+6e 
+00 
+01 
+08 
+00 
+10 
+00 
+00 
+00 
+04 
+02 
+00 
+01 
+08 
+40 
+17 
+00 
+00 
+00 
+04 
+01 
+00 
+01 
+00 
+00 
+00 
+00 
+00 
+27 
+00 
+00 
+00 
+55 
+89 
+e5 
+83 
+7d 
+08 
+02 
+72 
+17 
+8b 
+45 
+0c 
+8b 
+58 
+04 
+b9 
+00 
+00 
+00 
+00 
+51 
+53 
+e8 
+e5 
+ff 
+ff 
+ff 
+83 
+c4 
+08 
+5d 
+c3 
+b8 
+02 
+00 
+00 
+00 
+5d 
+c3 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
diff --git a/modules/objfmts/rdf/tests/testlib.asm b/modules/objfmts/rdf/tests/testlib.asm
new file mode 100644 (file)
index 0000000..6ee3d89
--- /dev/null
@@ -0,0 +1,18 @@
+; program to test retrieval of and linkage to modules in libraries by
+; ldrdf
+
+[SECTION .text]
+[GLOBAL _main]
+[EXTERN _strcmp]
+
+_main:
+       push dword string1
+       push dword string2
+       call _strcmp
+       add esp,8               ; doh! clear up stack ;-)
+       ret
+
+[SECTION .data]
+
+string1:       db 'abc',0      ; try changing these strings and see
+string2:       db 'abd',0      ; what happens!
diff --git a/modules/objfmts/rdf/tests/testlib.hex b/modules/objfmts/rdf/tests/testlib.hex
new file mode 100644 (file)
index 0000000..0067d61
--- /dev/null
@@ -0,0 +1,128 @@
+52 
+44 
+4f 
+46 
+46 
+32 
+76 
+00 
+00 
+00 
+39 
+00 
+00 
+00 
+03 
+0c 
+00 
+00 
+00 
+00 
+00 
+00 
+5f 
+6d 
+61 
+69 
+6e 
+00 
+02 
+0b 
+00 
+02 
+00 
+5f 
+73 
+74 
+72 
+63 
+6d 
+70 
+00 
+01 
+08 
+00 
+01 
+00 
+00 
+00 
+04 
+01 
+00 
+01 
+08 
+00 
+06 
+00 
+00 
+00 
+04 
+01 
+00 
+01 
+08 
+40 
+0b 
+00 
+00 
+00 
+04 
+02 
+00 
+01 
+00 
+00 
+00 
+00 
+00 
+13 
+00 
+00 
+00 
+68 
+00 
+00 
+00 
+00 
+68 
+04 
+00 
+00 
+00 
+e8 
+f1 
+ff 
+ff 
+ff 
+83 
+c4 
+08 
+c3 
+02 
+00 
+01 
+00 
+00 
+00 
+08 
+00 
+00 
+00 
+61 
+62 
+63 
+00 
+61 
+62 
+64 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
index 01ea7fe203ecee4e0f0ce4deaae17f0f25a1e30b..56323a31f40d78bfe432007cab2920bfabbb3019 100644 (file)
@@ -177,3 +177,12 @@ __SECT__
 %endmacro
 %endif
 
+%ifidn __YASM_OBJFMT__,rdf
+%imacro library 1+.nolist
+[library %1]
+%endmacro
+%imacro module 1+.nolist
+[module %1]
+%endmacro
+%endif
+