145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*
245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * ELF object format
345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *
445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *  Copyright (C) 2003-2007  Michael Urman
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/* Notes
3045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *
3145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * elf-objfmt uses the "linking" view of an ELF file:
3245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * ELF header, an optional program header table, several sections,
3345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * and a section header table
3445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *
3545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * The ELF header tells us some overall program information,
3645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *   where to find the PHT (if it exists) with phnum and phentsize,
3745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *   and where to find the SHT with shnum and shentsize
3845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *
3945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * The PHT doesn't seem to be generated by NASM for elftest.asm
4045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *
4145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * The SHT
4245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *
4345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Each Section is spatially disjoint, and has exactly one SHT entry.
4445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
4545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
4645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include <libyasm.h>
4745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
4845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "elf.h"
4945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "elf-machine.h"
5045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
5145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgtypedef struct yasm_objfmt_elf {
5245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_objfmt_base objfmt;            /* base structure */
5345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
5445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_symtab_head* elf_symtab;        /* symbol table of indexed syms */
5545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_strtab_head* shstrtab;          /* section name strtab */
5645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_strtab_head* strtab;            /* strtab entries */
5745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
5845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_strtab_entry *file_strtab_entry;/* .file symbol associated string */
5945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_symrec *dotdotsym;             /* ..sym symbol */
6045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} yasm_objfmt_elf;
6145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
6245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgtypedef struct {
6345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_objfmt_elf *objfmt_elf;
6445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_errwarns *errwarns;
6545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    FILE *f;
6645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_secthead *shead;
6745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_section *sect;
6845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_object *object;
6945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned long sindex;
70a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org    yasm_symrec *GOT_sym;
7145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} elf_objfmt_output_info;
7245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
7345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgtypedef struct {
7445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_object *object;
7545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_objfmt_elf *objfmt_elf;
7645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_errwarns *errwarns;
7745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int local_names;
7845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} build_symtab_info;
7945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
8045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_objfmt_module yasm_elf_LTX_objfmt;
8145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_objfmt_module yasm_elf32_LTX_objfmt;
8245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_objfmt_module yasm_elf64_LTX_objfmt;
8345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
8445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
8545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic elf_symtab_entry *
8645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgelf_objfmt_symtab_append(yasm_objfmt_elf *objfmt_elf, yasm_symrec *sym,
8745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                         elf_section_index sectidx, elf_symbol_binding bind,
8845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                         elf_symbol_type type, elf_symbol_vis vis,
8945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                         yasm_expr *size, elf_address *value,
9045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                         yasm_object *object)
9145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
9245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_symtab_entry *entry = yasm_symrec_get_data(sym, &elf_symrec_data);
9345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
9445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (!entry) {
9545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /*@only@*/ char *symname = yasm_symrec_get_global_name(sym, object);
9645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        elf_strtab_entry *name =
9745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            elf_strtab_append_str(objfmt_elf->strtab, symname);
9845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_xfree(symname);
9945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        entry = elf_symtab_entry_create(name, sym);
10045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_symrec_add_data(sym, &elf_symrec_data, entry);
10145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
10245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
10345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Only append to table if not already appended */
10445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (!elf_sym_in_table(entry))
10545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        elf_symtab_append_entry(objfmt_elf->elf_symtab, entry);
10645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
10745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_symtab_set_nonzero(entry, NULL, sectidx, bind, type, size, value);
10845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_sym_set_visibility(entry, vis);
10945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
11045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return entry;
11145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
11245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
11345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic elf_symtab_entry *
11445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgbuild_extern(yasm_objfmt_elf *objfmt_elf, yasm_symrec *sym, yasm_object *object)
11545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
11645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_valparamhead *objext_valparams =
11745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_symrec_get_objext_valparams(sym);
11845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
11945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (objext_valparams) {
12045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_valparam *vp = yasm_vps_first(objext_valparams);
12145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        for (; vp; vp = yasm_vps_next(vp)) {
12245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (yasm_vp_string(vp))
12345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                yasm_error_set(YASM_ERROR_TYPE,
12445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                               N_("unrecognized symbol type `%s'"),
12545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                               yasm_vp_string(vp));
12645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
12745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
12845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
12945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return elf_objfmt_symtab_append(objfmt_elf, sym, SHN_UNDEF, STB_GLOBAL, 0,
13045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                    STV_DEFAULT, NULL, NULL, object);
13145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
13245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
13345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstruct elf_build_global_data {
13445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_expr *size;
13545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned long type; /* elf_symbol_type */
13645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_symbol_vis vis;
13745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned int vis_overrides;
13845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org};
13945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
14045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int
14145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgelf_global_helper_valparam(void *obj, yasm_valparam *vp, unsigned long line,
14245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                           void *d)
14345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
14445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
14545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    struct elf_build_global_data *data = (struct elf_build_global_data *)d;
14645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    const char *s;
14745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
14845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (!vp->val && (s = yasm_vp_id(vp))) {
14945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_error_set(YASM_ERROR_TYPE, N_("unrecognized symbol type `%s'"),
15045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                       s);
15145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return -1;
15245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    } else if (!vp->val && vp->type == YASM_PARAM_EXPR && !data->size) {
15345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        data->size = yasm_expr_copy(vp->param.e);
15445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return 0;
15545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    } else
15645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return yasm_dir_helper_valparam_warn(obj, vp, line, d);
15745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
15845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
15945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int
16045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgelf_global_helper_vis(void *obj, yasm_valparam *vp, unsigned long line,
16145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                      void *d, uintptr_t vis)
16245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
16345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    struct elf_build_global_data *data = (struct elf_build_global_data *)d;
16445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    data->vis = vis;
16545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    data->vis_overrides++;
16645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return 0;
16745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
16845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
16945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
17045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic elf_symtab_entry *
17145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgbuild_global(yasm_objfmt_elf *objfmt_elf, yasm_symrec *sym, yasm_object *object)
17245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
17345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_valparamhead *objext_valparams =
17445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_symrec_get_objext_valparams(sym);
17545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
17645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    struct elf_build_global_data data;
17745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
17845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    static const yasm_dir_help help[] = {
17945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        { "function", 0, yasm_dir_helper_flag_set,
18045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org          offsetof(struct elf_build_global_data, type), STT_FUNC },
18145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        { "data", 0, yasm_dir_helper_flag_set,
18245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org          offsetof(struct elf_build_global_data, type), STT_OBJECT },
18345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        { "object", 0, yasm_dir_helper_flag_set,
18445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org          offsetof(struct elf_build_global_data, type), STT_OBJECT },
18545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        { "internal", 0, elf_global_helper_vis, 0, STV_INTERNAL },
18645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        { "hidden", 0, elf_global_helper_vis, 0, STV_HIDDEN },
18745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        { "protected", 0, elf_global_helper_vis, 0, STV_PROTECTED },
18845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    };
18945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
19045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    data.size = NULL;
19145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    data.type = 0;
19245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    data.vis = STV_DEFAULT;
19345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    data.vis_overrides = 0;
19445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
19545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (objext_valparams)
19645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_dir_helper(sym, yasm_vps_first(objext_valparams),
19745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        yasm_symrec_get_decl_line(sym), help, NELEMS(help),
19845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        &data, elf_global_helper_valparam);
19945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
20045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (data.vis_overrides > 1) {
20145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_warn_set(YASM_WARN_GENERAL,
20245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            N_("More than one symbol visibility provided; using last"));
20345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
20445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
20545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return elf_objfmt_symtab_append(objfmt_elf, sym, SHN_UNDEF, STB_GLOBAL,
20645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                    data.type, data.vis, data.size, NULL,
20745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                    object);
20845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
20945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
21045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic /*@null@*/ elf_symtab_entry *
21145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgbuild_common(yasm_objfmt_elf *objfmt_elf, yasm_symrec *sym, yasm_object *object)
21245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
21345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_expr **size = yasm_symrec_get_common_size(sym);
21445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_valparamhead *objext_valparams =
21545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_symrec_get_objext_valparams(sym);
21645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned long addralign = 0;
21745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
21845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (objext_valparams) {
21945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_valparam *vp = yasm_vps_first(objext_valparams);
22045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        for (; vp; vp = yasm_vps_next(vp)) {
22145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (!vp->val) {
22245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                /*@only@*/ /*@null@*/ yasm_expr *align_expr;
22345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                /*@dependent@*/ /*@null@*/ const yasm_intnum *align_intn;
22445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
22545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (!(align_expr = yasm_vp_expr(vp, object->symtab,
22645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                                yasm_symrec_get_def_line(sym)))
22745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    || !(align_intn = yasm_expr_get_intnum(&align_expr, 0))) {
22845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    yasm_error_set(YASM_ERROR_VALUE,
22945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        N_("alignment constraint is not an integer"));
23045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    if (align_expr)
23145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        yasm_expr_destroy(align_expr);
23245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    return NULL;
23345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
23445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                addralign = yasm_intnum_get_uint(align_intn);
23545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                yasm_expr_destroy(align_expr);
23645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
23745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                /* Alignments must be a power of two. */
23845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (!is_exp2(addralign)) {
23945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    yasm_error_set(YASM_ERROR_VALUE,
24045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        N_("alignment constraint is not a power of two"));
24145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    return NULL;
24245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
24345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            } else
24445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                yasm_warn_set(YASM_WARN_GENERAL,
24545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                              N_("Unrecognized qualifier `%s'"), vp->val);
24645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
24745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
24845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
24945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return elf_objfmt_symtab_append(objfmt_elf, sym, SHN_COMMON, STB_GLOBAL,
25045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                    0, STV_DEFAULT, *size, &addralign, object);
25145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
25245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
25345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int
25445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgelf_objfmt_build_symtab(yasm_symrec *sym, /*@null@*/ void *d)
25545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
25645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    build_symtab_info *info = (build_symtab_info *)d;
25745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_sym_vis vis = yasm_symrec_get_visibility(sym);
25845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_sym_status status = yasm_symrec_get_status(sym);
25945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_symtab_entry *entry = yasm_symrec_get_data(sym, &elf_symrec_data);
26045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_address value=0;
26145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_section *sect=NULL;
26245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_bytecode *precbc=NULL;
26345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
26445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    assert(info != NULL);
26545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
26645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (vis & YASM_SYM_EXTERN) {
26745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        entry = build_extern(info->objfmt_elf, sym, info->object);
26845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_errwarn_propagate(info->errwarns,
26945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                               yasm_symrec_get_decl_line(sym));
27045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return 0;
27145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
27245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
27345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (vis & YASM_SYM_COMMON) {
27445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        entry = build_common(info->objfmt_elf, sym, info->object);
27545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_errwarn_propagate(info->errwarns,
27645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                               yasm_symrec_get_decl_line(sym));
27745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* If the COMMON variable was actually defined, fall through. */
27845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (!(status & YASM_SYM_DEFINED))
27945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return 0;
28045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
28145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
28245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Ignore any undefined at this point. */
28345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (!(status & YASM_SYM_DEFINED))
28445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return 0;
28545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
28645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (!yasm_symrec_get_label(sym, &precbc)) {
28745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (!yasm_symrec_get_equ(sym) && !yasm_symrec_is_abs(sym))
28845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return 0;
28945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        precbc = NULL;
29045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
29145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
29245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (precbc)
29345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        sect = yasm_bc_get_section(precbc);
29445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
29545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (entry && elf_sym_in_table(entry))
29645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        ;
29745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    else if (vis & YASM_SYM_GLOBAL) {
29845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        entry = build_global(info->objfmt_elf, sym, info->object);
29945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_errwarn_propagate(info->errwarns, yasm_symrec_get_decl_line(sym));
30045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    } else {
30145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        int is_sect = 0;
30245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
30345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* Locals (except when debugging) do not need to be
30445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         * in the symbol table, unless they're a section.
30545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         */
30645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (sect &&
30745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            strcmp(yasm_symrec_get_name(sym), yasm_section_get_name(sect))==0)
30845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            is_sect = 1;
30945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#if 0
31045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* FIXME: to enable this we must have handling in place for special
31145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         * symbols.
31245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         */
31345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (!info->local_names && !is_sect)
31445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return 0;
31545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#else
31645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (yasm_symrec_get_equ(sym) && !yasm_symrec_is_abs(sym))
31745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return 0;
31845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#endif
31945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        entry = yasm_symrec_get_data(sym, &elf_symrec_data);
32045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (!entry) {
32145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /*@only@*/ char *symname =
32245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                yasm_symrec_get_global_name(sym, info->object);
32345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            elf_strtab_entry *name = !info->local_names || is_sect ? NULL :
32445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                elf_strtab_append_str(info->objfmt_elf->strtab, symname);
32545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_xfree(symname);
32645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            entry = elf_symtab_entry_create(name, sym);
32745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_symrec_add_data(sym, &elf_symrec_data, entry);
32845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
32945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
33045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (!elf_sym_in_table(entry))
33145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            elf_symtab_insert_local_sym(info->objfmt_elf->elf_symtab, entry);
33245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
33345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        elf_symtab_set_nonzero(entry, sect, 0, STB_LOCAL,
33445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                               is_sect ? STT_SECTION : 0, NULL, 0);
33545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
33645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (is_sect)
33745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return 0;
33845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
33945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
34045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (precbc)
34145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        value = yasm_bc_next_offset(precbc);
34245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_symtab_set_nonzero(entry, sect, 0, 0, 0, NULL, &value);
34345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
34445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return 0;
34545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
34645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
34745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic yasm_objfmt *
34845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgelf_objfmt_create_common(yasm_object *object, yasm_objfmt_module *module,
34945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                         int bits_pref,
35045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                         const elf_machine_handler **elf_march_out)
35145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
35245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_objfmt_elf *objfmt_elf = yasm_xmalloc(sizeof(yasm_objfmt_elf));
35345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_symrec *filesym;
35445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_symtab_entry *entry;
35545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    const elf_machine_handler *elf_march;
35645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
35745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    objfmt_elf->objfmt.module = module;
35845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_march = elf_set_arch(object->arch, object->symtab, bits_pref);
35945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (!elf_march) {
36045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_xfree(objfmt_elf);
36145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return NULL;
36245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
36345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (elf_march_out)
36445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *elf_march_out = elf_march;
36545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
36645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    objfmt_elf->shstrtab = elf_strtab_create();
36745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    objfmt_elf->strtab = elf_strtab_create();
36845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    objfmt_elf->elf_symtab = elf_symtab_create();
36945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
37045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* FIXME: misuse of NULL bytecode here; it works, but only barely. */
37145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    filesym = yasm_symtab_define_label(object->symtab, ".file", NULL, 0, 0);
37245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Put in current input filename; we'll replace it in output() */
37345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    objfmt_elf->file_strtab_entry =
37445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        elf_strtab_append_str(objfmt_elf->strtab, object->src_filename);
37545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    entry = elf_symtab_entry_create(objfmt_elf->file_strtab_entry, filesym);
37645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_symrec_add_data(filesym, &elf_symrec_data, entry);
37745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_symtab_set_nonzero(entry, NULL, SHN_ABS, STB_LOCAL, STT_FILE, NULL,
37845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                           NULL);
37945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_symtab_append_entry(objfmt_elf->elf_symtab, entry);
38045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
38145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* FIXME: misuse of NULL bytecode */
38245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    objfmt_elf->dotdotsym =
38345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_symtab_define_label(object->symtab, "..sym", NULL, 0, 0);
38445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
38545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return (yasm_objfmt *)objfmt_elf;
38645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
38745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
38845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic yasm_objfmt *
38945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgelf_objfmt_create(yasm_object *object)
39045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
39145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    const elf_machine_handler *elf_march;
39245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_objfmt *objfmt;
39345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_objfmt_elf *objfmt_elf;
39445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
39545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    objfmt = elf_objfmt_create_common(object, &yasm_elf_LTX_objfmt, 0,
39645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                      &elf_march);
39745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (objfmt) {
39845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        objfmt_elf = (yasm_objfmt_elf *)objfmt;
39945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* Figure out which bitness of object format to use */
40045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (elf_march->bits == 32)
40145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            objfmt_elf->objfmt.module = &yasm_elf32_LTX_objfmt;
40245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else if (elf_march->bits == 64)
40345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            objfmt_elf->objfmt.module = &yasm_elf64_LTX_objfmt;
40445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
40545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return objfmt;
40645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
40745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
40845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic yasm_objfmt *
40945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgelf32_objfmt_create(yasm_object *object)
41045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
41145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return elf_objfmt_create_common(object, &yasm_elf32_LTX_objfmt, 32, NULL);
41245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
41345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
41445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic yasm_objfmt *
41545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgelf64_objfmt_create(yasm_object *object)
41645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
41745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return elf_objfmt_create_common(object, &yasm_elf64_LTX_objfmt, 64, NULL);
41845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
41945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
42045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic long
42145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgelf_objfmt_output_align(FILE *f, unsigned int align)
42245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
42345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    long pos;
42445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned long delta;
42545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (!is_exp2(align))
42645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_internal_error("requested alignment not a power of two");
42745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
42845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    pos = ftell(f);
42945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (pos == -1) {
43045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_error_set(YASM_ERROR_IO,
43145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                       N_("could not get file position on output file"));
43245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return -1;
43345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
43445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    delta = align - (pos & (align-1));
43545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (delta != align) {
43645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        pos += delta;
43745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (fseek(f, pos, SEEK_SET) < 0) {
43845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_error_set(YASM_ERROR_IO,
43945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                           N_("could not set file position on output file"));
44045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return -1;
44145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
44245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
44345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return pos;
44445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
44545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
44645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int
44745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgelf_objfmt_output_reloc(yasm_symrec *sym, yasm_bytecode *bc,
44845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        unsigned char *buf, unsigned int destsize,
44945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        unsigned int valsize, int warn, void *d)
45045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
45145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_reloc_entry *reloc;
45245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_objfmt_output_info *info = d;
45345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_intnum *zero;
45445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int retval;
45545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
45645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    reloc = elf_reloc_entry_create(sym, NULL,
457a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org        yasm_intnum_create_uint(bc->offset), 0, valsize, 0);
45845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (reloc == NULL) {
45945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_error_set(YASM_ERROR_TYPE, N_("elf: invalid relocation size"));
46045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return 1;
46145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
46245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* allocate .rel[a] sections on a need-basis */
46345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_secthead_append_reloc(info->sect, info->shead, reloc);
46445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
46545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    zero = yasm_intnum_create_uint(0);
466a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org    elf_handle_reloc_addend(zero, reloc, 0);
46745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    retval = yasm_arch_intnum_tobytes(info->object->arch, zero, buf, destsize,
46845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                      valsize, 0, bc, warn);
46945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_intnum_destroy(zero);
47045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return retval;
47145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
47245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
47345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int
47445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgelf_objfmt_output_value(yasm_value *value, unsigned char *buf,
47545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        unsigned int destsize, unsigned long offset,
47645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        yasm_bytecode *bc, int warn, /*@null@*/ void *d)
47745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
47845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*@null@*/ elf_objfmt_output_info *info = (elf_objfmt_output_info *)d;
47945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*@dependent@*/ /*@null@*/ yasm_intnum *intn;
48045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned long intn_val;
48145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*@null@*/ elf_reloc_entry *reloc = NULL;
48245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int retval;
48345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned int valsize = value->size;
48445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
48545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (info == NULL)
48645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_internal_error("null info struct");
48745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
48845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (value->abs)
48945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        value->abs = yasm_expr_simplify(value->abs, 1);
49045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
49145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Try to output constant and PC-relative section-local first.
49245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * Note this does NOT output any value with a SEG, WRT, external,
49345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * cross-section, or non-PC-relative reference (those are handled below).
49445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     */
49545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    switch (yasm_value_output_basic(value, buf, destsize, bc, warn,
49645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                    info->object->arch)) {
49745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case -1:
49845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return 1;
49945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case 0:
50045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            break;
50145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        default:
50245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return 0;
50345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
50445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
50545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Handle other expressions, with relocation if necessary */
50645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (value->seg_of || value->section_rel || value->rshift > 0) {
50745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_error_set(YASM_ERROR_TOO_COMPLEX,
50845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                       N_("elf: relocation too complex"));
50945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return 1;
51045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
51145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
51245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    intn_val = 0;
51345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (value->rel) {
51445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_sym_vis vis = yasm_symrec_get_visibility(value->rel);
51545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /*@dependent@*/ /*@null@*/ yasm_symrec *sym = value->rel;
51645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /*@dependent@*/ /*@null@*/ yasm_symrec *wrt = value->wrt;
51745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
51845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (wrt == info->objfmt_elf->dotdotsym)
51945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            wrt = NULL;
52045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else if (wrt && elf_is_wrt_sym_relative(wrt))
52145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            ;
52245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else if (wrt && elf_is_wrt_pos_adjusted(wrt))
52345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            intn_val = offset + bc->offset;
52445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else if (vis == YASM_SYM_LOCAL) {
52545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_bytecode *sym_precbc;
52645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /* Local symbols need relocation to their section's start, and
52745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * add in the offset of the bytecode (within the target section)
52845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * into the abs portion.
52945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             *
53045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * This is only done if the symbol is relocated against the
53145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * section instead of the symbol itself.
53245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             */
53345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (yasm_symrec_get_label(sym, &sym_precbc)) {
53445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                /* Relocate to section start */
53545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                yasm_section *sym_sect = yasm_bc_get_section(sym_precbc);
53645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                /*@null@*/ elf_secthead *sym_shead;
53745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                sym_shead = yasm_section_get_data(sym_sect, &elf_section_data);
53845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                assert(sym_shead != NULL);
53945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                sym = elf_secthead_get_sym(sym_shead);
54045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
54145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                intn_val = yasm_bc_next_offset(sym_precbc);
54245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
54345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
54445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
54545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* For PC-relative, need to add offset of expression within bc. */
54645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (value->curpos_rel)
54745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            intn_val += offset;
54845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
549a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org        /* Check for _GLOBAL_OFFSET_TABLE_ symbol reference */
55045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        reloc = elf_reloc_entry_create(sym, wrt,
55145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_intnum_create_uint(bc->offset + offset), value->curpos_rel,
552a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org            valsize, sym == info->GOT_sym);
55345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (reloc == NULL) {
55445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_error_set(YASM_ERROR_TYPE,
55545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                           N_("elf: invalid relocation (WRT or size)"));
55645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return 1;
55745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
55845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* allocate .rel[a] sections on a need-basis */
55945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        elf_secthead_append_reloc(info->sect, info->shead, reloc);
56045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
56145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
56245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    intn = yasm_intnum_create_uint(intn_val);
56345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
56445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (value->abs) {
56545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_intnum *intn2 = yasm_expr_get_intnum(&value->abs, 0);
56645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (!intn2) {
56745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_error_set(YASM_ERROR_TOO_COMPLEX,
56845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                           N_("elf: relocation too complex"));
56945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_intnum_destroy(intn);
57045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return 1;
57145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
57245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_intnum_calc(intn, YASM_EXPR_ADD, intn2);
57345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
57445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
57545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (reloc)
576a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org        elf_handle_reloc_addend(intn, reloc, offset);
57745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    retval = yasm_arch_intnum_tobytes(info->object->arch, intn, buf, destsize,
57845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                      valsize, 0, bc, warn);
57945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_intnum_destroy(intn);
58045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return retval;
58145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
58245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
58345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int
58445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgelf_objfmt_output_bytecode(yasm_bytecode *bc, /*@null@*/ void *d)
58545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
58645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*@null@*/ elf_objfmt_output_info *info = (elf_objfmt_output_info *)d;
58745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned char buf[256];
58845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*@null@*/ /*@only@*/ unsigned char *bigbuf;
58945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned long size = 256;
59045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int gap;
59145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
59245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (info == NULL)
59345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_internal_error("null info struct");
59445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
59545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bigbuf = yasm_bc_tobytes(bc, buf, &size, &gap, info,
59645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                             elf_objfmt_output_value, elf_objfmt_output_reloc);
59745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
59845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Don't bother doing anything else if size ended up being 0. */
59945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (size == 0) {
60045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (bigbuf)
60145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_xfree(bigbuf);
60245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return 0;
60345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
60445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    else {
60545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_intnum *bcsize = yasm_intnum_create_uint(size);
60645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        elf_secthead_add_size(info->shead, bcsize);
60745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_intnum_destroy(bcsize);
60845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
60945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
61045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Warn that gaps are converted to 0 and write out the 0's. */
61145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (gap) {
61245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        unsigned long left;
61345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_warn_set(YASM_WARN_UNINIT_CONTENTS,
61445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            N_("uninitialized space declared in code/data section: zeroing"));
61545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* Write out in chunks */
61645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        memset(buf, 0, 256);
61745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        left = size;
61845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (left > 256) {
61945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            fwrite(buf, 256, 1, info->f);
62045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            left -= 256;
62145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
62245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        fwrite(buf, left, 1, info->f);
62345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    } else {
62445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* Output buf (or bigbuf if non-NULL) to file */
62545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        fwrite(bigbuf ? bigbuf : buf, (size_t)size, 1, info->f);
62645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
62745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
62845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* If bigbuf was allocated, free it */
62945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (bigbuf)
63045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_xfree(bigbuf);
63145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
63245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return 0;
63345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
63445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
63545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int
63645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgelf_objfmt_output_section(yasm_section *sect, /*@null@*/ void *d)
63745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
63845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*@null@*/ elf_objfmt_output_info *info = (elf_objfmt_output_info *)d;
63945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*@dependent@*/ /*@null@*/ elf_secthead *shead;
64045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    long pos;
64145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    char *relname;
64245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    const char *sectname;
64345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
64445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (info == NULL)
64545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_internal_error("null info struct");
64645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    shead = yasm_section_get_data(sect, &elf_section_data);
64745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (shead == NULL)
64845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_internal_error("no associated data");
64945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
65045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (elf_secthead_get_align(shead) == 0)
65145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        elf_secthead_set_align(shead, yasm_section_get_align(sect));
65245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
65345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* don't output header-only sections */
65445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if ((elf_secthead_get_type(shead) & SHT_NOBITS) == SHT_NOBITS)
65545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
65645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_bytecode *last = yasm_section_bcs_last(sect);
65745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (last) {
65845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_intnum *sectsize;
65945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            sectsize = yasm_intnum_create_uint(yasm_bc_next_offset(last));
66045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            elf_secthead_add_size(shead, sectsize);
66145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_intnum_destroy(sectsize);
66245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
66345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        elf_secthead_set_index(shead, ++info->sindex);
66445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return 0;
66545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
66645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
66745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if ((pos = ftell(info->f)) == -1) {
66845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_error_set(YASM_ERROR_IO,
66945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                       N_("couldn't read position on output stream"));
67045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_errwarn_propagate(info->errwarns, 0);
67145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
67245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    pos = elf_secthead_set_file_offset(shead, pos);
67345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (fseek(info->f, pos, SEEK_SET) < 0) {
67445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_error_set(YASM_ERROR_IO, N_("couldn't seek on output stream"));
67545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_errwarn_propagate(info->errwarns, 0);
67645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
67745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
67845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    info->sect = sect;
67945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    info->shead = shead;
68045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_section_bcs_traverse(sect, info->errwarns, info,
68145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                              elf_objfmt_output_bytecode);
68245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
68345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_secthead_set_index(shead, ++info->sindex);
68445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
68545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* No relocations to output?  Go on to next section */
68645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (elf_secthead_write_relocs_to_file(info->f, sect, shead,
68745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                          info->errwarns) == 0)
68845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return 0;
68945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_secthead_set_rel_index(shead, ++info->sindex);
69045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
69145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* name the relocation section .rel[a].foo */
69245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    sectname = yasm_section_get_name(sect);
69345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    relname = elf_secthead_name_reloc_section(sectname);
69445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_secthead_set_rel_name(shead,
69545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        elf_strtab_append_str(info->objfmt_elf->shstrtab, relname));
69645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_xfree(relname);
69745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
69845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return 0;
69945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
70045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
70145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int
70245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgelf_objfmt_output_secthead(yasm_section *sect, /*@null@*/ void *d)
70345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
70445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*@null@*/ elf_objfmt_output_info *info = (elf_objfmt_output_info *)d;
70545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*@dependent@*/ /*@null@*/ elf_secthead *shead;
70645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
70745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (info == NULL)
70845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_internal_error("null info struct");
70945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    shead = yasm_section_get_data(sect, &elf_section_data);
71045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (shead == NULL)
71145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_internal_error("no section header attached to section");
71245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
71345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if(elf_secthead_write_to_file(info->f, shead, info->sindex+1))
71445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        info->sindex++;
71545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
71645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* output strtab headers here? */
71745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
71845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* relocation entries for .foo are stored in section .rel[a].foo */
71945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if(elf_secthead_write_rel_to_file(info->f, 3, sect, shead,
72045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                      info->sindex+1))
72145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        info->sindex++;
72245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
72345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return 0;
72445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
72545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
72645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void
72745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgelf_objfmt_output(yasm_object *object, FILE *f, int all_syms,
72845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                  yasm_errwarns *errwarns)
72945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
73045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_objfmt_elf *objfmt_elf = (yasm_objfmt_elf *)object->objfmt;
73145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_objfmt_output_info info;
73245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    build_symtab_info buildsym_info;
73345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    long pos;
73445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned long elf_shead_addr;
73545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_secthead *esdn;
73645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned long elf_strtab_offset, elf_shstrtab_offset, elf_symtab_offset;
73745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned long elf_strtab_size, elf_shstrtab_size, elf_symtab_size;
73845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_strtab_entry *elf_strtab_name, *elf_shstrtab_name, *elf_symtab_name;
73945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned long elf_symtab_nlocal;
74045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
74145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    info.object = object;
74245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    info.objfmt_elf = objfmt_elf;
74345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    info.errwarns = errwarns;
74445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    info.f = f;
745a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org    info.GOT_sym = yasm_symtab_get(object->symtab, "_GLOBAL_OFFSET_TABLE_");
74645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
74745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Update filename strtab */
74845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_strtab_entry_set_str(objfmt_elf->file_strtab_entry,
74945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                             object->src_filename);
75045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
75145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Allocate space for Ehdr by seeking forward */
75245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (fseek(f, (long)(elf_proghead_get_size()), SEEK_SET) < 0) {
75345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_error_set(YASM_ERROR_IO, N_("could not seek on output file"));
75445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_errwarn_propagate(errwarns, 0);
75545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return;
75645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
75745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
75845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* add all (local) syms to symtab because relocation needs a symtab index
75945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * if all_syms, register them by name.  if not, use strtab entry 0 */
76045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    buildsym_info.object = object;
76145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    buildsym_info.objfmt_elf = objfmt_elf;
76245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    buildsym_info.errwarns = errwarns;
76345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    buildsym_info.local_names = all_syms;
76445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_symtab_traverse(object->symtab, &buildsym_info,
76545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                         elf_objfmt_build_symtab);
76645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_symtab_nlocal = elf_symtab_assign_indices(objfmt_elf->elf_symtab);
76745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
76845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* output known sections - includes reloc sections which aren't in yasm's
76945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * list.  Assign indices as we go. */
77045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    info.sindex = 3;
77145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (yasm_object_sections_traverse(object, &info,
77245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                      elf_objfmt_output_section))
77345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return;
77445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
77545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* add final sections to the shstrtab */
77645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_strtab_name = elf_strtab_append_str(objfmt_elf->shstrtab, ".strtab");
77745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_symtab_name = elf_strtab_append_str(objfmt_elf->shstrtab, ".symtab");
77845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_shstrtab_name = elf_strtab_append_str(objfmt_elf->shstrtab,
77945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                              ".shstrtab");
78045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
78145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* output .shstrtab */
78245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if ((pos = elf_objfmt_output_align(f, 4)) == -1) {
78345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_errwarn_propagate(errwarns, 0);
78445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return;
78545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
78645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_shstrtab_offset = (unsigned long) pos;
78745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_shstrtab_size = elf_strtab_output_to_file(f, objfmt_elf->shstrtab);
78845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
78945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* output .strtab */
79045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if ((pos = elf_objfmt_output_align(f, 4)) == -1) {
79145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_errwarn_propagate(errwarns, 0);
79245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return;
79345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
79445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_strtab_offset = (unsigned long) pos;
79545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_strtab_size = elf_strtab_output_to_file(f, objfmt_elf->strtab);
79645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
79745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* output .symtab - last section so all others have indexes */
79845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if ((pos = elf_objfmt_output_align(f, 4)) == -1) {
79945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_errwarn_propagate(errwarns, 0);
80045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return;
80145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
80245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_symtab_offset = (unsigned long) pos;
80345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_symtab_size = elf_symtab_write_to_file(f, objfmt_elf->elf_symtab,
80445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                               errwarns);
80545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
80645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* output section header table */
80745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if ((pos = elf_objfmt_output_align(f, 16)) == -1) {
80845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_errwarn_propagate(errwarns, 0);
80945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return;
81045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
81145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_shead_addr = (unsigned long) pos;
81245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
81345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* stabs debugging support */
81445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (strcmp(yasm_dbgfmt_keyword(object->dbgfmt), "stabs")==0) {
81545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_section *stabsect = yasm_object_find_general(object, ".stab");
81645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_section *stabstrsect =
81745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_object_find_general(object, ".stabstr");
81845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (stabsect && stabstrsect) {
81945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            elf_secthead *stab =
82045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                yasm_section_get_data(stabsect, &elf_section_data);
82145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            elf_secthead *stabstr =
82245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                yasm_section_get_data(stabstrsect, &elf_section_data);
82345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (stab && stabstr) {
82445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                elf_secthead_set_link(stab, elf_secthead_get_index(stabstr));
82545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
82645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else
82745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                yasm_internal_error(N_("missing .stab or .stabstr section/data"));
82845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
82945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
83045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
83145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* output dummy section header - 0 */
83245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    info.sindex = 0;
83345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
83445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    esdn = elf_secthead_create(NULL, SHT_NULL, 0, 0, 0);
83545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_secthead_set_index(esdn, 0);
83645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_secthead_write_to_file(f, esdn, 0);
83745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_secthead_destroy(esdn);
83845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
83945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    esdn = elf_secthead_create(elf_shstrtab_name, SHT_STRTAB, 0,
84045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                               elf_shstrtab_offset, elf_shstrtab_size);
84145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_secthead_set_index(esdn, 1);
84245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_secthead_write_to_file(f, esdn, 1);
84345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_secthead_destroy(esdn);
84445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
84545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    esdn = elf_secthead_create(elf_strtab_name, SHT_STRTAB, 0,
84645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                               elf_strtab_offset, elf_strtab_size);
84745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_secthead_set_index(esdn, 2);
84845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_secthead_write_to_file(f, esdn, 2);
84945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_secthead_destroy(esdn);
85045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
85145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    esdn = elf_secthead_create(elf_symtab_name, SHT_SYMTAB, 0,
85245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                               elf_symtab_offset, elf_symtab_size);
85345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_secthead_set_index(esdn, 3);
85445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_secthead_set_info(esdn, elf_symtab_nlocal);
85545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_secthead_set_link(esdn, 2);     /* for .strtab, which is index 2 */
85645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_secthead_write_to_file(f, esdn, 3);
85745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_secthead_destroy(esdn);
85845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
85945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    info.sindex = 3;
86045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* output remaining section headers */
86145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_object_sections_traverse(object, &info, elf_objfmt_output_secthead);
86245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
86345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* output Ehdr */
86445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (fseek(f, 0, SEEK_SET) < 0) {
86545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_error_set(YASM_ERROR_IO, N_("could not seek on output file"));
86645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_errwarn_propagate(errwarns, 0);
86745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return;
86845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
86945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
87045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_proghead_write_to_file(f, elf_shead_addr, info.sindex+1, 1);
87145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
87245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
87345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void
87445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgelf_objfmt_destroy(yasm_objfmt *objfmt)
87545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
87645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_objfmt_elf *objfmt_elf = (yasm_objfmt_elf *)objfmt;
87745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_symtab_destroy(objfmt_elf->elf_symtab);
87845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_strtab_destroy(objfmt_elf->shstrtab);
87945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_strtab_destroy(objfmt_elf->strtab);
88045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_xfree(objfmt);
88145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
88245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
883a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.orgstatic void
884a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.orgelf_objfmt_init_new_section(yasm_section *sect, unsigned long line)
88545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
886a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org    yasm_object *object = yasm_section_get_object(sect);
887a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org    const char *sectname = yasm_section_get_name(sect);
88845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_objfmt_elf *objfmt_elf = (yasm_objfmt_elf *)object->objfmt;
88945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_secthead *esd;
89045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_symrec *sym;
89145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_strtab_entry *name = elf_strtab_append_str(objfmt_elf->shstrtab,
89245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                                   sectname);
89345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
894a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org    elf_section_type type=SHT_PROGBITS;
895a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org    elf_size entsize=0;
896a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org
897a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org    if (yasm__strcasecmp(sectname, ".stab")==0) {
898a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org        entsize = 12;
899a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org    } else if (yasm__strcasecmp(sectname, ".stabstr")==0) {
900a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org        type = SHT_STRTAB;
901a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org    }
902a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org
903a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org    esd = elf_secthead_create(name, type, 0, 0, 0);
904a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org    elf_secthead_set_entsize(esd, entsize);
90545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_section_add_data(sect, &elf_section_data, esd);
90645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    sym = yasm_symtab_define_label(object->symtab, sectname,
90745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                   yasm_section_bcs_first(sect), 1, line);
90845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
90945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_secthead_set_sym(esd, sym);
91045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
91145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
91245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic yasm_section *
91345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgelf_objfmt_add_default_section(yasm_object *object)
91445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
91545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_section *retval;
91645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int isnew;
91745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
91845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    retval = yasm_object_get_general(object, ".text", 16, 1, 0, &isnew, 0);
919a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org    if (isnew)
920a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org    {
921a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org        elf_secthead *esd = yasm_section_get_data(retval, &elf_section_data);
922a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org        elf_secthead_set_typeflags(esd, SHT_PROGBITS,
923a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                                   SHF_ALLOC + SHF_EXECINSTR);
924a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org        yasm_section_set_default(retval, 1);
925a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org    }
92645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return retval;
92745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
92845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
92945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstruct elf_section_switch_data {
93045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*@only@*/ /*@null@*/ yasm_intnum *align_intn;
93145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned long flags;
93245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned long type;
93345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int gasflags;
93445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int stdsect;
93545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org};
93645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
93745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* GAS-style flags */
93845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int
93945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgelf_helper_gasflags(void *obj, yasm_valparam *vp, unsigned long line, void *d,
94045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    /*@unused@*/ uintptr_t arg)
94145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
94245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    struct elf_section_switch_data *data = (struct elf_section_switch_data *)d;
94345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    const char *s = yasm_vp_string(vp);
94445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    size_t i;
94545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
94645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (!s) {
94745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_error_set(YASM_ERROR_VALUE,
94845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                       N_("non-string section attribute"));
94945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return -1;
95045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
95145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
95245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (data->stdsect && strlen(s) == 0) {
95345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        data->gasflags = 1;
95445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return 0;
95545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
95645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
95745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    data->flags = 0;
95845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    for (i=0; i<strlen(s); i++) {
95945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        switch (s[i]) {
96045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            case 'a':
96145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                data->flags |= SHF_ALLOC;
96245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                break;
96345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            case 'w':
96445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                data->flags |= SHF_WRITE;
96545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                break;
96645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            case 'x':
96745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                data->flags |= SHF_EXECINSTR;
96845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                break;
96945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            case 'M':
97045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                data->flags |= SHF_MERGE;
97145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                break;
97245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            case 'S':
97345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                data->flags |= SHF_STRINGS;
97445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                break;
97545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            case 'G':
97645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                data->flags |= SHF_GROUP;
97745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                break;
97845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            case 'T':
97945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                data->flags |= SHF_TLS;
98045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                break;
98145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            default:
98245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                yasm_warn_set(YASM_WARN_GENERAL,
98345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                              N_("unrecognized section attribute: `%c'"),
98445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                              s[i]);
98545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
98645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
98745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
98845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    data->gasflags = 1;
98945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return 0;
99045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
99145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
99245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic /*@observer@*/ /*@null@*/ yasm_section *
99345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgelf_objfmt_section_switch(yasm_object *object, yasm_valparamhead *valparams,
99445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                          /*@null@*/ yasm_valparamhead *objext_valparams,
99545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                          unsigned long line)
99645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
99745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_valparam *vp;
99845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_section *retval;
99945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int isnew;
100045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned long align = 4;
100145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int flags_override = 0;
100245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    const char *sectname;
100345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int resonly = 0;
100445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
100545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    struct elf_section_switch_data data;
100645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
100745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    static const yasm_dir_help help[] = {
100845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        { "alloc", 0, yasm_dir_helper_flag_or,
100945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org          offsetof(struct elf_section_switch_data, flags), SHF_ALLOC },
101045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        { "exec", 0, yasm_dir_helper_flag_or,
101145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org          offsetof(struct elf_section_switch_data, flags), SHF_EXECINSTR },
101245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        { "write", 0, yasm_dir_helper_flag_or,
101345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org          offsetof(struct elf_section_switch_data, flags), SHF_WRITE },
101445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        { "tls", 0, yasm_dir_helper_flag_or,
101545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org          offsetof(struct elf_section_switch_data, flags), SHF_TLS },
101645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        { "progbits", 0, yasm_dir_helper_flag_set,
101745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org          offsetof(struct elf_section_switch_data, type), SHT_PROGBITS },
101845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        { "noalloc", 0, yasm_dir_helper_flag_and,
101945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org          offsetof(struct elf_section_switch_data, flags), SHF_ALLOC },
102045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        { "noexec", 0, yasm_dir_helper_flag_and,
102145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org          offsetof(struct elf_section_switch_data, flags), SHF_EXECINSTR },
102245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        { "nowrite",  0, yasm_dir_helper_flag_and,
102345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org          offsetof(struct elf_section_switch_data, flags), SHF_WRITE },
102445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        { "notls",  0, yasm_dir_helper_flag_and,
102545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org          offsetof(struct elf_section_switch_data, flags), SHF_TLS },
102645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        { "noprogbits", 0, yasm_dir_helper_flag_set,
102745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org          offsetof(struct elf_section_switch_data, type), SHT_NOBITS },
102845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        { "nobits", 0, yasm_dir_helper_flag_set,
102945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org          offsetof(struct elf_section_switch_data, type), SHT_NOBITS },
103045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        { "gasflags", 1, elf_helper_gasflags, 0, 0 },
103145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        { "align", 1, yasm_dir_helper_intn,
103245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org          offsetof(struct elf_section_switch_data, align_intn), 0 }
103345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    };
103445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*@only@*/ /*@null@*/ yasm_expr *merge_expr = NULL;
103545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*@dependent@*/ /*@null@*/ const yasm_intnum *merge_intn = NULL;
103645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_secthead *esd;
103745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
103845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    data.align_intn = NULL;
103945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    data.flags = SHF_ALLOC;
104045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    data.type = SHT_PROGBITS;
104145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    data.gasflags = 0;
104245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    data.stdsect = 1;
104345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
104445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    vp = yasm_vps_first(valparams);
104545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    sectname = yasm_vp_string(vp);
104645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (!sectname)
104745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return NULL;
104845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    vp = yasm_vps_next(vp);
104945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
105045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (strcmp(sectname, ".bss") == 0) {
105145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        data.type = SHT_NOBITS;
105245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        data.flags = SHF_ALLOC + SHF_WRITE;
105345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        resonly = 1;
105445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    } else if (strcmp(sectname, ".data") == 0) {
105545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        data.type = SHT_PROGBITS;
105645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        data.flags = SHF_ALLOC + SHF_WRITE;
105745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    } else if (strcmp(sectname, ".tdata") == 0) {
105845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        data.type = SHT_PROGBITS;
105945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        data.flags = SHF_ALLOC + SHF_WRITE + SHF_TLS;
106045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    } else if (strcmp(sectname, ".rodata") == 0) {
106145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        data.type = SHT_PROGBITS;
106245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        data.flags = SHF_ALLOC;
106345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    } else if (strcmp(sectname, ".text") == 0) {
106445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        align = 16;
106545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        data.type = SHT_PROGBITS;
106645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        data.flags = SHF_ALLOC + SHF_EXECINSTR;
106745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    } else if (strcmp(sectname, ".comment") == 0) {
106845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        align = 0;
106945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        data.type = SHT_PROGBITS;
107045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        data.flags = 0;
107145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    } else {
107245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* Default to code */
107345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        align = 1;
107445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        data.stdsect = 0;
107545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
107645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
107745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    flags_override = yasm_dir_helper(object, vp, line, help, NELEMS(help),
107845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                     &data, yasm_dir_helper_valparam_warn);
107945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (flags_override < 0)
108045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return NULL;    /* error occurred */
108145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
108245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (data.align_intn) {
108345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        align = yasm_intnum_get_uint(data.align_intn);
108445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_intnum_destroy(data.align_intn);
108545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
108645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* Alignments must be a power of two. */
108745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (!is_exp2(align)) {
108845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_error_set(YASM_ERROR_VALUE,
108945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                           N_("argument to `%s' is not a power of two"),
109045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                           "align");
109145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return NULL;
109245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
109345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
109445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
109545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Handle merge entity size */
109645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (data.flags & SHF_MERGE) {
109745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (objext_valparams && (vp = yasm_vps_first(objext_valparams))
109845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            && !vp->val) {
109945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (!(merge_expr = yasm_vp_expr(vp, object->symtab, line)) ||
110045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                !(merge_intn = yasm_expr_get_intnum(&merge_expr, 0)))
110145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                yasm_warn_set(YASM_WARN_GENERAL,
110245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                              N_("invalid merge entity size"));
110345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        } else {
110445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_warn_set(YASM_WARN_GENERAL,
110545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                          N_("entity size for SHF_MERGE not specified"));
110645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            data.flags &= ~SHF_MERGE;
110745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
110845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
110945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
111045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    retval = yasm_object_get_general(object, sectname, align,
111145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                     (data.flags & SHF_EXECINSTR) != 0,
111245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                     resonly, &isnew, line);
111345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
1114a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org    esd = yasm_section_get_data(retval, &elf_section_data);
111545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
111645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (isnew || yasm_section_is_default(retval)) {
111745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_section_set_default(retval, 0);
111845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        elf_secthead_set_typeflags(esd, data.type, data.flags);
111945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (merge_intn)
112045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            elf_secthead_set_entsize(esd, yasm_intnum_get_uint(merge_intn));
112145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_section_set_align(retval, align, line);
112245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    } else if (flags_override && !data.gasflags)
112345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_warn_set(YASM_WARN_GENERAL,
112445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                      N_("section flags ignored on section redeclaration"));
112545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (merge_expr)
112645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_expr_destroy(merge_expr);
112745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return retval;
112845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
112945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
113045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic /*@observer@*/ /*@null@*/ yasm_symrec *
113145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgelf_objfmt_get_special_sym(yasm_object *object, const char *name,
113245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                           const char *parser)
113345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
113445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (yasm__strcasecmp(name, "sym") == 0) {
113545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_objfmt_elf *objfmt_elf = (yasm_objfmt_elf *)object->objfmt;
113645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return objfmt_elf->dotdotsym;
113745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
113845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return elf_get_special_sym(name, parser);
113945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
114045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
114145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void
114245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgdir_type(yasm_object *object, yasm_valparamhead *valparams,
114345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         yasm_valparamhead *objext_valparams, unsigned long line)
114445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
114545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_objfmt_elf *objfmt_elf = (yasm_objfmt_elf *)object->objfmt;
114645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_valparam *vp = yasm_vps_first(valparams);
114745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    const char *symname = yasm_vp_id(vp);
114845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Get symbol elf data */
114945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_symrec *sym = yasm_symtab_use(object->symtab, symname, line);
115045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_symtab_entry *entry = yasm_symrec_get_data(sym, &elf_symrec_data);
115145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*@null@*/ const char *type;
115245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
115345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Create entry if necessary */
115445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (!entry) {
115545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        entry = elf_symtab_entry_create(
115645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            elf_strtab_append_str(objfmt_elf->strtab, symname), sym);
115745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_symrec_add_data(sym, &elf_symrec_data, entry);
115845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
115945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
116045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Pull new type from param */
116145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    vp = yasm_vps_next(vp);
116245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (vp && !vp->val && (type = yasm_vp_id(vp))) {
116345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (yasm__strcasecmp(type, "function") == 0)
116445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            elf_sym_set_type(entry, STT_FUNC);
116545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else if (yasm__strcasecmp(type, "object") == 0)
116645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            elf_sym_set_type(entry, STT_OBJECT);
116745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else if (yasm__strcasecmp(type, "tls_object") == 0)
116845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            elf_sym_set_type(entry, STT_TLS);
116945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else if (yasm__strcasecmp(type, "notype") == 0)
117045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            elf_sym_set_type(entry, STT_NOTYPE);
117145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else
117245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_warn_set(YASM_WARN_GENERAL,
117345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                          N_("unrecognized symbol type `%s'"), type);
117445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    } else
117545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_error_set(YASM_ERROR_SYNTAX, N_("no type specified"));
117645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
117745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
117845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void
117945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgdir_size(yasm_object *object, yasm_valparamhead *valparams,
118045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         yasm_valparamhead *objext_valparams, unsigned long line)
118145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
118245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_objfmt_elf *objfmt_elf = (yasm_objfmt_elf *)object->objfmt;
118345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_valparam *vp = yasm_vps_first(valparams);
118445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    const char *symname = yasm_vp_id(vp);
118545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Get symbol elf data */
118645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_symrec *sym = yasm_symtab_use(object->symtab, symname, line);
118745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_symtab_entry *entry = yasm_symrec_get_data(sym, &elf_symrec_data);
118845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*@only@*/ /*@null@*/ yasm_expr *size;
118945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
119045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Create entry if necessary */
119145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (!entry) {
119245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        entry = elf_symtab_entry_create(
119345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            elf_strtab_append_str(objfmt_elf->strtab, symname), sym);
119445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_symrec_add_data(sym, &elf_symrec_data, entry);
119545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
119645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
119745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Pull new size from param */
119845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    vp = yasm_vps_next(vp);
119945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (vp && !vp->val && (size = yasm_vp_expr(vp, object->symtab, line)))
120045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        elf_sym_set_size(entry, size);
120145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    else
120245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_error_set(YASM_ERROR_SYNTAX, N_("no size specified"));
120345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
120445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
120545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void
120645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgdir_weak(yasm_object *object, yasm_valparamhead *valparams,
120745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         yasm_valparamhead *objext_valparams, unsigned long line)
120845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
120945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_objfmt_elf *objfmt_elf = (yasm_objfmt_elf *)object->objfmt;
121045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_valparam *vp = yasm_vps_first(valparams);
121145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    const char *symname = yasm_vp_id(vp);
121245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_symrec *sym = yasm_symtab_declare(object->symtab, symname,
121345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                           YASM_SYM_GLOBAL, line);
121445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_objfmt_symtab_append(objfmt_elf, sym, SHN_UNDEF, STB_WEAK, 0,
121545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                             STV_DEFAULT, NULL, NULL, object);
121645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
121745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
121845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void
121945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgdir_ident(yasm_object *object, yasm_valparamhead *valparams,
122045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org          yasm_valparamhead *objext_valparams, unsigned long line)
122145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
122245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_valparamhead sect_vps;
122345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_datavalhead dvs;
122445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_section *comment;
122545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_valparam *vp;
122645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_valparam *vp2;
122745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
122845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Accept, but do nothing with empty ident */
122945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (!valparams)
123045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return;
123145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    vp = yasm_vps_first(valparams);
123245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (!vp)
123345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return;
123445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
123545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Put ident data into .comment section */
123645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_vps_initialize(&sect_vps);
123745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    vp2 = yasm_vp_create_string(NULL, yasm__xstrdup(".comment"));
123845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_vps_append(&sect_vps, vp2);
123945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    comment = elf_objfmt_section_switch(object, &sect_vps, NULL, line);
124045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_vps_delete(&sect_vps);
124145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
124245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* To match GAS output, if the comment section is empty, put an
124345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * initial 0 byte in the section.
124445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     */
124545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (yasm_section_bcs_first(comment) == yasm_section_bcs_last(comment)) {
124645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_dvs_initialize(&dvs);
124745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_dvs_append(&dvs, yasm_dv_create_expr(
124845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_expr_create_ident(
124945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                yasm_expr_int(yasm_intnum_create_uint(0)), line)));
125045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_section_bcs_append(comment,
125145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_bc_create_data(&dvs, 1, 0, object->arch, line));
125245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
125345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
125445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_dvs_initialize(&dvs);
125545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    do {
125645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        const char *s = yasm_vp_string(vp);
125745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (!s) {
125845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_error_set(YASM_ERROR_VALUE,
125945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                           N_(".comment requires string parameters"));
126045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_dvs_delete(&dvs);
126145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return;
126245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
126345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_dvs_append(&dvs,
126445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        yasm_dv_create_string(yasm__xstrdup(s), strlen(s)));
126545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    } while ((vp = yasm_vps_next(vp)));
126645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
126745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_section_bcs_append(comment,
126845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_bc_create_data(&dvs, 1, 1, object->arch, line));
126945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
127045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
127145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* Define valid debug formats to use with this object format */
127245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic const char *elf_objfmt_dbgfmt_keywords[] = {
127345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "null",
127445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "stabs",
127545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "dwarf2",
127645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    NULL
127745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org};
127845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
127945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic const yasm_directive elf_objfmt_directives[] = {
128045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    { ".type",          "gas",  dir_type,       YASM_DIR_ID_REQUIRED },
128145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    { ".size",          "gas",  dir_size,       YASM_DIR_ID_REQUIRED },
128245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    { ".weak",          "gas",  dir_weak,       YASM_DIR_ID_REQUIRED },
128345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    { ".ident",         "gas",  dir_ident,      YASM_DIR_ANY },
128445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    { "type",           "nasm", dir_type,       YASM_DIR_ID_REQUIRED },
128545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    { "size",           "nasm", dir_size,       YASM_DIR_ID_REQUIRED },
128645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    { "weak",           "nasm", dir_weak,       YASM_DIR_ID_REQUIRED },
128745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    { "ident",          "nasm", dir_ident,      YASM_DIR_ANY },
128845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    { NULL, NULL, NULL, 0 }
128945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org};
129045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
129145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic const char *elf_nasm_stdmac[] = {
129245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%imacro type 1+.nolist",
129345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "[type %1]",
129445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%endmacro",
129545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%imacro size 1+.nolist",
129645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "[size %1]",
129745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%endmacro",
129845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%imacro weak 1+.nolist",
129945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "[weak %1]",
130045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%endmacro",
130145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    NULL
130245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org};
130345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
130445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic const yasm_stdmac elf_objfmt_stdmacs[] = {
130545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    { "nasm", "nasm", elf_nasm_stdmac },
130645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    { NULL, NULL, NULL }
130745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org};
130845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
130945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* Define objfmt structure -- see objfmt.h for details */
131045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_objfmt_module yasm_elf_LTX_objfmt = {
131145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "ELF",
131245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "elf",
131345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "o",
131445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    32,
131545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    0,
131645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_objfmt_dbgfmt_keywords,
131745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "null",
131845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_objfmt_directives,
131945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_objfmt_stdmacs,
132045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_objfmt_create,
132145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_objfmt_output,
132245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_objfmt_destroy,
132345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_objfmt_add_default_section,
1324a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org    elf_objfmt_init_new_section,
132545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_objfmt_section_switch,
132645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_objfmt_get_special_sym
132745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org};
132845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
132945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_objfmt_module yasm_elf32_LTX_objfmt = {
133045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "ELF (32-bit)",
133145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "elf32",
133245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "o",
133345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    32,
133445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    0,
133545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_objfmt_dbgfmt_keywords,
133645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "null",
133745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_objfmt_directives,
133845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_objfmt_stdmacs,
133945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf32_objfmt_create,
134045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_objfmt_output,
134145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_objfmt_destroy,
134245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_objfmt_add_default_section,
1343a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org    elf_objfmt_init_new_section,
134445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_objfmt_section_switch,
134545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_objfmt_get_special_sym
134645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org};
134745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
134845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_objfmt_module yasm_elf64_LTX_objfmt = {
134945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "ELF (64-bit)",
135045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "elf64",
135145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "o",
135245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    64,
135345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    0,
135445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_objfmt_dbgfmt_keywords,
135545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "null",
135645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_objfmt_directives,
135745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_objfmt_stdmacs,
135845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf64_objfmt_create,
135945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_objfmt_output,
136045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_objfmt_destroy,
136145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_objfmt_add_default_section,
1362a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org    elf_objfmt_init_new_section,
136345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_objfmt_section_switch,
136445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elf_objfmt_get_special_sym
136545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org};
1366