145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*
245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Flat-format binary object format
345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *
445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *  Copyright (C) 2002-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#ifdef HAVE_UNISTD_H
3045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include <unistd.h>
3145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#endif
3245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include <libyasm.h>
3345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
3445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
3545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#define REGULAR_OUTBUF_SIZE     1024
3645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
3745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgtypedef struct bin_section_data {
3845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int bss;                    /* aka nobits */
3945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
4045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* User-provided alignment */
4145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_intnum *align, *valign;
4245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
4345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* User-provided starts */
4445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*@null@*/ /*@owned@*/ yasm_expr *start, *vstart;
4545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
4645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* User-provided follows */
4745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*@null@*/ /*@owned@*/ char *follows, *vfollows;
4845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
4945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Calculated (final) starts, used only during output() */
5045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*@null@*/ /*@owned@*/ yasm_intnum *istart, *ivstart;
5145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
5245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Calculated (final) length, used only during output() */
5345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*@null@*/ /*@owned@*/ yasm_intnum *length;
5445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} bin_section_data;
5545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
5645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgtypedef struct yasm_objfmt_bin {
5745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_objfmt_base objfmt;            /* base structure */
5845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
5945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    enum {
6045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        NO_MAP = 0,
6145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        MAP_NONE = 0x01,
6245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        MAP_BRIEF = 0x02,
6345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        MAP_SECTIONS = 0x04,
6445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        MAP_SYMBOLS = 0x08
6545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    } map_flags;
6645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*@null@*/ /*@only@*/ char *map_filename;
6745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
6845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*@null@*/ /*@only@*/ yasm_expr *org;
6945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} yasm_objfmt_bin;
7045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
7145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* symrec data is used only for the special symbols section<sectname>.start,
7245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * section<sectname>.vstart, and section<sectname>.length
7345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
7445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgtypedef struct bin_symrec_data {
7545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_section *section;          /* referenced section */
7645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    enum bin_ssym {
7745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        SSYM_START,
7845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        SSYM_VSTART,
7945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        SSYM_LENGTH
8045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    } which;
8145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} bin_symrec_data;
8245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
8345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void bin_section_data_destroy(/*@only@*/ void *d);
8445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void bin_section_data_print(void *data, FILE *f, int indent_level);
8545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
8645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic const yasm_assoc_data_callback bin_section_data_cb = {
8745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bin_section_data_destroy,
8845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bin_section_data_print
8945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org};
9045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
9145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void bin_symrec_data_destroy(/*@only@*/ void *d);
9245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void bin_symrec_data_print(void *data, FILE *f, int indent_level);
9345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
9445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic const yasm_assoc_data_callback bin_symrec_data_cb = {
9545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bin_symrec_data_destroy,
9645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bin_symrec_data_print
9745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org};
9845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
9945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_objfmt_module yasm_bin_LTX_objfmt;
10045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
10145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
10245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic yasm_objfmt *
10345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgbin_objfmt_create(yasm_object *object)
10445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
10545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_objfmt_bin *objfmt_bin = yasm_xmalloc(sizeof(yasm_objfmt_bin));
10645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    objfmt_bin->objfmt.module = &yasm_bin_LTX_objfmt;
10745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
10845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    objfmt_bin->map_flags = NO_MAP;
10945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    objfmt_bin->map_filename = NULL;
11045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    objfmt_bin->org = NULL;
11145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
11245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return (yasm_objfmt *)objfmt_bin;
11345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
11445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
115a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.orgtypedef TAILQ_HEAD(bin_group_head, bin_group) bin_groups;
11645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
11745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgtypedef struct bin_group {
11845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    TAILQ_ENTRY(bin_group) link;
11945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_section *section;
12045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bin_section_data *bsd;
12145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
12245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Groups that (in parallel) logically come immediately after this
12345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * group's section.
12445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     */
12545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bin_groups follow_groups;
12645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} bin_group;
12745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
12845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* Recursive function to find group containing named section. */
12945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic bin_group *
13045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgfind_group_by_name(bin_groups *groups, const char *name)
13145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
13245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bin_group *group, *found;
13345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    TAILQ_FOREACH(group, groups, link) {
13445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (strcmp(yasm_section_get_name(group->section), name) == 0)
13545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return group;
13645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* Recurse to loop through follow groups */
13745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        found = find_group_by_name(&group->follow_groups, name);
13845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (found)
13945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return found;
14045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
14145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return NULL;
14245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
14345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
14445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* Recursive function to find group.  Returns NULL if not found. */
14545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic bin_group *
14645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgfind_group_by_section(bin_groups *groups, yasm_section *section)
14745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
14845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bin_group *group, *found;
14945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    TAILQ_FOREACH(group, groups, link) {
15045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (group->section == section)
15145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return group;
15245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* Recurse to loop through follow groups */
15345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        found = find_group_by_section(&group->follow_groups, section);
15445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (found)
15545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return found;
15645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
15745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return NULL;
15845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
15945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
160a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org#if 0
161a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org/* Debugging function */
16245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void
16345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgprint_groups(const bin_groups *groups, int indent_level)
16445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
16545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bin_group *group;
16645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    TAILQ_FOREACH(group, groups, link) {
16745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        printf("%*sSection `%s':\n", indent_level, "",
16845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org               yasm_section_get_name(group->section));
16945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        bin_section_data_print(group->bsd, stdout, indent_level+1);
17045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (!TAILQ_EMPTY(&group->follow_groups)) {
17145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            printf("%*sFollowing groups:\n", indent_level, "");
17245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            print_groups(&group->follow_groups, indent_level+1);
17345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
17445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
17545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
176a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org#endif
17745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
17845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void
17945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgbin_group_destroy(/*@only@*/ bin_group *group)
18045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
18145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bin_group *follow, *group_temp;
18245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    TAILQ_FOREACH_SAFE(follow, &group->follow_groups, link, group_temp)
18345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        bin_group_destroy(follow);
18445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_xfree(group);
18545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
18645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
18745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgtypedef struct bin_objfmt_output_info {
18845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_object *object;
18945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_errwarns *errwarns;
19045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*@dependent@*/ FILE *f;
19145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*@only@*/ unsigned char *buf;
19245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*@observer@*/ const yasm_section *sect;
19345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned long start;        /* what normal variables go against */
19445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
19545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_intnum *origin;
19645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_intnum *tmp_intn;      /* temporary working intnum */
19745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
19845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bin_groups lma_groups, vma_groups;
19945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} bin_objfmt_output_info;
20045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
20145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int
20245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgbin_objfmt_check_sym(yasm_symrec *sym, /*@null@*/ void *d)
20345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
20445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*@null@*/ bin_objfmt_output_info *info = (bin_objfmt_output_info *)d;
20545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_sym_vis vis = yasm_symrec_get_visibility(sym);
20645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    assert(info != NULL);
20745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
20845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Don't check internally-generated symbols.  Only internally generated
20945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * symbols have symrec data, so simply check for its presence.
21045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     */
21145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (yasm_symrec_get_data(sym, &bin_symrec_data_cb))
21245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return 0;
21345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
21445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (vis & YASM_SYM_EXTERN) {
21545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_warn_set(YASM_WARN_GENERAL,
21645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            N_("binary object format does not support extern variables"));
21745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_errwarn_propagate(info->errwarns, yasm_symrec_get_decl_line(sym));
21845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    } else if (vis & YASM_SYM_GLOBAL) {
21945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_warn_set(YASM_WARN_GENERAL,
22045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            N_("binary object format does not support global variables"));
22145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_errwarn_propagate(info->errwarns, yasm_symrec_get_decl_line(sym));
22245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    } else if (vis & YASM_SYM_COMMON) {
22345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_error_set(YASM_ERROR_TYPE,
22445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            N_("binary object format does not support common variables"));
22545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_errwarn_propagate(info->errwarns, yasm_symrec_get_decl_line(sym));
22645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
22745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return 0;
22845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
22945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
23045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int
23145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgbin_lma_create_group(yasm_section *sect, /*@null@*/ void *d)
23245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
23345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bin_objfmt_output_info *info = (bin_objfmt_output_info *)d;
23445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bin_section_data *bsd = yasm_section_get_data(sect, &bin_section_data_cb);
23545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned long align = yasm_section_get_align(sect);
23645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bin_group *group;
23745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
23845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    assert(info != NULL);
23945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    assert(bsd != NULL);
24045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
24145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    group = yasm_xmalloc(sizeof(bin_group));
24245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    group->section = sect;
24345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    group->bsd = bsd;
24445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    TAILQ_INIT(&group->follow_groups);
24545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
24645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Determine section alignment as necessary. */
24745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (!bsd->align)
24845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        bsd->align = yasm_intnum_create_uint(align > 4 ? align : 4);
24945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    else {
25045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_intnum *align_intn = yasm_intnum_create_uint(align);
25145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (yasm_intnum_compare(align_intn, bsd->align) > 0) {
25245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_warn_set(YASM_WARN_GENERAL,
25345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                N_("section `%s' internal align of %lu is greater than `%s' of %lu; using `%s'"),
25445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                yasm_section_get_name(sect),
25545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                yasm_intnum_get_uint(align_intn),
25645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                N_("align"),
25745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                yasm_intnum_get_uint(bsd->align),
25845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                N_("align"));
25945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_errwarn_propagate(info->errwarns, 0);
26045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
26145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_intnum_destroy(align_intn);
26245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
26345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
26445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Calculate section integer start. */
26545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (bsd->start) {
26645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        bsd->istart = yasm_expr_get_intnum(&bsd->start, 0);
26745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (!bsd->istart) {
26845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_error_set(YASM_ERROR_TOO_COMPLEX,
26945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                           N_("start expression is too complex"));
27045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_errwarn_propagate(info->errwarns, bsd->start->line);
27145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return 1;
27245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        } else
27345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            bsd->istart = yasm_intnum_copy(bsd->istart);
27445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    } else
27545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        bsd->istart = NULL;
27645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
27745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Calculate section integer vstart. */
27845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (bsd->vstart) {
27945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        bsd->ivstart = yasm_expr_get_intnum(&bsd->vstart, 0);
28045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (!bsd->ivstart) {
28145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_error_set(YASM_ERROR_TOO_COMPLEX,
28245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                           N_("vstart expression is too complex"));
28345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_errwarn_propagate(info->errwarns, bsd->vstart->line);
28445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return 1;
28545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        } else
28645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            bsd->ivstart = yasm_intnum_copy(bsd->ivstart);
28745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    } else
28845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        bsd->ivstart = NULL;
28945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
29045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Calculate section integer length. */
29145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bsd->length = yasm_calc_bc_dist(yasm_section_bcs_first(sect),
29245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                    yasm_section_bcs_last(sect));
29345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
29445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    TAILQ_INSERT_TAIL(&info->lma_groups, group, link);
29545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return 0;
29645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
29745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
29845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int
29945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgbin_vma_create_group(yasm_section *sect, /*@null@*/ void *d)
30045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
30145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bin_objfmt_output_info *info = (bin_objfmt_output_info *)d;
30245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bin_section_data *bsd = yasm_section_get_data(sect, &bin_section_data_cb);
30345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bin_group *group;
30445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
30545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    assert(info != NULL);
30645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    assert(bsd != NULL);
30745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
30845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    group = yasm_xmalloc(sizeof(bin_group));
30945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    group->section = sect;
31045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    group->bsd = bsd;
31145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    TAILQ_INIT(&group->follow_groups);
31245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
31345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    TAILQ_INSERT_TAIL(&info->vma_groups, group, link);
31445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return 0;
31545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
31645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
31745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* Calculates new start address based on alignment constraint.
31845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Start is modified (rounded up) to the closest aligned value greater than
31945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * what was passed in.
32045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Align must be a power of 2.
32145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
32245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void
32345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgbin_objfmt_align(yasm_intnum *start, const yasm_intnum *align)
32445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
32545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Because alignment is always a power of two, we can use some bit
32645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * trickery to do this easily.
32745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     */
32845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_intnum *align_intn =
32945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_intnum_create_uint(yasm_intnum_get_uint(align)-1);
33045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_intnum_calc(align_intn, YASM_EXPR_AND, start);
33145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (!yasm_intnum_is_zero(align_intn)) {
33245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* start = (start & ~(align-1)) + align; */
33345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_intnum_set_uint(align_intn, yasm_intnum_get_uint(align)-1);
33445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_intnum_calc(align_intn, YASM_EXPR_NOT, NULL);
33545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_intnum_calc(align_intn, YASM_EXPR_AND, start);
33645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_intnum_set(start, align);
33745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_intnum_calc(start, YASM_EXPR_ADD, align_intn);
33845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
33945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_intnum_destroy(align_intn);
34045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
34145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
34245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* Recursive function to assign start addresses.
34345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Updates start, last, and vdelta parameters as it goes along.
34445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * The tmp parameter is just a working intnum so one doesn't have to be
34545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * locally allocated for this purpose.
34645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
34745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void
34845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orggroup_assign_start_recurse(bin_group *group, yasm_intnum *start,
34945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                           yasm_intnum *last, yasm_intnum *vdelta,
35045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                           yasm_intnum *tmp, yasm_errwarns *errwarns)
35145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
35245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bin_group *follow_group;
35345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
35445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Determine LMA */
35545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (group->bsd->istart) {
35645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_intnum_set(group->bsd->istart, start);
35745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (group->bsd->align) {
35845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            bin_objfmt_align(group->bsd->istart, group->bsd->align);
35945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (yasm_intnum_compare(start, group->bsd->istart) != 0) {
36045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                yasm_warn_set(YASM_WARN_GENERAL,
36145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    N_("start inconsistent with align; using aligned value"));
36245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                yasm_errwarn_propagate(errwarns, group->bsd->start->line);
36345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
36445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
36545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    } else {
36645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        group->bsd->istart = yasm_intnum_copy(start);
36745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (group->bsd->align != 0)
36845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            bin_objfmt_align(group->bsd->istart, group->bsd->align);
36945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
37045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
37145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Determine VMA if either just valign specified or if no v* specified */
37245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (!group->bsd->vstart) {
37345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (!group->bsd->vfollows && !group->bsd->valign) {
37445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /* No v* specified, set VMA=LMA+vdelta. */
37545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            group->bsd->ivstart = yasm_intnum_copy(group->bsd->istart);
37645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_intnum_calc(group->bsd->ivstart, YASM_EXPR_ADD, vdelta);
37745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        } else if (!group->bsd->vfollows) {
37845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /* Just valign specified: set VMA=LMA+vdelta, align VMA, then add
37945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * delta between unaligned and aligned to vdelta parameter.
38045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             */
38145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            group->bsd->ivstart = yasm_intnum_copy(group->bsd->istart);
38245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_intnum_calc(group->bsd->ivstart, YASM_EXPR_ADD, vdelta);
38345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_intnum_set(tmp, group->bsd->ivstart);
38445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            bin_objfmt_align(group->bsd->ivstart, group->bsd->valign);
38545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_intnum_calc(vdelta, YASM_EXPR_ADD, group->bsd->ivstart);
38645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_intnum_calc(vdelta, YASM_EXPR_SUB, tmp);
38745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
38845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
38945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
39045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Find the maximum end value */
39145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_intnum_set(tmp, group->bsd->istart);
39245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_intnum_calc(tmp, YASM_EXPR_ADD, group->bsd->length);
39345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (yasm_intnum_compare(tmp, last) > 0)     /* tmp > last */
39445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_intnum_set(last, tmp);
39545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
39645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Recurse for each following group. */
39745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    TAILQ_FOREACH(follow_group, &group->follow_groups, link) {
39845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* Following sections have to follow this one,
39945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         * so add length to start.
40045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         */
40145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_intnum_set(start, group->bsd->istart);
40245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_intnum_calc(start, YASM_EXPR_ADD, group->bsd->length);
40345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
40445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        group_assign_start_recurse(follow_group, start, last, vdelta, tmp,
40545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                   errwarns);
40645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
40745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
40845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
40945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* Recursive function to assign start addresses.
41045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Updates start parameter as it goes along.
41145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * The tmp parameter is just a working intnum so one doesn't have to be
41245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * locally allocated for this purpose.
41345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
41445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void
41545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orggroup_assign_vstart_recurse(bin_group *group, yasm_intnum *start,
41645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            yasm_errwarns *errwarns)
41745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
41845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bin_group *follow_group;
41945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
42045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Determine VMA section alignment as necessary.
42145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * Default to LMA alignment if not specified.
42245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     */
42345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (!group->bsd->valign)
42445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        group->bsd->valign = yasm_intnum_copy(group->bsd->align);
42545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    else {
42645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        unsigned long align = yasm_section_get_align(group->section);
42745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_intnum *align_intn = yasm_intnum_create_uint(align);
42845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (yasm_intnum_compare(align_intn, group->bsd->valign) > 0) {
42945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_warn_set(YASM_WARN_GENERAL,
43045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                N_("section `%s' internal align of %lu is greater than `%s' of %lu; using `%s'"),
43145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                yasm_section_get_name(group->section),
43245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                yasm_intnum_get_uint(align_intn),
43345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                N_("valign"),
43445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                yasm_intnum_get_uint(group->bsd->valign),
43545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                N_("valign"));
43645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_errwarn_propagate(errwarns, 0);
43745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
43845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_intnum_destroy(align_intn);
43945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
44045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
44145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Determine VMA */
44245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (group->bsd->ivstart) {
44345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_intnum_set(group->bsd->ivstart, start);
44445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (group->bsd->valign) {
44545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            bin_objfmt_align(group->bsd->ivstart, group->bsd->valign);
44645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (yasm_intnum_compare(start, group->bsd->ivstart) != 0) {
44745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                yasm_error_set(YASM_ERROR_VALUE,
44845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                               N_("vstart inconsistent with valign"));
44945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                yasm_errwarn_propagate(errwarns, group->bsd->vstart->line);
45045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
45145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
45245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    } else {
45345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        group->bsd->ivstart = yasm_intnum_copy(start);
45445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (group->bsd->valign)
45545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            bin_objfmt_align(group->bsd->ivstart, group->bsd->valign);
45645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
45745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
45845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Recurse for each following group. */
45945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    TAILQ_FOREACH(follow_group, &group->follow_groups, link) {
46045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* Following sections have to follow this one,
46145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         * so add length to start.
46245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         */
46345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_intnum_set(start, group->bsd->ivstart);
46445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_intnum_calc(start, YASM_EXPR_ADD, group->bsd->length);
46545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
46645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        group_assign_vstart_recurse(follow_group, start, errwarns);
46745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
46845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
46945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
47045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic /*@null@*/ const yasm_intnum *
47145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgget_ssym_value(yasm_symrec *sym)
47245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
47345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bin_symrec_data *bsymd = yasm_symrec_get_data(sym, &bin_symrec_data_cb);
47445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bin_section_data *bsd;
47545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
47645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (!bsymd)
47745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return NULL;
47845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
47945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bsd = yasm_section_get_data(bsymd->section, &bin_section_data_cb);
48045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    assert(bsd != NULL);
48145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
48245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    switch (bsymd->which) {
48345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case SSYM_START: return bsd->istart;
48445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case SSYM_VSTART: return bsd->ivstart;
48545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case SSYM_LENGTH: return bsd->length;
48645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
48745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return NULL;
48845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
48945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
49045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic /*@only@*/ yasm_expr *
49145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgbin_objfmt_expr_xform(/*@returned@*/ /*@only@*/ yasm_expr *e,
49245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                      /*@unused@*/ /*@null@*/ void *d)
49345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
49445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int i;
49545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    for (i=0; i<e->numterms; i++) {
49645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /*@dependent@*/ yasm_section *sect;
49745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /*@dependent@*/ /*@null@*/ yasm_bytecode *precbc;
49845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /*@null@*/ yasm_intnum *dist;
49945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /*@null@*/ const yasm_intnum *ssymval;
50045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
50145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* Transform symrecs or precbcs that reference sections into
50245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         * vstart + intnum(dist).
50345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         */
50445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (((e->terms[i].type == YASM_EXPR_SYM &&
50545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             yasm_symrec_get_label(e->terms[i].data.sym, &precbc)) ||
50645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            (e->terms[i].type == YASM_EXPR_PRECBC &&
50745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             (precbc = e->terms[i].data.precbc))) &&
50845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            (sect = yasm_bc_get_section(precbc)) &&
50945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            (dist = yasm_calc_bc_dist(yasm_section_bcs_first(sect), precbc))) {
51045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            bin_section_data *bsd;
51145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            bsd = yasm_section_get_data(sect, &bin_section_data_cb);
51245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            assert(bsd != NULL);
51345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_intnum_calc(dist, YASM_EXPR_ADD, bsd->ivstart);
51445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            e->terms[i].type = YASM_EXPR_INT;
51545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            e->terms[i].data.intn = dist;
51645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
51745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
51845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* Transform our special symrecs into the appropriate value */
51945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (e->terms[i].type == YASM_EXPR_SYM &&
52045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            (ssymval = get_ssym_value(e->terms[i].data.sym))) {
52145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            e->terms[i].type = YASM_EXPR_INT;
52245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            e->terms[i].data.intn = yasm_intnum_copy(ssymval);
52345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
52445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
52545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
52645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return e;
52745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
52845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
52945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgtypedef struct map_output_info {
53045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* address width */
53145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int bytes;
53245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
53345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* intnum output static data areas */
53445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned char *buf;
53545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_intnum *intn;
53645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
53745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* symrec output information */
53845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned long count;
53945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_section *section;  /* NULL for EQUs */
54045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
54145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_object *object;    /* object */
54245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    FILE *f;                /* map output file */
54345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} map_output_info;
54445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
54545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int
54645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgmap_prescan_bytes(yasm_section *sect, void *d)
54745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
54845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bin_section_data *bsd = yasm_section_get_data(sect, &bin_section_data_cb);
54945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    map_output_info *info = (map_output_info *)d;
55045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
55145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    assert(bsd != NULL);
55245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    assert(info != NULL);
55345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
55445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while (!yasm_intnum_check_size(bsd->length, info->bytes * 8, 0, 0))
55545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        info->bytes *= 2;
55645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while (!yasm_intnum_check_size(bsd->istart, info->bytes * 8, 0, 0))
55745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        info->bytes *= 2;
55845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while (!yasm_intnum_check_size(bsd->ivstart, info->bytes * 8, 0, 0))
55945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        info->bytes *= 2;
56045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
56145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return 0;
56245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
56345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
56445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void
56545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgmap_print_intnum(const yasm_intnum *intn, map_output_info *info)
56645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
56745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    size_t i;
56845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_intnum_get_sized(intn, info->buf, info->bytes, info->bytes*8, 0, 0,
56945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                          0);
57045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    for (i=info->bytes; i != 0; i--)
57145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        fprintf(info->f, "%02X", info->buf[i-1]);
57245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
57345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
57445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void
57545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgmap_sections_summary(bin_groups *groups, map_output_info *info)
57645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
57745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bin_group *group;
57845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    TAILQ_FOREACH(group, groups, link) {
57945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        bin_section_data *bsd = group->bsd;
58045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
58145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        assert(bsd != NULL);
58245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        assert(info != NULL);
58345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
58445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        map_print_intnum(bsd->ivstart, info);
58545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        fprintf(info->f, "  ");
58645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
58745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_intnum_set(info->intn, bsd->ivstart);
58845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_intnum_calc(info->intn, YASM_EXPR_ADD, bsd->length);
58945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        map_print_intnum(info->intn, info);
59045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        fprintf(info->f, "  ");
59145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
59245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        map_print_intnum(bsd->istart, info);
59345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        fprintf(info->f, "  ");
59445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
59545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_intnum_set(info->intn, bsd->istart);
59645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_intnum_calc(info->intn, YASM_EXPR_ADD, bsd->length);
59745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        map_print_intnum(info->intn, info);
59845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        fprintf(info->f, "  ");
59945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
60045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        map_print_intnum(bsd->length, info);
60145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        fprintf(info->f, "  ");
60245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
60345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        fprintf(info->f, "%-*s", 10, bsd->bss ? "nobits" : "progbits");
60445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        fprintf(info->f, "%s\n", yasm_section_get_name(group->section));
60545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
60645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* Recurse to loop through follow groups */
60745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        map_sections_summary(&group->follow_groups, info);
60845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
60945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
61045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
61145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void
61245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgmap_sections_detail(bin_groups *groups, map_output_info *info)
61345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
61445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bin_group *group;
61545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    TAILQ_FOREACH(group, groups, link) {
61645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        bin_section_data *bsd = group->bsd;
61745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        size_t i;
61845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        const char *s;
61945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
62045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        s = yasm_section_get_name(group->section);
62145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        fprintf(info->f, "---- Section %s ", s);
62245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        for (i=0; i<(65-strlen(s)); i++)
62345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            fputc('-', info->f);
62445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
62545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        fprintf(info->f, "\n\nclass:     %s",
62645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                bsd->bss ? "nobits" : "progbits");
62745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        fprintf(info->f, "\nlength:    ");
62845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        map_print_intnum(bsd->length, info);
62945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        fprintf(info->f, "\nstart:     ");
63045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        map_print_intnum(bsd->istart, info);
63145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        fprintf(info->f, "\nalign:     ");
63245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        map_print_intnum(bsd->align, info);
63345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        fprintf(info->f, "\nfollows:   %s",
63445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                bsd->follows ? bsd->follows : "not defined");
63545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        fprintf(info->f, "\nvstart:    ");
63645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        map_print_intnum(bsd->ivstart, info);
63745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        fprintf(info->f, "\nvalign:    ");
63845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        map_print_intnum(bsd->valign, info);
63945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        fprintf(info->f, "\nvfollows:  %s\n\n",
64045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                bsd->vfollows ? bsd->vfollows : "not defined");
64145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
64245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* Recurse to loop through follow groups */
64345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        map_sections_detail(&group->follow_groups, info);
64445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
64545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
64645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
64745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int
64845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgmap_symrec_count(yasm_symrec *sym, void *d)
64945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
65045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    map_output_info *info = (map_output_info *)d;
65145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*@dependent@*/ yasm_bytecode *precbc;
65245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
65345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    assert(info != NULL);
65445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
65545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* TODO: autodetect wider size */
65645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (!info->section && yasm_symrec_get_equ(sym)) {
65745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        info->count++;
65845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    } else if (yasm_symrec_get_label(sym, &precbc) &&
65945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org               yasm_bc_get_section(precbc) == info->section) {
66045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        info->count++;
66145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
66245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return 0;
66345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
66445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
66545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int
66645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgmap_symrec_output(yasm_symrec *sym, void *d)
66745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
66845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    map_output_info *info = (map_output_info *)d;
66945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    const yasm_expr *equ;
67045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*@dependent@*/ yasm_bytecode *precbc;
67145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*@only@*/ char *name = yasm_symrec_get_global_name(sym, info->object);
67245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
67345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    assert(info != NULL);
67445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
67545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (!info->section && (equ = yasm_symrec_get_equ(sym))) {
67645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_expr *realequ = yasm_expr_copy(equ);
67745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        realequ = yasm_expr__level_tree
67845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            (realequ, 1, 1, 1, 0, bin_objfmt_expr_xform, NULL);
67945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_intnum_set(info->intn, yasm_expr_get_intnum(&realequ, 0));
68045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_expr_destroy(realequ);
68145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        map_print_intnum(info->intn, info);
68245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        fprintf(info->f, "  %s\n", name);
68345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    } else if (yasm_symrec_get_label(sym, &precbc) &&
68445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org               yasm_bc_get_section(precbc) == info->section) {
68545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        bin_section_data *bsd =
68645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_section_get_data(info->section, &bin_section_data_cb);
68745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
68845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* Real address */
68945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_intnum_set_uint(info->intn, yasm_bc_next_offset(precbc));
69045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_intnum_calc(info->intn, YASM_EXPR_ADD, bsd->istart);
69145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        map_print_intnum(info->intn, info);
69245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        fprintf(info->f, "  ");
69345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
69445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* Virtual address */
69545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_intnum_set_uint(info->intn, yasm_bc_next_offset(precbc));
69645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_intnum_calc(info->intn, YASM_EXPR_ADD, bsd->ivstart);
69745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        map_print_intnum(info->intn, info);
69845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
69945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* Name */
70045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        fprintf(info->f, "  %s\n", name);
70145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
70245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_xfree(name);
70345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return 0;
70445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
70545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
70645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void
70745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgmap_sections_symbols(bin_groups *groups, map_output_info *info)
70845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
70945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bin_group *group;
71045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    TAILQ_FOREACH(group, groups, link) {
71145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        info->count = 0;
71245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        info->section = group->section;
71345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_symtab_traverse(info->object->symtab, info, map_symrec_count);
71445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
71545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (info->count > 0) {
71645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            const char *s = yasm_section_get_name(group->section);
71745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            size_t i;
71845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            fprintf(info->f, "---- Section %s ", s);
71945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            for (i=0; i<(65-strlen(s)); i++)
72045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                fputc('-', info->f);
72145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            fprintf(info->f, "\n\n%-*s%-*s%s\n",
72245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    info->bytes*2+2, "Real",
72345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    info->bytes*2+2, "Virtual",
72445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    "Name");
72545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_symtab_traverse(info->object->symtab, info,
72645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                 map_symrec_output);
72745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            fprintf(info->f, "\n\n");
72845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
72945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
73045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* Recurse to loop through follow groups */
73145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        map_sections_symbols(&group->follow_groups, info);
73245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
73345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
73445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
73545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void
73645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgoutput_map(bin_objfmt_output_info *info)
73745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
73845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_objfmt_bin *objfmt_bin = (yasm_objfmt_bin *)info->object->objfmt;
73945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    FILE *f;
74045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int i;
74145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    map_output_info mapinfo;
74245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
74345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (objfmt_bin->map_flags == NO_MAP)
74445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return;
74545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
74645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (objfmt_bin->map_flags == MAP_NONE)
74745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        objfmt_bin->map_flags = MAP_BRIEF;          /* default to brief */
74845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
74945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (!objfmt_bin->map_filename)
75045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        f = stdout;                                 /* default to stdout */
75145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    else {
75245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        f = fopen(objfmt_bin->map_filename, "wt");
75345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (!f) {
75445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_warn_set(YASM_WARN_GENERAL,
75545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                          N_("unable to open map file `%s'"),
75645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                          objfmt_bin->map_filename);
75745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_errwarn_propagate(info->errwarns, 0);
75845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return;
75945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
76045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
76145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
76245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    mapinfo.object = info->object;
76345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    mapinfo.f = f;
76445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
76545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Temporary intnum */
76645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    mapinfo.intn = info->tmp_intn;
76745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
76845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Prescan all values to figure out what width we should make the output
76945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * fields.  Start with a minimum of 4.
77045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     */
77145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    mapinfo.bytes = 4;
77245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while (!yasm_intnum_check_size(info->origin, mapinfo.bytes * 8, 0, 0))
77345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        mapinfo.bytes *= 2;
77445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_object_sections_traverse(info->object, &mapinfo, map_prescan_bytes);
77545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    mapinfo.buf = yasm_xmalloc(mapinfo.bytes);
77645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
77745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fprintf(f, "\n- YASM Map file ");
77845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    for (i=0; i<63; i++)
77945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        fputc('-', f);
78045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fprintf(f, "\n\nSource file:  %s\n", info->object->src_filename);
78145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fprintf(f, "Output file:  %s\n\n", info->object->obj_filename);
78245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
78345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fprintf(f, "-- Program origin ");
78445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    for (i=0; i<61; i++)
78545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        fputc('-', f);
78645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fprintf(f, "\n\n");
78745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    map_print_intnum(info->origin, &mapinfo);
78845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fprintf(f, "\n\n");
78945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
79045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (objfmt_bin->map_flags & MAP_BRIEF) {
79145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        fprintf(f, "-- Sections (summary) ");
79245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        for (i=0; i<57; i++)
79345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            fputc('-', f);
79445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        fprintf(f, "\n\n%-*s%-*s%-*s%-*s%-*s%-*s%s\n",
79545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                mapinfo.bytes*2+2, "Vstart",
79645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                mapinfo.bytes*2+2, "Vstop",
79745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                mapinfo.bytes*2+2, "Start",
79845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                mapinfo.bytes*2+2, "Stop",
79945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                mapinfo.bytes*2+2, "Length",
80045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                10, "Class", "Name");
80145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
80245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        map_sections_summary(&info->lma_groups, &mapinfo);
80345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        fprintf(f, "\n");
80445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
80545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
80645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (objfmt_bin->map_flags & MAP_SECTIONS) {
80745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        fprintf(f, "-- Sections (detailed) ");
80845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        for (i=0; i<56; i++)
80945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            fputc('-', f);
81045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        fprintf(f, "\n\n");
81145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        map_sections_detail(&info->lma_groups, &mapinfo);
81245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
81345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
81445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (objfmt_bin->map_flags & MAP_SYMBOLS) {
81545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        fprintf(f, "-- Symbols ");
81645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        for (i=0; i<68; i++)
81745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            fputc('-', f);
81845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        fprintf(f, "\n\n");
81945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
82045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* We do two passes for EQU and each section; the first pass
82145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         * determines the byte width to use for the value and whether any
82245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         * symbols are present, the second pass actually outputs the text.
82345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         */
82445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
82545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* EQUs */
82645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        mapinfo.count = 0;
82745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        mapinfo.section = NULL;
82845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_symtab_traverse(info->object->symtab, &mapinfo, map_symrec_count);
82945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
83045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (mapinfo.count > 0) {
83145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            fprintf(f, "---- No Section ");
83245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            for (i=0; i<63; i++)
83345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                fputc('-', f);
83445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            fprintf(f, "\n\n%-*s%s\n", mapinfo.bytes*2+2, "Value", "Name");
83545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_symtab_traverse(info->object->symtab, &mapinfo,
83645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                 map_symrec_output);
83745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            fprintf(f, "\n\n");
83845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
83945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
84045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* Other sections */
84145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        map_sections_symbols(&info->lma_groups, &mapinfo);
84245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
84345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
84445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (f != stdout)
84545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        fclose(f);
84645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
84745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_xfree(mapinfo.buf);
84845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
84945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
85045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* Check for LMA overlap using a simple N^2 algorithm. */
85145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int
85245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgcheck_lma_overlap(yasm_section *sect, /*@null@*/ void *d)
85345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
85445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bin_section_data *bsd, *bsd2;
85545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_section *other = (yasm_section *)d;
85645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_intnum *overlap;
85745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
85845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (!d)
85945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return yasm_object_sections_traverse(yasm_section_get_object(sect),
86045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                             sect, check_lma_overlap);
86145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (sect == other)
86245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return 0;
86345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
86445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bsd = yasm_section_get_data(sect, &bin_section_data_cb);
86545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bsd2 = yasm_section_get_data(other, &bin_section_data_cb);
86645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
86745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (yasm_intnum_is_zero(bsd->length) ||
86845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_intnum_is_zero(bsd2->length))
86945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return 0;
87045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
87145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (yasm_intnum_compare(bsd->istart, bsd2->istart) <= 0) {
87245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        overlap = yasm_intnum_copy(bsd->istart);
87345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_intnum_calc(overlap, YASM_EXPR_ADD, bsd->length);
87445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_intnum_calc(overlap, YASM_EXPR_SUB, bsd2->istart);
87545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    } else {
87645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        overlap = yasm_intnum_copy(bsd2->istart);
87745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_intnum_calc(overlap, YASM_EXPR_ADD, bsd2->length);
87845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_intnum_calc(overlap, YASM_EXPR_SUB, bsd->istart);
87945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
88045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
88145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (yasm_intnum_sign(overlap) > 0) {
88245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_error_set(YASM_ERROR_GENERAL,
88345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                       N_("sections `%s' and `%s' overlap by %lu bytes"),
88445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                       yasm_section_get_name(sect),
88545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                       yasm_section_get_name(other),
88645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                       yasm_intnum_get_uint(overlap));
88745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_intnum_destroy(overlap);
88845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return -1;
88945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
89045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
89145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_intnum_destroy(overlap);
89245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return 0;
89345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
89445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
89545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int
89645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgbin_objfmt_output_value(yasm_value *value, unsigned char *buf,
89745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        unsigned int destsize,
89845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        /*@unused@*/ unsigned long offset, yasm_bytecode *bc,
89945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        int warn, /*@null@*/ void *d)
90045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
90145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*@null@*/ bin_objfmt_output_info *info = (bin_objfmt_output_info *)d;
90245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*@dependent@*/ /*@null@*/ yasm_bytecode *precbc;
90345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*@dependent@*/ yasm_section *sect;
90445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
90545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    assert(info != NULL);
90645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
90745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Binary objects we need to resolve against object, not against section. */
90845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (value->rel) {
90945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        unsigned int rshift = (unsigned int)value->rshift;
91045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_expr *syme;
91145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /*@null@*/ const yasm_intnum *ssymval;
91245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
91345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (yasm_symrec_is_abs(value->rel)) {
91445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            syme = yasm_expr_create_ident(yasm_expr_int(
91545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                yasm_intnum_create_uint(0)), bc->line);
91645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        } else if (yasm_symrec_get_label(value->rel, &precbc)
91745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                   && (sect = yasm_bc_get_section(precbc))) {
91845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            syme = yasm_expr_create_ident(yasm_expr_sym(value->rel), bc->line);
91945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        } else if ((ssymval = get_ssym_value(value->rel))) {
92045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            syme = yasm_expr_create_ident(yasm_expr_int(
92145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                yasm_intnum_copy(ssymval)), bc->line);
92245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        } else
92345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            goto done;
92445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
92545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* Handle PC-relative */
92645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (value->curpos_rel) {
92745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_expr *sube;
92845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            sube = yasm_expr_create(YASM_EXPR_SUB, yasm_expr_precbc(bc),
92945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                yasm_expr_int(yasm_intnum_create_uint(bc->len*bc->mult_int)),
93045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                bc->line);
93145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            syme = yasm_expr_create(YASM_EXPR_SUB, yasm_expr_expr(syme),
93245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                    yasm_expr_expr(sube), bc->line);
93345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            value->curpos_rel = 0;
93445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            value->ip_rel = 0;
93545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
93645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
93745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (value->rshift > 0)
93845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            syme = yasm_expr_create(YASM_EXPR_SHR, yasm_expr_expr(syme),
93945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                yasm_expr_int(yasm_intnum_create_uint(rshift)), bc->line);
94045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
94145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* Add into absolute portion */
94245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (!value->abs)
94345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            value->abs = syme;
94445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else
94545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            value->abs =
94645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                yasm_expr_create(YASM_EXPR_ADD, yasm_expr_expr(value->abs),
94745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                 yasm_expr_expr(syme), bc->line);
94845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        value->rel = NULL;
94945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        value->rshift = 0;
95045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
95145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgdone:
95245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Simplify absolute portion of value, transforming symrecs */
95345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (value->abs)
95445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        value->abs = yasm_expr__level_tree
95545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            (value->abs, 1, 1, 1, 0, bin_objfmt_expr_xform, NULL);
95645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
95745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Output */
95845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    switch (yasm_value_output_basic(value, buf, destsize, bc, warn,
95945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                    info->object->arch)) {
96045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case -1:
96145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return 1;
96245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case 0:
96345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            break;
96445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        default:
96545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return 0;
96645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
96745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
96845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Couldn't output, assume it contains an external reference. */
96945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_error_set(YASM_ERROR_GENERAL,
97045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        N_("binary object format does not support external references"));
97145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return 1;
97245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
97345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
97445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int
97545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgbin_objfmt_output_bytecode(yasm_bytecode *bc, /*@null@*/ void *d)
97645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
97745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*@null@*/ bin_objfmt_output_info *info = (bin_objfmt_output_info *)d;
97845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*@null@*/ /*@only@*/ unsigned char *bigbuf;
97945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned long size = REGULAR_OUTBUF_SIZE;
98045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int gap;
98145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
98245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    assert(info != NULL);
98345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
98445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bigbuf = yasm_bc_tobytes(bc, info->buf, &size, &gap, info,
98545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                             bin_objfmt_output_value, NULL);
98645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
98745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Don't bother doing anything else if size ended up being 0. */
98845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (size == 0) {
98945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (bigbuf)
99045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_xfree(bigbuf);
99145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return 0;
99245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
99345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
99445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Warn that gaps are converted to 0 and write out the 0's. */
99545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (gap) {
99645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        unsigned long left;
99745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_warn_set(YASM_WARN_UNINIT_CONTENTS,
99845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            N_("uninitialized space declared in code/data section: zeroing"));
99945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* Write out in chunks */
100045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        memset(info->buf, 0, REGULAR_OUTBUF_SIZE);
100145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        left = size;
100245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (left > REGULAR_OUTBUF_SIZE) {
100345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            fwrite(info->buf, REGULAR_OUTBUF_SIZE, 1, info->f);
100445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            left -= REGULAR_OUTBUF_SIZE;
100545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
100645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        fwrite(info->buf, left, 1, info->f);
100745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    } else {
100845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* Output buf (or bigbuf if non-NULL) to file */
100945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        fwrite(bigbuf ? bigbuf : info->buf, (size_t)size, 1, info->f);
101045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
101145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
101245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* If bigbuf was allocated, free it */
101345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (bigbuf)
101445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_xfree(bigbuf);
101545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
101645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return 0;
101745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
101845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
101945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* Check to ensure bytecode is res* (for BSS sections) */
102045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int
102145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgbin_objfmt_no_output_bytecode(yasm_bytecode *bc, /*@null@*/ void *d)
102245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
102345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*@null@*/ bin_objfmt_output_info *info = (bin_objfmt_output_info *)d;
102445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*@null@*/ /*@only@*/ unsigned char *bigbuf;
102545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned long size = REGULAR_OUTBUF_SIZE;
102645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int gap;
102745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
102845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    assert(info != NULL);
102945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
103045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bigbuf = yasm_bc_tobytes(bc, info->buf, &size, &gap, info,
103145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                             bin_objfmt_output_value, NULL);
103245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
103345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* If bigbuf was allocated, free it */
103445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (bigbuf)
103545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_xfree(bigbuf);
103645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
103745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Don't bother doing anything else if size ended up being 0. */
103845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (size == 0)
103945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return 0;
104045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
104145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Warn if not a gap. */
104245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (!gap) {
104345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_warn_set(YASM_WARN_GENERAL,
104445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            N_("initialized space declared in nobits section: ignoring"));
104545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
104645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
104745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return 0;
104845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
104945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
105045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int
105145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgbin_objfmt_output_section(yasm_section *sect, /*@null@*/ void *d)
105245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
105345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bin_section_data *bsd = yasm_section_get_data(sect, &bin_section_data_cb);
105445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*@null@*/ bin_objfmt_output_info *info = (bin_objfmt_output_info *)d;
105545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
105645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    assert(bsd != NULL);
105745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    assert(info != NULL);
105845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
105945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (bsd->bss) {
106045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_section_bcs_traverse(sect, info->errwarns,
106145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                  info, bin_objfmt_no_output_bytecode);
106245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    } else {
106345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_intnum_set(info->tmp_intn, bsd->istart);
106445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_intnum_calc(info->tmp_intn, YASM_EXPR_SUB, info->origin);
106545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (yasm_intnum_sign(info->tmp_intn) < 0) {
106645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_error_set(YASM_ERROR_VALUE,
106745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                           N_("section `%s' starts before origin (ORG)"),
106845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                           yasm_section_get_name(sect));
106945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_errwarn_propagate(info->errwarns, 0);
107045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return 0;
107145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
107245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (!yasm_intnum_check_size(info->tmp_intn, sizeof(long)*8, 0, 1)) {
107345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_error_set(YASM_ERROR_VALUE,
107445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                           N_("section `%s' start value too large"),
107545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                           yasm_section_get_name(sect));
107645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_errwarn_propagate(info->errwarns, 0);
107745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return 0;
107845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
107945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (fseek(info->f, yasm_intnum_get_int(info->tmp_intn) + info->start,
108045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                  SEEK_SET) < 0)
108145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm__fatal(N_("could not seek on output file"));
108245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_section_bcs_traverse(sect, info->errwarns,
108345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                  info, bin_objfmt_output_bytecode);
108445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
108545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
108645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return 0;
108745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
108845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
108945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void
109045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgbin_objfmt_cleanup(bin_objfmt_output_info *info)
109145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
109245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bin_group *group, *group_temp;
109345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
109445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_xfree(info->buf);
109545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_intnum_destroy(info->origin);
109645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_intnum_destroy(info->tmp_intn);
109745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
109845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    TAILQ_FOREACH_SAFE(group, &info->lma_groups, link, group_temp)
109945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        bin_group_destroy(group);
110045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
110145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    TAILQ_FOREACH_SAFE(group, &info->vma_groups, link, group_temp)
110245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        bin_group_destroy(group);
110345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
110445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
110545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void
110645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgbin_objfmt_output(yasm_object *object, FILE *f, /*@unused@*/ int all_syms,
110745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                  yasm_errwarns *errwarns)
110845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
110945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_objfmt_bin *objfmt_bin = (yasm_objfmt_bin *)object->objfmt;
111045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bin_objfmt_output_info info;
111145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bin_group *group, *lma_group, *vma_group, *group_temp;
111245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_intnum *start, *last, *vdelta;
111345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bin_groups unsorted_groups, bss_groups;
111445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
111545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    info.start = ftell(f);
111645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
111745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Set ORG to 0 unless otherwise specified */
111845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (objfmt_bin->org) {
111945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        info.origin = yasm_expr_get_intnum(&objfmt_bin->org, 0);
112045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (!info.origin) {
112145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_error_set(YASM_ERROR_TOO_COMPLEX,
112245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                           N_("ORG expression is too complex"));
112345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_errwarn_propagate(errwarns, objfmt_bin->org->line);
112445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return;
112545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
112645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (yasm_intnum_sign(info.origin) < 0) {
112745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_error_set(YASM_ERROR_VALUE, N_("ORG expression is negative"));
112845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_errwarn_propagate(errwarns, objfmt_bin->org->line);
112945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return;
113045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
113145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        info.origin = yasm_intnum_copy(info.origin);
113245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    } else
113345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        info.origin = yasm_intnum_create_uint(0);
113445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
113545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    info.object = object;
113645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    info.errwarns = errwarns;
113745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    info.f = f;
113845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    info.buf = yasm_xmalloc(REGULAR_OUTBUF_SIZE);
113945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    info.tmp_intn = yasm_intnum_create_uint(0);
114045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    TAILQ_INIT(&info.lma_groups);
114145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    TAILQ_INIT(&info.vma_groups);
114245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
114345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Check symbol table */
114445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_symtab_traverse(object->symtab, &info, bin_objfmt_check_sym);
114545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
114645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Create section groups */
114745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (yasm_object_sections_traverse(object, &info, bin_lma_create_group)) {
114845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        bin_objfmt_cleanup(&info);
114945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return;     /* error detected */
115045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
115145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
115245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Determine section order according to LMA.
115345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * Sections can be ordered either by (priority):
115445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     *  - follows
115545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     *  - start
115645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     *  - progbits/nobits setting
115745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     *  - order in the input file
115845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     */
115945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
116045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Look at each group with follows specified, and find the section
116145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * that group is supposed to follow.
116245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     */
116345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    TAILQ_FOREACH_SAFE(lma_group, &info.lma_groups, link, group_temp) {
116445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (lma_group->bsd->follows) {
116545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            bin_group *found;
116645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /* Need to find group containing section this section follows. */
116745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            found =
116845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                find_group_by_name(&info.lma_groups, lma_group->bsd->follows);
116945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (!found) {
117045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                yasm_error_set(YASM_ERROR_VALUE,
117145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                               N_("section `%s' follows an invalid or unknown section `%s'"),
117245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                               yasm_section_get_name(lma_group->section),
117345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                               lma_group->bsd->follows);
117445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                yasm_errwarn_propagate(errwarns, 0);
117545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                bin_objfmt_cleanup(&info);
117645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                return;
117745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
117845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
117945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /* Check for loops */
118045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (lma_group->section == found->section ||
118145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                find_group_by_section(&lma_group->follow_groups,
118245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                      found->section)) {
118345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                yasm_error_set(YASM_ERROR_VALUE,
118445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                               N_("follows loop between section `%s' and section `%s'"),
118545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                               yasm_section_get_name(lma_group->section),
118645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                               yasm_section_get_name(found->section));
118745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                yasm_errwarn_propagate(errwarns, 0);
118845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                bin_objfmt_cleanup(&info);
118945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                return;
119045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
119145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
119245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /* Remove this section from main lma groups list */
119345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            TAILQ_REMOVE(&info.lma_groups, lma_group, link);
119445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /* Add it after the section it's supposed to follow. */
119545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            TAILQ_INSERT_TAIL(&found->follow_groups, lma_group, link);
119645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
119745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
119845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
119945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Sort the top-level groups according to their start address.
120045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * Use Shell sort for ease of implementation.
120145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * If no start address is specified for a section, don't change the order,
120245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * and move BSS sections to a separate list so they can be moved to the
120345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * end of the lma list after all other sections are sorted.
120445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     */
120545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsorted_groups = info.lma_groups;  /* structure copy */
120645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    TAILQ_INIT(&info.lma_groups);
120745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    TAILQ_INIT(&bss_groups);
120845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    TAILQ_FOREACH_SAFE(lma_group, &unsorted_groups, link, group_temp) {
120945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        bin_group *before;
121045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
121145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (!lma_group->bsd->istart) {
121245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (lma_group->bsd->bss)
121345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                TAILQ_INSERT_TAIL(&bss_groups, lma_group, link);
121445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else
121545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                TAILQ_INSERT_TAIL(&info.lma_groups, lma_group, link);
121645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            continue;
121745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
121845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
121945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        before = NULL;
122045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        TAILQ_FOREACH(group, &info.lma_groups, link) {
122145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (!group->bsd->istart)
122245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                continue;
122345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (yasm_intnum_compare(group->bsd->istart,
122445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                    lma_group->bsd->istart) > 0) {
122545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                before = group;
122645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                break;
122745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
122845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
122945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (before)
123045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            TAILQ_INSERT_BEFORE(before, lma_group, link);
123145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else
123245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            TAILQ_INSERT_TAIL(&info.lma_groups, lma_group, link);
123345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
123445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
123545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Move the pure-BSS sections to the end of the LMA list. */
123645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    TAILQ_FOREACH_SAFE(group, &bss_groups, link, group_temp)
123745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        TAILQ_INSERT_TAIL(&info.lma_groups, group, link);
123845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    TAILQ_INIT(&bss_groups);    /* For sanity */
123945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
124045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Assign a LMA start address to every section.
124145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * Also assign VMA=LMA unless otherwise specified.
124245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     *
124345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * We need to assign VMA=LMA here (while walking the tree) for the case:
124445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     *  sect1 start=0 (size=0x11)
124545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     *  sect2 follows=sect1 valign=16 (size=0x104)
124645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     *  sect3 follows=sect2 valign=16
124745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * Where the valign of sect2 will result in a sect3 vaddr higher than a
124845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * naive segment-by-segment interpretation (where sect3 and sect2 would
124945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * have a VMA overlap).
125045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     *
125145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * Algorithm for VMA=LMA setting:
125245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * Start with delta=0.
125345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * If there's no virtual attributes, we simply set VMA = LMA+delta.
125445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * If there's only valign specified, we set VMA = aligned LMA, and add
125545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * any new alignment difference to delta.
125645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     *
125745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * We could do the LMA start and VMA=LMA steps in two separate steps,
125845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * but it's easier to just recurse once.
125945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     */
126045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    start = yasm_intnum_copy(info.origin);
126145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    last = yasm_intnum_copy(info.origin);
126245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    vdelta = yasm_intnum_create_uint(0);
126345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    TAILQ_FOREACH(lma_group, &info.lma_groups, link) {
126445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (lma_group->bsd->istart)
126545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_intnum_set(start, lma_group->bsd->istart);
126645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        group_assign_start_recurse(lma_group, start, last, vdelta,
126745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                   info.tmp_intn, errwarns);
126845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_intnum_set(start, last);
126945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
127045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_intnum_destroy(last);
127145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_intnum_destroy(vdelta);
127245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
127345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*
127445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * Determine section order according to VMA
127545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     */
127645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
127745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Create section groups */
127845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (yasm_object_sections_traverse(object, &info, bin_vma_create_group)) {
127945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_intnum_destroy(start);
128045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        bin_objfmt_cleanup(&info);
128145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return;     /* error detected */
128245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
128345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
128445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Look at each group with vfollows specified, and find the section
128545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * that group is supposed to follow.
128645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     */
128745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    TAILQ_FOREACH_SAFE(vma_group, &info.vma_groups, link, group_temp) {
128845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (vma_group->bsd->vfollows) {
128945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            bin_group *found;
129045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /* Need to find group containing section this section follows. */
129145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            found = find_group_by_name(&info.vma_groups,
129245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                       vma_group->bsd->vfollows);
129345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (!found) {
129445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                yasm_error_set(YASM_ERROR_VALUE,
129545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                               N_("section `%s' vfollows an invalid or unknown section `%s'"),
129645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                               yasm_section_get_name(vma_group->section),
129745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                               vma_group->bsd->vfollows);
129845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                yasm_errwarn_propagate(errwarns, 0);
129945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                yasm_intnum_destroy(start);
130045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                bin_objfmt_cleanup(&info);
130145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                return;
130245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
130345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
130445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /* Check for loops */
130545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (vma_group->section == found->section ||
130645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                find_group_by_section(&vma_group->follow_groups,
130745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                      found->section)) {
130845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                yasm_error_set(YASM_ERROR_VALUE,
130945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                               N_("vfollows loop between section `%s' and section `%s'"),
131045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                               yasm_section_get_name(vma_group->section),
131145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                               yasm_section_get_name(found->section));
131245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                yasm_errwarn_propagate(errwarns, 0);
131345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                bin_objfmt_cleanup(&info);
131445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                return;
131545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
131645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
131745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /* Remove this section from main lma groups list */
131845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            TAILQ_REMOVE(&info.vma_groups, vma_group, link);
131945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /* Add it after the section it's supposed to follow. */
132045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            TAILQ_INSERT_TAIL(&found->follow_groups, vma_group, link);
132145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
132245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
132345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
132445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Due to the combination of steps above, we now know that all top-level
132545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * groups have integer ivstart:
132645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * Vstart Vfollows Valign   Handled by
132745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     *     No       No     No   group_assign_start_recurse()
132845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     *     No       No    Yes   group_assign_start_recurse()
132945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     *     No      Yes    -     vfollows loop (above)
133045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     *    Yes      -      -     bin_lma_create_group()
133145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     */
133245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    TAILQ_FOREACH(vma_group, &info.vma_groups, link) {
133345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_intnum_set(start, vma_group->bsd->ivstart);
133445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        group_assign_vstart_recurse(vma_group, start, errwarns);
133545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
133645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
133745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Output map file */
133845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    output_map(&info);
133945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
134045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Ensure we don't have overlapping progbits LMAs.
134145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * Use a dumb O(N^2) algorithm as the number of sections is essentially
134245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * always low.
134345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     */
134445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (yasm_object_sections_traverse(object, NULL, check_lma_overlap)) {
134545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_errwarn_propagate(errwarns, 0);
134645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_intnum_destroy(start);
134745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        bin_objfmt_cleanup(&info);
134845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return;
134945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
135045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
135145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Output sections */
135245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_object_sections_traverse(object, &info, bin_objfmt_output_section);
135345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
135445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Clean up */
135545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_intnum_destroy(start);
135645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bin_objfmt_cleanup(&info);
135745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
135845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
135945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void
136045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgbin_objfmt_destroy(yasm_objfmt *objfmt)
136145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
136245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_objfmt_bin *objfmt_bin = (yasm_objfmt_bin *)objfmt;
136345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (objfmt_bin->map_filename)
136445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_xfree(objfmt_bin->map_filename);
136545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_expr_destroy(objfmt_bin->org);
136645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_xfree(objfmt);
136745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
136845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
136945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void
137045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgdefine_section_symbol(yasm_symtab *symtab, yasm_section *sect,
137145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                      const char *sectname, const char *suffix,
137245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                      enum bin_ssym which, unsigned long line)
137345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
137445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_symrec *sym;
137545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bin_symrec_data *bsymd = yasm_xmalloc(sizeof(bin_symrec_data));
137645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    char *symname = yasm_xmalloc(8+strlen(sectname)+strlen(suffix)+1);
137745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
137845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    strcpy(symname, "section.");
137945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    strcat(symname, sectname);
138045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    strcat(symname, suffix);
138145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
138245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bsymd->section = sect;
138345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bsymd->which = which;
138445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
138545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    sym = yasm_symtab_declare(symtab, symname, YASM_SYM_EXTERN, line);
138645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_xfree(symname);
138745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_symrec_add_data(sym, &bin_symrec_data_cb, bsymd);
138845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
138945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
1390a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.orgstatic void
1391a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.orgbin_objfmt_init_new_section(yasm_section *sect, unsigned long line)
139245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
1393a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org    yasm_object *object = yasm_section_get_object(sect);
1394a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org    const char *sectname = yasm_section_get_name(sect);
139545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*yasm_objfmt_bin *objfmt_bin = (yasm_objfmt_bin *)object->objfmt;*/
139645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bin_section_data *data;
139745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
139845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    data = yasm_xmalloc(sizeof(bin_section_data));
139945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    data->bss = 0;
140045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    data->align = NULL;
140145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    data->valign = NULL;
140245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    data->start = NULL;
140345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    data->vstart = NULL;
140445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    data->follows = NULL;
140545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    data->vfollows = NULL;
140645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    data->istart = NULL;
140745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    data->ivstart = NULL;
140845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    data->length = NULL;
140945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_section_add_data(sect, &bin_section_data_cb, data);
141045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
141145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    define_section_symbol(object->symtab, sect, sectname, ".start",
141245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                          SSYM_START, line);
141345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    define_section_symbol(object->symtab, sect, sectname, ".vstart",
141445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                          SSYM_VSTART, line);
141545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    define_section_symbol(object->symtab, sect, sectname, ".length",
141645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                          SSYM_LENGTH, line);
141745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
141845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
141945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic yasm_section *
142045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgbin_objfmt_add_default_section(yasm_object *object)
142145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
142245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_section *retval;
142345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int isnew;
142445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
142545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    retval = yasm_object_get_general(object, ".text", 0, 1, 0, &isnew, 0);
1426a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org    if (isnew)
142745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_section_set_default(retval, 1);
142845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return retval;
142945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
143045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
1431a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org/* GAS-style flags */
1432a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.orgstatic int
1433a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.orgbin_helper_gasflags(void *obj, yasm_valparam *vp, unsigned long line, void *d,
1434a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                    /*@unused@*/ uintptr_t arg)
1435a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org{
1436a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org    /* TODO */
1437a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org    return 0;
1438a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org}
1439a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org
144045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic /*@observer@*/ /*@null@*/ yasm_section *
144145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgbin_objfmt_section_switch(yasm_object *object, yasm_valparamhead *valparams,
144245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                          /*@unused@*/ /*@null@*/
144345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                          yasm_valparamhead *objext_valparams,
144445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                          unsigned long line)
144545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
144645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_valparam *vp;
144745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_section *retval;
144845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int isnew;
144945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int flags_override = 0;
145045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    const char *sectname;
145145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bin_section_data *bsd = NULL;
145245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
145345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    struct bin_section_switch_data {
145445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /*@only@*/ /*@null@*/ char *follows;
145545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /*@only@*/ /*@null@*/ char *vfollows;
145645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /*@only@*/ /*@null@*/ yasm_expr *start;
145745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /*@only@*/ /*@null@*/ yasm_expr *vstart;
145845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /*@only@*/ /*@null@*/ yasm_intnum *align;
145945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /*@only@*/ /*@null@*/ yasm_intnum *valign;
146045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        unsigned long bss;
146145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        unsigned long code;
146245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    } data;
146345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
146445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    static const yasm_dir_help help[] = {
146545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        { "follows", 1, yasm_dir_helper_string,
146645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org          offsetof(struct bin_section_switch_data, follows), 0 },
146745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        { "vfollows", 1, yasm_dir_helper_string,
146845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org          offsetof(struct bin_section_switch_data, vfollows), 0 },
146945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        { "start", 1, yasm_dir_helper_expr,
147045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org          offsetof(struct bin_section_switch_data, start), 0 },
147145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        { "vstart", 1, yasm_dir_helper_expr,
147245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org          offsetof(struct bin_section_switch_data, vstart), 0 },
147345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        { "align", 1, yasm_dir_helper_intn,
147445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org          offsetof(struct bin_section_switch_data, align), 0 },
147545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        { "valign", 1, yasm_dir_helper_intn,
147645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org          offsetof(struct bin_section_switch_data, valign), 0 },
147745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        { "nobits", 0, yasm_dir_helper_flag_set,
147845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org          offsetof(struct bin_section_switch_data, bss), 1 },
147945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        { "progbits", 0, yasm_dir_helper_flag_set,
148045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org          offsetof(struct bin_section_switch_data, bss), 0 },
148145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        { "code", 0, yasm_dir_helper_flag_set,
148245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org          offsetof(struct bin_section_switch_data, code), 1 },
148345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        { "data", 0, yasm_dir_helper_flag_set,
148445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org          offsetof(struct bin_section_switch_data, code), 0 },
148545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        { "execute", 0, yasm_dir_helper_flag_set,
148645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org          offsetof(struct bin_section_switch_data, code), 1 },
148745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        { "noexecute", 0, yasm_dir_helper_flag_set,
1488a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org          offsetof(struct bin_section_switch_data, code), 0 },
1489a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org        { "gasflags", 1, bin_helper_gasflags, 0, 0 }
149045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    };
149145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
149245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    vp = yasm_vps_first(valparams);
149345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    sectname = yasm_vp_string(vp);
149445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (!sectname)
149545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return NULL;
149645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    vp = yasm_vps_next(vp);
149745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
149845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    retval = yasm_object_find_general(object, sectname);
149945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (retval) {
150045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        bsd = yasm_section_get_data(retval, &bin_section_data_cb);
150145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        assert(bsd != NULL);
150245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        data.follows = bsd->follows;
150345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        data.vfollows = bsd->vfollows;
150445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        data.start = bsd->start;
150545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        data.vstart = bsd->vstart;
150645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        data.align = NULL;
150745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        data.valign = NULL;
150845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        data.bss = bsd->bss;
150945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        data.code = yasm_section_is_code(retval);
151045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    } else {
151145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        data.follows = NULL;
151245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        data.vfollows = NULL;
151345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        data.start = NULL;
151445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        data.vstart = NULL;
151545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        data.align = NULL;
151645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        data.valign = NULL;
151745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        data.bss = strcmp(sectname, ".bss") == 0;
151845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        data.code = strcmp(sectname, ".text") == 0;
151945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
152045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
152145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    flags_override = yasm_dir_helper(object, vp, line, help, NELEMS(help),
152245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                     &data, yasm_dir_helper_valparam_warn);
152345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (flags_override < 0)
152445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return NULL;    /* error occurred */
152545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
152645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (data.start && data.follows) {
152745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_error_set(YASM_ERROR_GENERAL,
152845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            N_("cannot combine `start' and `follows' section attributes"));
152945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return NULL;
153045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
153145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
153245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (data.vstart && data.vfollows) {
153345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_error_set(YASM_ERROR_GENERAL,
153445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            N_("cannot combine `vstart' and `vfollows' section attributes"));
153545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return NULL;
153645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
153745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
153845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (data.align) {
153945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        unsigned long align = yasm_intnum_get_uint(data.align);
154045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
154145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* Alignments must be a power of two. */
154245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (!is_exp2(align)) {
154345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_error_set(YASM_ERROR_VALUE,
154445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                           N_("argument to `%s' is not a power of two"),
154545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                           "align");
154645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return NULL;
154745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
154845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    } else
154945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        data.align = bsd ? bsd->align : NULL;
155045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
155145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (data.valign) {
155245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        unsigned long valign = yasm_intnum_get_uint(data.valign);
155345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
155445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* Alignments must be a power of two. */
155545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (!is_exp2(valign)) {
155645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_error_set(YASM_ERROR_VALUE,
155745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                           N_("argument to `%s' is not a power of two"),
155845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                           "valign");
155945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return NULL;
156045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
156145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    } else
156245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        data.valign = bsd ? bsd->valign : NULL;
156345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
156445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    retval = yasm_object_get_general(object, sectname, 0, (int)data.code,
156545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                     (int)data.bss, &isnew, line);
156645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
1567a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org    bsd = yasm_section_get_data(retval, &bin_section_data_cb);
156845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
156945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (isnew || yasm_section_is_default(retval)) {
157045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_section_set_default(retval, 0);
157145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
157245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
157345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Update section flags */
157445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bsd->bss = data.bss;
157545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bsd->align = data.align;
157645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bsd->valign = data.valign;
157745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bsd->start = data.start;
157845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bsd->vstart = data.vstart;
157945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bsd->follows = data.follows;
158045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bsd->vfollows = data.vfollows;
158145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
158245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return retval;
158345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
158445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
158545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic /*@observer@*/ /*@null@*/ yasm_symrec *
158645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgbin_objfmt_get_special_sym(yasm_object *object, const char *name,
158745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                           const char *parser)
158845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
158945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return NULL;
159045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
159145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
159245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void
159345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgbin_objfmt_dir_org(yasm_object *object,
159445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                   /*@null@*/ yasm_valparamhead *valparams,
159545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                   /*@unused@*/ /*@null@*/
159645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                   yasm_valparamhead *objext_valparams, unsigned long line)
159745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
159845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_objfmt_bin *objfmt_bin = (yasm_objfmt_bin *)object->objfmt;
159945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_valparam *vp;
160045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
160145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* We only allow a single ORG in a program. */
160245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (objfmt_bin->org) {
160345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_error_set(YASM_ERROR_GENERAL, N_("program origin redefined"));
160445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return;
160545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
160645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
160745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* ORG takes just a simple expression as param */
160845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    vp = yasm_vps_first(valparams);
160945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    objfmt_bin->org = yasm_vp_expr(vp, object->symtab, line);
161045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (!objfmt_bin->org) {
161145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_error_set(YASM_ERROR_SYNTAX,
161245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                       N_("argument to ORG must be expression"));
161345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return;
161445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
161545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
161645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
161745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstruct bin_dir_map_data {
161845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned long flags;
161945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*@only@*/ /*@null@*/ char *filename;
162045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org};
162145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
162245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int
162345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgdir_map_filename(void *obj, yasm_valparam *vp, unsigned long line, void *data)
162445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
162545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    struct bin_dir_map_data *mdata = (struct bin_dir_map_data *)data;
162645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    const char *filename;
162745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
162845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (mdata->filename) {
162945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_warn_set(YASM_WARN_GENERAL, N_("map file already specified"));
163045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return 0;
163145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
163245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
163345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    filename = yasm_vp_string(vp);
163445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (!filename) {
163545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_error_set(YASM_ERROR_SYNTAX,
163645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                       N_("unexpected expression in [map]"));
163745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return -1;
163845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
163945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    mdata->filename = yasm__xstrdup(filename);
164045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
164145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return 1;
164245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
164345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
164445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void
164545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgbin_objfmt_dir_map(yasm_object *object,
164645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                   /*@null@*/ yasm_valparamhead *valparams,
164745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                   /*@unused@*/ /*@null@*/
164845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                   yasm_valparamhead *objext_valparams, unsigned long line)
164945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
165045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_objfmt_bin *objfmt_bin = (yasm_objfmt_bin *)object->objfmt;
165145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
165245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    struct bin_dir_map_data data;
165345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
165445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    static const yasm_dir_help help[] = {
165545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        { "all", 0, yasm_dir_helper_flag_or,
165645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org          offsetof(struct bin_dir_map_data, flags),
165745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org          MAP_BRIEF|MAP_SECTIONS|MAP_SYMBOLS },
165845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        { "brief", 0, yasm_dir_helper_flag_or,
165945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org          offsetof(struct bin_dir_map_data, flags), MAP_BRIEF },
166045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        { "sections", 0, yasm_dir_helper_flag_or,
166145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org          offsetof(struct bin_dir_map_data, flags), MAP_SECTIONS },
166245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        { "segments", 0, yasm_dir_helper_flag_or,
166345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org          offsetof(struct bin_dir_map_data, flags), MAP_SECTIONS },
166445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        { "symbols", 0, yasm_dir_helper_flag_or,
166545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org          offsetof(struct bin_dir_map_data, flags), MAP_SYMBOLS }
166645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    };
166745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
166845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    data.flags = objfmt_bin->map_flags | MAP_NONE;
166945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    data.filename = objfmt_bin->map_filename;
167045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
167145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (valparams && yasm_dir_helper(object, yasm_vps_first(valparams), line, help,
167245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                     NELEMS(help), &data, dir_map_filename) < 0)
167345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return;     /* error occurred */
167445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
167545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    objfmt_bin->map_flags = data.flags;
167645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    objfmt_bin->map_filename = data.filename;
167745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
167845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
167945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void
168045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgbin_section_data_destroy(void *data)
168145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
168245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bin_section_data *bsd = (bin_section_data *)data;
168345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (bsd->start)
168445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_expr_destroy(bsd->start);
168545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (bsd->vstart)
168645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_expr_destroy(bsd->vstart);
168745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (bsd->follows)
168845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_xfree(bsd->follows);
168945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (bsd->vfollows)
169045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_xfree(bsd->vfollows);
169145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (bsd->istart)
169245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_intnum_destroy(bsd->istart);
169345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (bsd->ivstart)
169445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_intnum_destroy(bsd->ivstart);
169545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (bsd->length)
169645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_intnum_destroy(bsd->length);
169745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_xfree(data);
169845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
169945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
170045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void
170145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgbin_section_data_print(void *data, FILE *f, int indent_level)
170245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
170345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bin_section_data *bsd = (bin_section_data *)data;
170445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
170545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fprintf(f, "%*sbss=%d\n", indent_level, "", bsd->bss);
170645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
170745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fprintf(f, "%*salign=", indent_level, "");
170845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (bsd->align)
170945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_intnum_print(bsd->align, f);
171045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    else
171145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        fprintf(f, "(nil)");
171245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fprintf(f, "\n%*svalign=", indent_level, "");
171345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (bsd->valign)
171445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_intnum_print(bsd->valign, f);
171545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    else
171645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        fprintf(f, "(nil)");
171745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
171845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fprintf(f, "\n%*sstart=", indent_level, "");
171945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_expr_print(bsd->start, f);
172045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fprintf(f, "\n%*svstart=", indent_level, "");
172145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_expr_print(bsd->vstart, f);
172245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
172345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fprintf(f, "\n%*sfollows=", indent_level, "");
172445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (bsd->follows)
172545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        fprintf(f, "\"%s\"", bsd->follows);
172645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    else
172745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        fprintf(f, "(nil)");
172845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fprintf(f, "\n%*svfollows=", indent_level, "");
172945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (bsd->vfollows)
173045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        fprintf(f, "\"%s\"", bsd->vfollows);
173145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    else
173245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        fprintf(f, "(nil)");
173345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
173445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fprintf(f, "\n%*sistart=", indent_level, "");
173545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (bsd->istart)
173645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_intnum_print(bsd->istart, f);
173745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    else
173845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        fprintf(f, "(nil)");
173945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fprintf(f, "\n%*sivstart=", indent_level, "");
174045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (bsd->ivstart)
174145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_intnum_print(bsd->ivstart, f);
174245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    else
174345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        fprintf(f, "(nil)");
174445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
174545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fprintf(f, "\n%*slength=", indent_level, "");
174645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (bsd->length)
174745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_intnum_print(bsd->length, f);
174845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    else
174945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        fprintf(f, "(nil)");
175045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fprintf(f, "\n");
175145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
175245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
175345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void
175445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgbin_symrec_data_destroy(void *data)
175545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
175645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_xfree(data);
175745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
175845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
175945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void
176045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgbin_symrec_data_print(void *data, FILE *f, int indent_level)
176145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
176245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bin_symrec_data *bsymd = (bin_symrec_data *)data;
176345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
176445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fprintf(f, "%*ssection=\"%s\"\n", indent_level, "",
176545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_section_get_name(bsymd->section));
176645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fprintf(f, "%*swhich=", indent_level, "");
176745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    switch (bsymd->which) {
176845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case SSYM_START: fprintf(f, "START"); break;
176945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case SSYM_VSTART: fprintf(f, "VSTART"); break;
177045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case SSYM_LENGTH: fprintf(f, "LENGTH"); break;
177145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
177245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fprintf(f, "\n");
177345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
177445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
177545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
177645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* Define valid debug formats to use with this object format */
177745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic const char *bin_objfmt_dbgfmt_keywords[] = {
177845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "null",
177945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    NULL
178045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org};
178145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
178245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic const yasm_directive bin_objfmt_directives[] = {
178345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    { "org",    "nasm", bin_objfmt_dir_org,     YASM_DIR_ARG_REQUIRED },
178445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    { "map",    "nasm", bin_objfmt_dir_map,     YASM_DIR_ANY },
178545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    { NULL, NULL, NULL, 0 }
178645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org};
178745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
178845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic const char *bin_nasm_stdmac[] = {
178945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%imacro org 1+.nolist",
179045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "[org %1]",
179145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%endmacro",
179245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    NULL
179345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org};
179445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
179545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic const yasm_stdmac bin_objfmt_stdmacs[] = {
179645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    { "nasm", "nasm", bin_nasm_stdmac },
179745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    { "tasm", "tasm", bin_nasm_stdmac },
179845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    { NULL, NULL, NULL }
179945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org};
180045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
180145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* Define objfmt structure -- see objfmt.h for details */
180245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_objfmt_module yasm_bin_LTX_objfmt = {
180345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "Flat format binary",
180445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "bin",
180545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    NULL,
180645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    16,
180745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    0,
180845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bin_objfmt_dbgfmt_keywords,
180945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "null",
181045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bin_objfmt_directives,
181145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bin_objfmt_stdmacs,
181245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bin_objfmt_create,
181345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bin_objfmt_output,
181445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bin_objfmt_destroy,
181545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bin_objfmt_add_default_section,
1816a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org    bin_objfmt_init_new_section,
181745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bin_objfmt_section_switch,
181845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bin_objfmt_get_special_sym
181945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org};
182045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
182145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#define EXE_HEADER_SIZE 0x200
182245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
182345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* DOS .EXE binaries are just raw binaries with a header */
182445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_objfmt_module yasm_dosexe_LTX_objfmt;
182545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
182645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic yasm_objfmt *
182745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgdosexe_objfmt_create(yasm_object *object)
182845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
182945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_objfmt_bin *objfmt_bin = (yasm_objfmt_bin *) bin_objfmt_create(object);
183045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    objfmt_bin->objfmt.module = &yasm_dosexe_LTX_objfmt;
183145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return (yasm_objfmt *)objfmt_bin;
183245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
183345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
183445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic unsigned long
183545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgget_sym(yasm_object *object, const char *name) {
183645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_symrec *symrec = yasm_symtab_get(object->symtab, name);
183745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_bytecode *prevbc;
183845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (!symrec)
183945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return 0;
184045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (!yasm_symrec_get_label(symrec, &prevbc))
184145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return 0;
184245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return prevbc->offset + prevbc->len;
184345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
184445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
184545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void
184645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgdosexe_objfmt_output(yasm_object *object, FILE *f, /*@unused@*/ int all_syms,
184745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                  yasm_errwarns *errwarns)
184845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
184945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned long tot_size, size, bss_size;
185045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned long start, bss;
185145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned char c;
185245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
185345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fseek(f, EXE_HEADER_SIZE, SEEK_SET);
185445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
185545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bin_objfmt_output(object, f, all_syms, errwarns);
185645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
185745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    tot_size = ftell(f);
185845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
185945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* if there is a __bss_start symbol, data after it is 0, no need to write
186045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * it.  */
186145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bss = get_sym(object, "__bss_start");
186245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (bss)
186345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        size = bss;
186445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    else
186545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        size = tot_size;
186645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bss_size = tot_size - size;
186745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#ifdef HAVE_FTRUNCATE
186845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (size != tot_size)
186945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        ftruncate(fileno(f), EXE_HEADER_SIZE + size);
187045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#endif
187145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fseek(f, 0, SEEK_SET);
187245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
187345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* magic */
187445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fwrite("MZ", 1, 2, f);
187545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
187645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* file size */
187745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    c = size & 0xff;
187845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fwrite(&c, 1, 1, f);
187945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    c = !!(size & 0x100);
188045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fwrite(&c, 1, 1, f);
188145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    c = ((size + 511) >> 9) & 0xff;
188245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fwrite(&c, 1, 1, f);
188345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    c = ((size + 511) >> 17) & 0xff;
188445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fwrite(&c, 1, 1, f);
188545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
188645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* relocation # */
188745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    c = 0;
188845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fwrite(&c, 1, 1, f);
188945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fwrite(&c, 1, 1, f);
189045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
189145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* header size */
189245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    c = EXE_HEADER_SIZE / 16;
189345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fwrite(&c, 1, 1, f);
189445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    c = 0;
189545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fwrite(&c, 1, 1, f);
189645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
189745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* minimum paragraph # */
189845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bss_size = (bss_size + 15) >> 4;
189945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    c = bss_size & 0xff;
190045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fwrite(&c, 1, 1, f);
190145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    c = (bss_size >> 8) & 0xff;
190245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fwrite(&c, 1, 1, f);
190345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
190445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* maximum paragraph # */
190545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    c = 0xFF;
190645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fwrite(&c, 1, 1, f);
190745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fwrite(&c, 1, 1, f);
190845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
190945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* relative value of stack segment */
191045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    c = 0;
191145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fwrite(&c, 1, 1, f);
191245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fwrite(&c, 1, 1, f);
191345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
191445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* SP at start */
191545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    c = 0;
191645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fwrite(&c, 1, 1, f);
191745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fwrite(&c, 1, 1, f);
191845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
191945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* header checksum */
192045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    c = 0;
192145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fwrite(&c, 1, 1, f);
192245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fwrite(&c, 1, 1, f);
192345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
192445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* IP at start */
192545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    start = get_sym(object, "start");
192645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (!start) {
192745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_error_set(YASM_ERROR_GENERAL,
192845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                N_("%s: could not find symbol `start'"));
192945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return;
193045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
193145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    c = start & 0xff;
193245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fwrite(&c, 1, 1, f);
193345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    c = (start >> 8) & 0xff;
193445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fwrite(&c, 1, 1, f);
193545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
193645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* CS start */
193745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    c = 0;
193845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fwrite(&c, 1, 1, f);
193945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fwrite(&c, 1, 1, f);
194045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
194145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* reloc start */
194245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    c = 0x22;
194345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fwrite(&c, 1, 1, f);
194445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    c = 0;
194545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fwrite(&c, 1, 1, f);
194645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
194745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Overlay number */
194845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    c = 0;
194945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fwrite(&c, 1, 1, f);
195045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fwrite(&c, 1, 1, f);
195145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
195245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
195345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
195445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* Define objfmt structure -- see objfmt.h for details */
195545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_objfmt_module yasm_dosexe_LTX_objfmt = {
195645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "DOS .EXE format binary",
195745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "dosexe",
195845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "exe",
195945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    16,
196045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    0,
196145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bin_objfmt_dbgfmt_keywords,
196245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "null",
196345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bin_objfmt_directives,
196445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bin_objfmt_stdmacs,
196545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    dosexe_objfmt_create,
196645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    dosexe_objfmt_output,
196745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bin_objfmt_destroy,
196845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bin_objfmt_add_default_section,
1969a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org    bin_objfmt_init_new_section,
197045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bin_objfmt_section_switch,
197145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bin_objfmt_get_special_sym
197245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org};
1973