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