Home | History | Annotate | Download | only in dwarf2
      1 /*
      2  * DWARF2 debugging format
      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 struct dwarf2_head {
     34     yasm_bytecode *start_prevbc;
     35     yasm_bytecode *end_prevbc;
     36     /*@null@*/ yasm_section *debug_ptr;
     37     int with_address;
     38     int with_segment;
     39 };
     40 
     41 /* Bytecode callback function prototypes */
     42 static void dwarf2_head_bc_destroy(void *contents);
     43 static void dwarf2_head_bc_print(const void *contents, FILE *f,
     44                                  int indent_level);
     45 static int dwarf2_head_bc_calc_len
     46     (yasm_bytecode *bc, yasm_bc_add_span_func add_span, void *add_span_data);
     47 static int dwarf2_head_bc_tobytes
     48     (yasm_bytecode *bc, unsigned char **bufp, unsigned char *bufstart, void *d,
     49      yasm_output_value_func output_value,
     50      /*@null@*/ yasm_output_reloc_func output_reloc);
     51 
     52 /* Bytecode callback structures */
     53 static const yasm_bytecode_callback dwarf2_head_bc_callback = {
     54     dwarf2_head_bc_destroy,
     55     dwarf2_head_bc_print,
     56     yasm_bc_finalize_common,
     57     NULL,
     58     dwarf2_head_bc_calc_len,
     59     yasm_bc_expand_common,
     60     dwarf2_head_bc_tobytes,
     61     0
     62 };
     63 
     64 /* Section data callback function prototypes */
     65 static void dwarf2_section_data_destroy(void *data);
     66 static void dwarf2_section_data_print(void *data, FILE *f, int indent_level);
     67 
     68 /* Section data callback */
     69 const yasm_assoc_data_callback yasm_dwarf2__section_data_cb = {
     70     dwarf2_section_data_destroy,
     71     dwarf2_section_data_print
     72 };
     73 
     74 yasm_dbgfmt_module yasm_dwarf2_LTX_dbgfmt;
     75 
     76 
     77 static /*@null@*/ /*@only@*/ yasm_dbgfmt *
     78 dwarf2_dbgfmt_create(yasm_object *object)
     79 {
     80     yasm_dbgfmt_dwarf2 *dbgfmt_dwarf2 =
     81         yasm_xmalloc(sizeof(yasm_dbgfmt_dwarf2));
     82     size_t i;
     83 
     84     dbgfmt_dwarf2->dbgfmt.module = &yasm_dwarf2_LTX_dbgfmt;
     85 
     86     dbgfmt_dwarf2->dirs_allocated = 32;
     87     dbgfmt_dwarf2->dirs_size = 0;
     88     dbgfmt_dwarf2->dirs =
     89         yasm_xmalloc(sizeof(char *)*dbgfmt_dwarf2->dirs_allocated);
     90 
     91     dbgfmt_dwarf2->filenames_allocated = 32;
     92     dbgfmt_dwarf2->filenames_size = 0;
     93     dbgfmt_dwarf2->filenames =
     94         yasm_xmalloc(sizeof(dwarf2_filename)*dbgfmt_dwarf2->filenames_allocated);
     95     for (i=0; i<dbgfmt_dwarf2->filenames_allocated; i++) {
     96         dbgfmt_dwarf2->filenames[i].pathname = NULL;
     97         dbgfmt_dwarf2->filenames[i].filename = NULL;
     98         dbgfmt_dwarf2->filenames[i].dir = 0;
     99     }
    100 
    101     dbgfmt_dwarf2->format = DWARF2_FORMAT_32BIT;    /* TODO: flexible? */
    102 
    103     dbgfmt_dwarf2->sizeof_address = yasm_arch_get_address_size(object->arch)/8;
    104     switch (dbgfmt_dwarf2->format) {
    105         case DWARF2_FORMAT_32BIT:
    106             dbgfmt_dwarf2->sizeof_offset = 4;
    107             break;
    108         case DWARF2_FORMAT_64BIT:
    109             dbgfmt_dwarf2->sizeof_offset = 8;
    110             break;
    111     }
    112     dbgfmt_dwarf2->min_insn_len = yasm_arch_min_insn_len(object->arch);
    113 
    114     return (yasm_dbgfmt *)dbgfmt_dwarf2;
    115 }
    116 
    117 static void
    118 dwarf2_dbgfmt_destroy(/*@only@*/ yasm_dbgfmt *dbgfmt)
    119 {
    120     yasm_dbgfmt_dwarf2 *dbgfmt_dwarf2 = (yasm_dbgfmt_dwarf2 *)dbgfmt;
    121     size_t i;
    122     for (i=0; i<dbgfmt_dwarf2->dirs_size; i++)
    123         if (dbgfmt_dwarf2->dirs[i])
    124             yasm_xfree(dbgfmt_dwarf2->dirs[i]);
    125     yasm_xfree(dbgfmt_dwarf2->dirs);
    126     for (i=0; i<dbgfmt_dwarf2->filenames_size; i++) {
    127         if (dbgfmt_dwarf2->filenames[i].pathname)
    128             yasm_xfree(dbgfmt_dwarf2->filenames[i].pathname);
    129         if (dbgfmt_dwarf2->filenames[i].filename)
    130             yasm_xfree(dbgfmt_dwarf2->filenames[i].filename);
    131     }
    132     yasm_xfree(dbgfmt_dwarf2->filenames);
    133     yasm_xfree(dbgfmt);
    134 }
    135 
    136 /* Add a bytecode to a section, updating offset on insertion;
    137  * no optimization necessary.
    138  */
    139 yasm_bytecode *
    140 yasm_dwarf2__append_bc(yasm_section *sect, yasm_bytecode *bc)
    141 {
    142     yasm_bytecode *precbc = yasm_section_bcs_last(sect);
    143     bc->offset = yasm_bc_next_offset(precbc);
    144     yasm_section_bcs_append(sect, bc);
    145     return precbc;
    146 }
    147 
    148 static void
    149 dwarf2_dbgfmt_generate(yasm_object *object, yasm_linemap *linemap,
    150                        yasm_errwarns *errwarns)
    151 {
    152     yasm_dbgfmt_dwarf2 *dbgfmt_dwarf2 = (yasm_dbgfmt_dwarf2 *)object->dbgfmt;
    153     size_t num_line_sections;
    154     /*@null@*/ yasm_section *debug_info, *debug_line, *main_code;
    155 
    156     /* If we don't have any .file directives, generate line information
    157      * based on the asm source.
    158      */
    159     debug_line = yasm_dwarf2__generate_line(object, linemap, errwarns,
    160                                             dbgfmt_dwarf2->filenames_size == 0,
    161                                             &main_code, &num_line_sections);
    162 
    163     /* If we don't have a .debug_info (or it's empty), generate the minimal
    164      * set of .debug_info, .debug_aranges, and .debug_abbrev so that the
    165      * .debug_line we're generating is actually useful.
    166      */
    167     debug_info = yasm_object_find_general(object, ".debug_info");
    168     if (num_line_sections > 0 &&
    169         (!debug_info || yasm_section_bcs_first(debug_info)
    170                         == yasm_section_bcs_last(debug_info))) {
    171         debug_info = yasm_dwarf2__generate_info(object, debug_line, main_code);
    172         yasm_dwarf2__generate_aranges(object, debug_info);
    173         /*yasm_dwarf2__generate_pubnames(object, debug_info);*/
    174     }
    175 }
    176 
    177 yasm_symrec *
    178 yasm_dwarf2__bc_sym(yasm_symtab *symtab, yasm_bytecode *bc)
    179 {
    180     /*@dependent@*/ yasm_symrec *sym;
    181     if (bc->symrecs && bc->symrecs[0])
    182         sym = bc->symrecs[0];
    183     else
    184         sym = yasm_symtab_define_label(symtab, ".bcsym", bc, 0, 0);
    185     return sym;
    186 }
    187 
    188 dwarf2_head *
    189 yasm_dwarf2__add_head
    190     (yasm_dbgfmt_dwarf2 *dbgfmt_dwarf2, yasm_section *sect,
    191      /*@null@*/ yasm_section *debug_ptr, int with_address, int with_segment)
    192 {
    193     dwarf2_head *head;
    194     yasm_bytecode *bc;
    195 
    196     head = yasm_xmalloc(sizeof(dwarf2_head));
    197     head->start_prevbc = yasm_section_bcs_last(sect);
    198 
    199     bc = yasm_bc_create_common(&dwarf2_head_bc_callback, head, 0);
    200     bc->len = dbgfmt_dwarf2->sizeof_offset + 2;
    201     if (dbgfmt_dwarf2->format == DWARF2_FORMAT_64BIT)
    202         bc->len += 4;
    203 
    204     if (debug_ptr) {
    205         head->debug_ptr = debug_ptr;
    206         bc->len += dbgfmt_dwarf2->sizeof_offset;
    207     } else
    208         head->debug_ptr = NULL;
    209 
    210     head->with_address = with_address;
    211     head->with_segment = with_segment;
    212     if (with_address)
    213         bc->len++;
    214     if (with_segment)
    215         bc->len++;
    216 
    217     head->end_prevbc = bc;
    218     yasm_dwarf2__append_bc(sect, bc);
    219     return head;
    220 }
    221 
    222 void
    223 yasm_dwarf2__set_head_end(dwarf2_head *head, yasm_bytecode *end_prevbc)
    224 {
    225     head->end_prevbc = end_prevbc;
    226 }
    227 
    228 static void
    229 dwarf2_head_bc_destroy(void *contents)
    230 {
    231     yasm_xfree(contents);
    232 }
    233 
    234 static void
    235 dwarf2_head_bc_print(const void *contents, FILE *f, int indent_level)
    236 {
    237     /* TODO */
    238 }
    239 
    240 static int
    241 dwarf2_head_bc_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
    242                         void *add_span_data)
    243 {
    244     yasm_internal_error(N_("tried to calc_len a dwarf2 head bytecode"));
    245     /*@notreached@*/
    246     return 0;
    247 }
    248 
    249 static int
    250 dwarf2_head_bc_tobytes(yasm_bytecode *bc, unsigned char **bufp,
    251                        unsigned char *bufstart, void *d,
    252                        yasm_output_value_func output_value,
    253                        yasm_output_reloc_func output_reloc)
    254 {
    255     yasm_object *object = yasm_section_get_object(bc->section);
    256     yasm_dbgfmt_dwarf2 *dbgfmt_dwarf2 = (yasm_dbgfmt_dwarf2 *)object->dbgfmt;
    257     dwarf2_head *head = (dwarf2_head *)bc->contents;
    258     unsigned char *buf = *bufp;
    259     yasm_intnum *intn, *cval;
    260 
    261     if (dbgfmt_dwarf2->format == DWARF2_FORMAT_64BIT) {
    262         YASM_WRITE_8(buf, 0xff);
    263         YASM_WRITE_8(buf, 0xff);
    264         YASM_WRITE_8(buf, 0xff);
    265         YASM_WRITE_8(buf, 0xff);
    266     }
    267 
    268     /* Total length of aranges info (following this field) */
    269     cval = yasm_intnum_create_uint(dbgfmt_dwarf2->sizeof_offset);
    270     intn = yasm_calc_bc_dist(head->start_prevbc, head->end_prevbc);
    271     yasm_intnum_calc(intn, YASM_EXPR_SUB, cval);
    272     yasm_arch_intnum_tobytes(object->arch, intn, buf,
    273                              dbgfmt_dwarf2->sizeof_offset,
    274                              dbgfmt_dwarf2->sizeof_offset*8, 0, bc, 0);
    275     buf += dbgfmt_dwarf2->sizeof_offset;
    276     yasm_intnum_destroy(intn);
    277 
    278     /* DWARF version */
    279     yasm_intnum_set_uint(cval, 2);
    280     yasm_arch_intnum_tobytes(object->arch, cval, buf, 2, 16, 0, bc, 0);
    281     buf += 2;
    282 
    283     /* Pointer to another debug section */
    284     if (head->debug_ptr) {
    285         yasm_value value;
    286         yasm_value_init_sym(&value,
    287             yasm_dwarf2__bc_sym(object->symtab,
    288                                 yasm_section_bcs_first(head->debug_ptr)),
    289             dbgfmt_dwarf2->sizeof_offset*8);
    290         output_value(&value, buf, dbgfmt_dwarf2->sizeof_offset,
    291                      (unsigned long)(buf-bufstart), bc, 0, d);
    292         buf += dbgfmt_dwarf2->sizeof_offset;
    293     }
    294 
    295     /* Size of the offset portion of the address */
    296     if (head->with_address)
    297         YASM_WRITE_8(buf, dbgfmt_dwarf2->sizeof_address);
    298 
    299     /* Size of a segment descriptor.  0 = flat address space */
    300     if (head->with_segment)
    301         YASM_WRITE_8(buf, 0);
    302 
    303     *bufp = buf;
    304 
    305     yasm_intnum_destroy(cval);
    306     return 0;
    307 }
    308 
    309 static void
    310 dwarf2_section_data_destroy(void *data)
    311 {
    312     dwarf2_section_data *dsd = data;
    313     dwarf2_loc *n1, *n2;
    314 
    315     /* Delete locations */
    316     n1 = STAILQ_FIRST(&dsd->locs);
    317     while (n1) {
    318         n2 = STAILQ_NEXT(n1, link);
    319         yasm_xfree(n1);
    320         n1 = n2;
    321     }
    322 
    323     yasm_xfree(data);
    324 }
    325 
    326 static void
    327 dwarf2_section_data_print(void *data, FILE *f, int indent_level)
    328 {
    329     /* TODO */
    330 }
    331 
    332 static const yasm_directive dwarf2_directives[] = {
    333     { ".loc",   "gas",  yasm_dwarf2__dir_loc,   YASM_DIR_ARG_REQUIRED },
    334     { ".file",  "gas",  yasm_dwarf2__dir_file,  YASM_DIR_ARG_REQUIRED },
    335     { "loc",    "nasm", yasm_dwarf2__dir_loc,   YASM_DIR_ARG_REQUIRED },
    336     { "file",   "nasm", yasm_dwarf2__dir_file,  YASM_DIR_ARG_REQUIRED },
    337     { NULL, NULL, NULL, 0 }
    338 };
    339 
    340 /* Define dbgfmt structure -- see dbgfmt.h for details */
    341 yasm_dbgfmt_module yasm_dwarf2_LTX_dbgfmt = {
    342     "DWARF2 debugging format",
    343     "dwarf2",
    344     dwarf2_directives,
    345     dwarf2_dbgfmt_create,
    346     dwarf2_dbgfmt_destroy,
    347     dwarf2_dbgfmt_generate
    348 };
    349