1/*
2 * DWARF2 debugging format - address range table
3 *
4 *  Copyright (C) 2006-2007  Peter Johnson
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
26 */
27#include <util.h>
28
29#include <libyasm.h>
30
31#include "dwarf2-dbgfmt.h"
32
33
34static void
35dwarf2_append_arange(yasm_section *debug_aranges, /*@only@*/ yasm_expr *start,
36                     /*@only@*/ yasm_expr *length, unsigned int sizeof_address)
37{
38    yasm_datavalhead dvs;
39    yasm_bytecode *bc;
40
41    yasm_dvs_initialize(&dvs);
42    yasm_dvs_append(&dvs, yasm_dv_create_expr(start));
43    yasm_dvs_append(&dvs, yasm_dv_create_expr(length));
44    bc = yasm_bc_create_data(&dvs, sizeof_address, 0, NULL, 0);
45    yasm_bc_finalize(bc, yasm_dwarf2__append_bc(debug_aranges, bc));
46    yasm_bc_calc_len(bc, NULL, NULL);
47}
48
49typedef struct dwarf2_aranges_info {
50    yasm_section *debug_aranges;    /* section to which address ranges go */
51    yasm_object *object;
52    yasm_dbgfmt_dwarf2 *dbgfmt_dwarf2;
53} dwarf2_aranges_info;
54
55static int
56dwarf2_generate_aranges_section(yasm_section *sect, /*@null@*/ void *d)
57{
58    dwarf2_aranges_info *info = (dwarf2_aranges_info *)d;
59    yasm_dbgfmt_dwarf2 *dbgfmt_dwarf2 = info->dbgfmt_dwarf2;
60    /*@null@*/ dwarf2_section_data *dsd;
61    /*@only@*/ yasm_expr *start, *length;
62
63    dsd = yasm_section_get_data(sect, &yasm_dwarf2__section_data_cb);
64    if (!dsd)
65        return 0;       /* no line data for this section */
66
67    /* Create address range descriptor */
68    start = yasm_expr_create_ident(
69        yasm_expr_sym(yasm_dwarf2__bc_sym(info->object->symtab,
70                                          yasm_section_bcs_first(sect))), 0);
71    length = yasm_expr_create_ident(
72        yasm_expr_int(yasm_calc_bc_dist(yasm_section_bcs_first(sect),
73                                        yasm_section_bcs_last(sect))), 0);
74    dwarf2_append_arange(info->debug_aranges, start, length,
75                         dbgfmt_dwarf2->sizeof_address);
76
77    return 0;
78}
79
80yasm_section *
81yasm_dwarf2__generate_aranges(yasm_object *object, yasm_section *debug_info)
82{
83    yasm_dbgfmt_dwarf2 *dbgfmt_dwarf2 = (yasm_dbgfmt_dwarf2 *)object->dbgfmt;
84    int new;
85    yasm_section *debug_aranges;
86    yasm_bytecode *bc;
87    dwarf2_head *head;
88    dwarf2_aranges_info info;
89
90    debug_aranges =
91        yasm_object_get_general(object, ".debug_aranges",
92                                2*dbgfmt_dwarf2->sizeof_address, 0, 0, &new,
93                                0);
94
95    /* header */
96    head = yasm_dwarf2__add_head(dbgfmt_dwarf2, debug_aranges, debug_info, 1,
97                                 1);
98
99    /* align ranges to 2x address size (range size) */
100    bc = yasm_bc_create_align(
101        yasm_expr_create_ident(yasm_expr_int(
102            yasm_intnum_create_uint(dbgfmt_dwarf2->sizeof_address*2)), 0),
103        NULL, NULL, NULL, 0);
104    yasm_bc_finalize(bc, yasm_dwarf2__append_bc(debug_aranges, bc));
105    yasm_bc_calc_len(bc, NULL, NULL);
106
107    info.debug_aranges = debug_aranges;
108    info.object = object;
109    info.dbgfmt_dwarf2 = dbgfmt_dwarf2;
110
111    yasm_object_sections_traverse(object, (void *)&info,
112                                  dwarf2_generate_aranges_section);
113
114    /* Terminate with empty address range descriptor */
115    dwarf2_append_arange(debug_aranges,
116        yasm_expr_create_ident(yasm_expr_int(yasm_intnum_create_uint(0)), 0),
117        yasm_expr_create_ident(yasm_expr_int(yasm_intnum_create_uint(0)), 0),
118        dbgfmt_dwarf2->sizeof_address);
119
120    /* mark end of aranges information */
121    yasm_dwarf2__set_head_end(head, yasm_section_bcs_last(debug_aranges));
122
123    return debug_aranges;
124}
125
126