145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*
245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * NASM-style list format
345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *
445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *  Copyright (C) 2004-2007  Peter Johnson
545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *
645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Redistribution and use in source and binary forms, with or without
745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * modification, are permitted provided that the following conditions
845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * are met:
945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * 1. Redistributions of source code must retain the above copyright
1045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *    notice, this list of conditions and the following disclaimer.
1145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * 2. Redistributions in binary form must reproduce the above copyright
1245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *    notice, this list of conditions and the following disclaimer in the
1345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *    documentation and/or other materials provided with the distribution.
1445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *
1545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
1645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
1945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * POSSIBILITY OF SUCH DAMAGE.
2645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
2745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include <util.h>
2845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
2945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include <libyasm.h>
3045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
3145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* NOTE: For this code to generate relocation information, the relocations
3245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * have to be added by the object format to each section in program source
3345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * order.
3445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *
3545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * This should not be an issue, as program source order == section bytecode
3645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * order, so unless the object formats are very obtuse with their bytecode
3745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * iteration, this should just happen.
3845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
3945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
4045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#define REGULAR_BUF_SIZE    1024
4145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
4245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_listfmt_module yasm_nasm_LTX_listfmt;
4345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
4445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgtypedef struct sectreloc {
4545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*@reldef@*/ SLIST_ENTRY(sectreloc) link;
4645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_section *sect;
4745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*@null@*/ yasm_reloc *next_reloc;  /* next relocation in section */
4845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned long next_reloc_addr;
4945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} sectreloc;
5045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
5145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgtypedef struct bcreloc {
5245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*@reldef@*/ STAILQ_ENTRY(bcreloc) link;
5345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned long offset;       /* start of reloc from start of bytecode */
5445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    size_t size;                /* size of reloc in bytes */
5545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int rel;                    /* PC/IP-relative or "absolute" */
5645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} bcreloc;
5745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
5845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgtypedef struct nasm_listfmt_output_info {
5945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_arch *arch;
6045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*@reldef@*/ STAILQ_HEAD(bcrelochead, bcreloc) bcrelocs;
6145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*@null@*/ yasm_reloc *next_reloc;  /* next relocation in section */
6245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned long next_reloc_addr;
6345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} nasm_listfmt_output_info;
6445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
6545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
6645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic /*@null@*/ /*@only@*/ yasm_listfmt *
6745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgnasm_listfmt_create(const char *in_filename, const char *obj_filename)
6845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
6945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_listfmt_base *listfmt = yasm_xmalloc(sizeof(yasm_listfmt_base));
7045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    listfmt->module = &yasm_nasm_LTX_listfmt;
7145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return (yasm_listfmt *)listfmt;
7245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
7345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
7445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void
7545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgnasm_listfmt_destroy(/*@only@*/ yasm_listfmt *listfmt)
7645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
7745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_xfree(listfmt);
7845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
7945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
8045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int
8145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgnasm_listfmt_output_value(yasm_value *value, unsigned char *buf,
8245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                          unsigned int destsize, unsigned long offset,
8345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                          yasm_bytecode *bc, int warn, /*@null@*/ void *d)
8445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
8545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*@null@*/ nasm_listfmt_output_info *info = (nasm_listfmt_output_info *)d;
8645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*@dependent@*/ /*@null@*/ yasm_intnum *intn;
8745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned int valsize = value->size;
8845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
8945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    assert(info != NULL);
9045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
9145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Output */
9245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    switch (yasm_value_output_basic(value, buf, destsize, bc, warn,
9345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                    info->arch)) {
9445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case -1:
9545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return 1;
9645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case 0:
9745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            break;
9845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        default:
9945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return 0;
10045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
10145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
10245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Generate reloc if needed */
10345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (info->next_reloc && info->next_reloc_addr == bc->offset+offset) {
10445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        bcreloc *reloc = yasm_xmalloc(sizeof(bcreloc));
10545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        reloc->offset = offset;
10645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        reloc->size = destsize;
10745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        reloc->rel = value->curpos_rel;
10845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        STAILQ_INSERT_TAIL(&info->bcrelocs, reloc, link);
10945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
11045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* Get next reloc's info */
11145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        info->next_reloc = yasm_section_reloc_next(info->next_reloc);
11245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (info->next_reloc) {
11345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_intnum *addr;
11445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_symrec *sym;
11545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_reloc_get(info->next_reloc, &addr, &sym);
11645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            info->next_reloc_addr = yasm_intnum_get_uint(addr);
11745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
11845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
11945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
12045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (value->abs) {
12145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        intn = yasm_expr_get_intnum(&value->abs, 0);
12245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (intn)
12345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return yasm_arch_intnum_tobytes(info->arch, intn, buf, destsize,
12445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                            valsize, 0, bc, 0);
12545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else {
12645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_error_set(YASM_ERROR_TOO_COMPLEX,
12745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                           N_("relocation too complex"));
12845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return 1;
12945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
13045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    } else {
13145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        int retval;
13245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        intn = yasm_intnum_create_uint(0);
13345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        retval = yasm_arch_intnum_tobytes(info->arch, intn, buf, destsize,
13445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                          valsize, 0, bc, 0);
13545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_intnum_destroy(intn);
13645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return retval;
13745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
13845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
13945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return 0;
14045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
14145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
14245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void
14345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgnasm_listfmt_output(yasm_listfmt *listfmt, FILE *f, yasm_linemap *linemap,
14445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    yasm_arch *arch)
14545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
14645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_bytecode *bc;
14745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    const char *source;
14845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned long line = 1;
14945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned long listline = 1;
15045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*@only@*/ unsigned char *buf;
15145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    nasm_listfmt_output_info info;
15245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*@reldef@*/ SLIST_HEAD(sectrelochead, sectreloc) reloc_hist;
15345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*@null@*/ sectreloc *last_hist = NULL;
15445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*@null@*/ bcreloc *reloc = NULL;
15545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_section *sect;
15645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
15745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    SLIST_INIT(&reloc_hist);
15845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
15945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    info.arch = arch;
16045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
16145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    buf = yasm_xmalloc(REGULAR_BUF_SIZE);
16245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
16345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while (!yasm_linemap_get_source(linemap, line, &bc, &source)) {
16445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (!bc) {
16545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            fprintf(f, "%6lu %*s%s\n", listline++, 32, "", source);
16645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        } else {
16745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /* get the next relocation for the bytecode's section */
16845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            sect = yasm_bc_get_section(bc);
16945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (!last_hist || last_hist->sect != sect) {
17045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                int found = 0;
17145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
17245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                /* look through reloc_hist for matching section */
17345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                SLIST_FOREACH(last_hist, &reloc_hist, link) {
17445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    if (last_hist->sect == sect) {
17545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        found = 1;
17645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        break;
17745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    }
17845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
17945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
18045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (!found) {
18145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    /* not found, add to list*/
18245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    last_hist = yasm_xmalloc(sizeof(sectreloc));
18345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    last_hist->sect = sect;
18445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    last_hist->next_reloc = yasm_section_relocs_first(sect);
18545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
18645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    if (last_hist->next_reloc) {
18745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        yasm_intnum *addr;
18845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        yasm_symrec *sym;
18945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        yasm_reloc_get(last_hist->next_reloc, &addr, &sym);
19045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        last_hist->next_reloc_addr =
19145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            yasm_intnum_get_uint(addr);
19245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    }
19345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
19445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    SLIST_INSERT_HEAD(&reloc_hist, last_hist, link);
19545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
19645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
19745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
19845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            info.next_reloc = last_hist->next_reloc;
19945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            info.next_reloc_addr = last_hist->next_reloc_addr;
20045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            STAILQ_INIT(&info.bcrelocs);
20145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
20245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /* loop over bytecodes on this line (usually only one) */
20345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            while (bc && bc->line == line) {
20445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                /*@null@*/ /*@only@*/ unsigned char *bigbuf;
20545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                unsigned long size = REGULAR_BUF_SIZE;
20645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                long multiple;
20745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                unsigned long offset = bc->offset;
20845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                unsigned char *origp, *p;
20945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                int gap;
21045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
21145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                /* convert bytecode into bytes, recording relocs along the
21245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                 * way
21345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                 */
21445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                bigbuf = yasm_bc_tobytes(bc, buf, &size, &gap, &info,
21545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                         nasm_listfmt_output_value, NULL);
21645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                yasm_bc_get_multiple(bc, &multiple, 1);
21745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (multiple <= 0)
21845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    size = 0;
21945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                else
22045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    size /= multiple;
22145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
22245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                /* output bytes with reloc information */
22345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                origp = bigbuf ? bigbuf : buf;
22445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                p = origp;
22545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                reloc = STAILQ_FIRST(&info.bcrelocs);
22645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (gap) {
22745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    fprintf(f, "%6lu %08lX <gap>%*s%s\n", listline++, offset,
22845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            18, "", source ? source : "");
22945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                } else while (size > 0) {
23045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    int i;
23145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
23245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    fprintf(f, "%6lu %08lX ", listline++, offset);
23345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    for (i=0; i<18 && size > 0; size--) {
23445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        if (reloc && (unsigned long)(p-origp) ==
23545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                     reloc->offset) {
23645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            fprintf(f, "%c", reloc->rel ? '(' : '[');
23745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            i++;
23845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        }
23945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        fprintf(f, "%02X", *(p++));
24045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        i+=2;
24145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        if (reloc && (unsigned long)(p-origp) ==
24245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                     reloc->offset+reloc->size) {
24345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            fprintf(f, "%c", reloc->rel ? ')' : ']');
24445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            i++;
24545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            reloc = STAILQ_NEXT(reloc, link);
24645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        }
24745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    }
24845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    if (size > 0)
24945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        fprintf(f, "-");
25045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    else {
25145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        if (multiple > 1) {
25245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            fprintf(f, "<rept>");
25345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            i += 6;
25445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        }
25545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        fprintf(f, "%*s", 18-i+1, "");
25645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    }
25745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    if (source) {
25845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        fprintf(f, "    %s", source);
25945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        source = NULL;
26045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    }
26145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    fprintf(f, "\n");
26245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
26345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
26445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (bigbuf)
26545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    yasm_xfree(bigbuf);
26645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                bc = STAILQ_NEXT(bc, link);
26745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
26845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
26945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /* delete bcrelocs (newly generated next bytecode if any) */
27045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            reloc = STAILQ_FIRST(&info.bcrelocs);
27145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            while (reloc) {
27245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                bcreloc *reloc2 = STAILQ_NEXT(reloc, link);
27345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                yasm_xfree(reloc);
27445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                reloc = reloc2;
27545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
27645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
27745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /* save reloc context */
27845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            last_hist->next_reloc = info.next_reloc;
27945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            last_hist->next_reloc_addr = info.next_reloc_addr;
28045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
28145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        line++;
28245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
28345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
28445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* delete reloc history */
28545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while (!SLIST_EMPTY(&reloc_hist)) {
28645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        last_hist = SLIST_FIRST(&reloc_hist);
28745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        SLIST_REMOVE_HEAD(&reloc_hist, link);
28845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_xfree(last_hist);
28945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
29045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
29145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_xfree(buf);
29245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
29345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
29445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* Define listfmt structure -- see listfmt.h for details */
29545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_listfmt_module yasm_nasm_LTX_listfmt = {
29645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "NASM-style list format",
29745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "nasm",
29845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    nasm_listfmt_create,
29945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    nasm_listfmt_destroy,
30045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    nasm_listfmt_output
30145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org};
302