/*
 * DWARF2 debugging format - address range table
 *
 *  Copyright (C) 2006-2007  Peter Johnson
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
#include <util.h>
/*@unused@*/ RCSID("$Id: dwarf2-aranges.c,v 1.1.1.1 2012/03/29 17:21:01 uid42307 Exp $");

#include <libyasm.h>

#include "dwarf2-dbgfmt.h"


static void
dwarf2_append_arange(yasm_section *debug_aranges, /*@only@*/ yasm_expr *start,
                     /*@only@*/ yasm_expr *length, unsigned int sizeof_address)
{
    yasm_datavalhead dvs;
    yasm_bytecode *bc;

    yasm_dvs_initialize(&dvs);
    yasm_dvs_append(&dvs, yasm_dv_create_expr(start));
    yasm_dvs_append(&dvs, yasm_dv_create_expr(length));
    bc = yasm_bc_create_data(&dvs, sizeof_address, 0, NULL, 0);
    yasm_bc_finalize(bc, yasm_dwarf2__append_bc(debug_aranges, bc));
    yasm_bc_calc_len(bc, NULL, NULL);
}

typedef struct dwarf2_aranges_info {
    yasm_section *debug_aranges;    /* section to which address ranges go */
    yasm_object *object;
    yasm_dbgfmt_dwarf2 *dbgfmt_dwarf2;
} dwarf2_aranges_info;

static int
dwarf2_generate_aranges_section(yasm_section *sect, /*@null@*/ void *d)
{
    dwarf2_aranges_info *info = (dwarf2_aranges_info *)d;
    yasm_dbgfmt_dwarf2 *dbgfmt_dwarf2 = info->dbgfmt_dwarf2;
    /*@null@*/ dwarf2_section_data *dsd;
    /*@only@*/ yasm_expr *start, *length;

    dsd = yasm_section_get_data(sect, &yasm_dwarf2__section_data_cb);
    if (!dsd)
        return 0;       /* no line data for this section */

    /* Create address range descriptor */
    start = yasm_expr_create_ident(
        yasm_expr_sym(yasm_dwarf2__bc_sym(info->object->symtab,
                                          yasm_section_bcs_first(sect))), 0);
    length = yasm_expr_create_ident(
        yasm_expr_int(yasm_calc_bc_dist(yasm_section_bcs_first(sect),
                                        yasm_section_bcs_last(sect))), 0);
    dwarf2_append_arange(info->debug_aranges, start, length,
                         dbgfmt_dwarf2->sizeof_address);

    return 0;
}

yasm_section *
yasm_dwarf2__generate_aranges(yasm_object *object, yasm_section *debug_info)
{
    yasm_dbgfmt_dwarf2 *dbgfmt_dwarf2 = (yasm_dbgfmt_dwarf2 *)object->dbgfmt;
    int new;
    yasm_section *debug_aranges;
    yasm_bytecode *bc;
    dwarf2_head *head;
    dwarf2_aranges_info info;

    debug_aranges =
        yasm_object_get_general(object, ".debug_aranges",
                                2*dbgfmt_dwarf2->sizeof_address, 0, 0, &new,
                                0);

    /* header */
    head = yasm_dwarf2__add_head(dbgfmt_dwarf2, debug_aranges, debug_info, 1,
                                 1);

    /* align ranges to 2x address size (range size) */
    bc = yasm_bc_create_align(
        yasm_expr_create_ident(yasm_expr_int(
            yasm_intnum_create_uint(dbgfmt_dwarf2->sizeof_address*2)), 0),
        NULL, NULL, NULL, 0);
    yasm_bc_finalize(bc, yasm_dwarf2__append_bc(debug_aranges, bc));
    yasm_bc_calc_len(bc, NULL, NULL);

    info.debug_aranges = debug_aranges;
    info.object = object;
    info.dbgfmt_dwarf2 = dbgfmt_dwarf2;

    yasm_object_sections_traverse(object, (void *)&info,
                                  dwarf2_generate_aranges_section);

    /* Terminate with empty address range descriptor */
    dwarf2_append_arange(debug_aranges,
        yasm_expr_create_ident(yasm_expr_int(yasm_intnum_create_uint(0)), 0),
        yasm_expr_create_ident(yasm_expr_int(yasm_intnum_create_uint(0)), 0),
        dbgfmt_dwarf2->sizeof_address);

    /* mark end of aranges information */
    yasm_dwarf2__set_head_end(head, yasm_section_bcs_last(debug_aranges));

    return debug_aranges;
}

