static void out_debug_aranges (segT aranges_seg, segT info_seg) { unsigned int addr_size = sizeof_address; struct line_seg *s; expressionS exp; symbolS *aranges_end; char *p; int sizeof_offset; sizeof_offset = out_header (aranges_seg, &exp); aranges_end = exp.X_add_symbol; /* Version. */ out_two (DWARF2_VERSION); /* Offset to .debug_info. */ TC_DWARF2_EMIT_OFFSET (section_symbol (info_seg), sizeof_offset); /* Size of an address (offset portion). */ out_byte (addr_size); /* Size of a segment descriptor. */ out_byte (0); /* Align the header. */ frag_align (ffs (2 * addr_size) - 1, 0, 0); for (s = all_segs; s; s = s->next) { fragS *frag; symbolS *beg, *end; frag = first_frag_for_seg (s->seg); beg = symbol_temp_new (s->seg, 0, frag); s->text_start = beg; frag = last_frag_for_seg (s->seg); end = symbol_temp_new (s->seg, get_frag_fix (frag, s->seg), frag); s->text_end = end; exp.X_op = O_symbol; exp.X_add_symbol = beg; exp.X_add_number = 0; emit_expr (&exp, addr_size); exp.X_op = O_subtract; exp.X_add_symbol = end; exp.X_op_symbol = beg; exp.X_add_number = 0; emit_expr (&exp, addr_size); } p = frag_more (2 * addr_size); md_number_to_chars (p, 0, addr_size); md_number_to_chars (p + addr_size, 0, addr_size); symbol_set_value_now (aranges_end); }
void dwarf2_gen_line_info (addressT ofs, struct dwarf2_line_info *loc) { static unsigned int line = -1; static unsigned int filenum = -1; symbolS *sym; /* Early out for as-yet incomplete location information. */ if (loc->filenum == 0 || loc->line == 0) return; /* Don't emit sequences of line symbols for the same line when the symbols apply to assembler code. It is necessary to emit duplicate line symbols when a compiler asks for them, because GDB uses them to determine the end of the prologue. */ if (debug_type == DEBUG_DWARF2 && line == loc->line && filenum == loc->filenum) return; line = loc->line; filenum = loc->filenum; sym = symbol_temp_new (now_seg, ofs, frag_now); dwarf2_gen_line_info_1 (sym, loc); }
static void out_debug_ranges (segT ranges_seg) { unsigned int addr_size = sizeof_address; struct line_seg *s; expressionS exp; unsigned int i; subseg_set (ranges_seg, 0); /* Base Address Entry. */ for (i = 0; i < addr_size; i++) out_byte (0xff); for (i = 0; i < addr_size; i++) out_byte (0); /* Range List Entry. */ for (s = all_segs; s; s = s->next) { fragS *frag; symbolS *beg, *end; frag = first_frag_for_seg (s->seg); beg = symbol_temp_new (s->seg, 0, frag); s->text_start = beg; frag = last_frag_for_seg (s->seg); end = symbol_temp_new (s->seg, get_frag_fix (frag, s->seg), frag); s->text_end = end; exp.X_op = O_symbol; exp.X_add_symbol = beg; exp.X_add_number = 0; emit_expr (&exp, addr_size); exp.X_op = O_symbol; exp.X_add_symbol = end; exp.X_add_number = 0; emit_expr (&exp, addr_size); } /* End of Range Entry. */ for (i = 0; i < addr_size; i++) out_byte (0); for (i = 0; i < addr_size; i++) out_byte (0); }
/* * section_symbol() creates and stores (if needed) a symbol for the start of * the section. This is used by code in dwarf2dbg.c . */ symbolS * section_symbol( frchainS *frcP) { if(frcP->section_symbol == NULL){ frcP->section_symbol = symbol_temp_new(frcP->frch_nsect, 0, frcP->frch_root); } return(frcP->section_symbol); }
static void relax_inc_line_addr (int line_delta, segT seg, fragS *to_frag, addressT to_ofs, fragS *from_frag, addressT from_ofs) { symbolS *to_sym, *from_sym; expressionS expr; int max_chars; to_sym = symbol_temp_new (seg, to_ofs, to_frag); from_sym = symbol_temp_new (seg, from_ofs, from_frag); expr.X_op = O_subtract; expr.X_add_symbol = to_sym; expr.X_op_symbol = from_sym; expr.X_add_number = 0; /* The maximum size of the frag is the line delta with a maximum sized address delta. */ max_chars = size_inc_line_addr (line_delta, -DWARF2_LINE_MIN_INSN_LENGTH); frag_var (rs_dwarf2dbg, max_chars, max_chars, 1, make_expr_symbol (&expr), line_delta, NULL); }
static void out_set_addr (segT seg, fragS *frag, addressT ofs) { expressionS expr; symbolS *sym; sym = symbol_temp_new (seg, ofs, frag); out_opcode (DW_LNS_extended_op); out_uleb128 (sizeof_address + 1); out_opcode (DW_LNE_set_address); expr.X_op = O_symbol; expr.X_add_symbol = sym; expr.X_add_number = 0; emit_expr (&expr, sizeof_address); }
void dwarf2_gen_line_info (addressT ofs, struct dwarf2_line_info *loc) { static unsigned int line = -1; static unsigned int filenum = -1; symbolS *sym; /* Early out for as-yet incomplete location information. */ if (loc->filenum == 0 || loc->line == 0) return; /* Don't emit sequences of line symbols for the same line when the symbols apply to assembler code. It is necessary to emit duplicate line symbols when a compiler asks for them, because GDB uses them to determine the end of the prologue. */ if (debug_type == DEBUG_DWARF2 && line == loc->line && filenum == loc->filenum) return; line = loc->line; filenum = loc->filenum; if (linkrelax) { char name[120]; /* Use a non-fake name for the line number location, so that it can be referred to by relocations. */ sprintf (name, ".Loc.%u.%u", line, filenum); sym = symbol_new (name, now_seg, ofs, frag_now); } else sym = symbol_temp_new (now_seg, ofs, frag_now); dwarf2_gen_line_info_1 (sym, loc); }
static void process_entries (segT seg, struct line_entry *e) { unsigned filenum = 1; unsigned line = 1; unsigned column = 0; unsigned isa = 0; unsigned flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; fragS *last_frag = NULL, *frag; addressT last_frag_ofs = 0, frag_ofs; symbolS *last_lab = NULL, *lab; struct line_entry *next; do { int line_delta; if (filenum != e->loc.filenum) { filenum = e->loc.filenum; out_opcode (DW_LNS_set_file); out_uleb128 (filenum); } if (column != e->loc.column) { column = e->loc.column; out_opcode (DW_LNS_set_column); out_uleb128 (column); } if (e->loc.discriminator != 0) { out_opcode (DW_LNS_extended_op); out_leb128 (1 + sizeof_leb128 (e->loc.discriminator, 0)); out_opcode (DW_LNE_set_discriminator); out_uleb128 (e->loc.discriminator); } if (isa != e->loc.isa) { isa = e->loc.isa; out_opcode (DW_LNS_set_isa); out_uleb128 (isa); } if ((e->loc.flags ^ flags) & DWARF2_FLAG_IS_STMT) { flags = e->loc.flags; out_opcode (DW_LNS_negate_stmt); } if (e->loc.flags & DWARF2_FLAG_BASIC_BLOCK) out_opcode (DW_LNS_set_basic_block); if (e->loc.flags & DWARF2_FLAG_PROLOGUE_END) out_opcode (DW_LNS_set_prologue_end); if (e->loc.flags & DWARF2_FLAG_EPILOGUE_BEGIN) out_opcode (DW_LNS_set_epilogue_begin); /* Don't try to optimize away redundant entries; gdb wants two entries for a function where the code starts on the same line as the {, and there's no way to identify that case here. Trust gcc to optimize appropriately. */ line_delta = e->loc.line - line; lab = e->label; frag = symbol_get_frag (lab); frag_ofs = S_GET_VALUE (lab); if (last_frag == NULL) { out_set_addr (lab); out_inc_line_addr (line_delta, 0); } else if (frag == last_frag && ! DWARF2_USE_FIXED_ADVANCE_PC) out_inc_line_addr (line_delta, frag_ofs - last_frag_ofs); else relax_inc_line_addr (line_delta, lab, last_lab); line = e->loc.line; last_lab = lab; last_frag = frag; last_frag_ofs = frag_ofs; next = e->next; free (e); e = next; } while (e); /* Emit a DW_LNE_end_sequence for the end of the section. */ frag = last_frag_for_seg (seg); frag_ofs = get_frag_fix (frag, seg); if (frag == last_frag && ! DWARF2_USE_FIXED_ADVANCE_PC) out_inc_line_addr (INT_MAX, frag_ofs - last_frag_ofs); else { lab = symbol_temp_new (seg, frag_ofs, frag); relax_inc_line_addr (INT_MAX, lab, last_lab); } }
static void out_debug_aranges (segT aranges_seg, segT info_seg) { unsigned int addr_size = sizeof_address; addressT size, skip; struct line_seg *s; expressionS expr; char *p; size = 4 + 2 + 4 + 1 + 1; skip = 2 * addr_size - (size & (2 * addr_size - 1)); if (skip == 2 * addr_size) skip = 0; size += skip; for (s = all_segs; s; s = s->next) size += 2 * addr_size; size += 2 * addr_size; subseg_set (aranges_seg, 0); /* Length of the compilation unit. */ out_four (size - 4); /* Version. */ out_two (2); /* Offset to .debug_info. */ /* ??? sizeof_offset */ TC_DWARF2_EMIT_OFFSET (section_symbol (info_seg), 4); /* Size of an address (offset portion). */ out_byte (addr_size); /* Size of a segment descriptor. */ out_byte (0); /* Align the header. */ if (skip) frag_align (ffs (2 * addr_size) - 1, 0, 0); for (s = all_segs; s; s = s->next) { fragS *frag; symbolS *beg, *end; frag = first_frag_for_seg (s->seg); beg = symbol_temp_new (s->seg, 0, frag); s->text_start = beg; frag = last_frag_for_seg (s->seg); end = symbol_temp_new (s->seg, get_frag_fix (frag), frag); s->text_end = end; expr.X_op = O_symbol; expr.X_add_symbol = beg; expr.X_add_number = 0; emit_expr (&expr, addr_size); expr.X_op = O_subtract; expr.X_add_symbol = end; expr.X_op_symbol = beg; expr.X_add_number = 0; emit_expr (&expr, addr_size); } p = frag_more (2 * addr_size); md_number_to_chars (p, 0, addr_size); md_number_to_chars (p + addr_size, 0, addr_size); }