dwarf2dbg.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 1,313 行 · 第 1/3 页
C
1,313 行
out_byte (byte) int byte;{ FRAG_APPEND_1_CHAR (byte);}/* Emit a statement program opcode into the current segment. */static inline voidout_opcode (opc) int opc;{ out_byte (opc);}/* Emit a two-byte word into the current segment. */static inline voidout_two (data) int data;{ md_number_to_chars (frag_more (2), data, 2);}/* Emit a four byte word into the current segment. */static inline voidout_four (data) int data;{ md_number_to_chars (frag_more (4), data, 4);}/* Emit an unsigned "little-endian base 128" number. */static voidout_uleb128 (value) addressT value;{ output_leb128 (frag_more (sizeof_leb128 (value, 0)), value, 0);}/* Emit a tuple for .debug_abbrev. */static inline voidout_abbrev (name, form) int name, form;{ out_uleb128 (name); out_uleb128 (form);}/* Create a new fake symbol whose value is the current position. */static symbolS *symbol_new_now (){ return symbol_new (fake_label_name, now_seg, frag_now_fix (), frag_now);}/* Set the value of SYM to the current position in the current segment. */static voidset_symbol_value_now (sym) symbolS *sym;{ S_SET_SEGMENT (sym, now_seg); S_SET_VALUE (sym, frag_now_fix ()); symbol_set_frag (sym, frag_now);}/* Get the size of a fragment. */static offsetTget_frag_fix (frag) fragS *frag;{ frchainS *fr; if (frag->fr_next) return frag->fr_fix; /* If a fragment is the last in the chain, special measures must be taken to find its size before relaxation, since it may be pending on some subsegment chain. */ for (fr = frchain_root; fr; fr = fr->frch_next) if (fr->frch_last == frag) { return ((char *) obstack_next_free (&fr->frch_obstack) - frag->fr_literal); } abort ();}/* Set an absolute address (may result in a relocation entry). */static voidout_set_addr (seg, frag, ofs) segT seg; fragS *frag; addressT ofs;{ expressionS expr; symbolS *sym; sym = symbol_new (fake_label_name, 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);}/* Encode a pair of line and address skips as efficiently as possible. Note that the line skip is signed, whereas the address skip is unsigned. The following two routines *must* be kept in sync. This is enforced by making emit_inc_line_addr abort if we do not emit exactly the expected number of bytes. */static intsize_inc_line_addr (line_delta, addr_delta) int line_delta; addressT addr_delta;{ unsigned int tmp, opcode; int len = 0; /* Scale the address delta by the minimum instruction length. */#if DWARF2_LINE_MIN_INSN_LENGTH > 1 assert (addr_delta % DWARF2_LINE_MIN_INSN_LENGTH == 0); addr_delta /= DWARF2_LINE_MIN_INSN_LENGTH;#endif /* INT_MAX is a signal that this is actually a DW_LNE_end_sequence. We cannot use special opcodes here, since we want the end_sequence to emit the matrix entry. */ if (line_delta == INT_MAX) { if (addr_delta == MAX_SPECIAL_ADDR_DELTA) len = 1; else len = 1 + sizeof_leb128 (addr_delta, 0); return len + 3; } /* Bias the line delta by the base. */ tmp = line_delta - DWARF2_LINE_BASE; /* If the line increment is out of range of a special opcode, we must encode it with DW_LNS_advance_line. */ if (tmp >= DWARF2_LINE_RANGE) { len = 1 + sizeof_leb128 (line_delta, 1); line_delta = 0; tmp = 0 - DWARF2_LINE_BASE; } /* Bias the opcode by the special opcode base. */ tmp += DWARF2_LINE_OPCODE_BASE; /* Avoid overflow when addr_delta is large. */ if (addr_delta < 256 + MAX_SPECIAL_ADDR_DELTA) { /* Try using a special opcode. */ opcode = tmp + addr_delta * DWARF2_LINE_RANGE; if (opcode <= 255) return len + 1; /* Try using DW_LNS_const_add_pc followed by special op. */ opcode = tmp + (addr_delta - MAX_SPECIAL_ADDR_DELTA) * DWARF2_LINE_RANGE; if (opcode <= 255) return len + 2; } /* Otherwise use DW_LNS_advance_pc. */ len += 1 + sizeof_leb128 (addr_delta, 0); /* DW_LNS_copy or special opcode. */ len += 1; return len;}static voidemit_inc_line_addr (line_delta, addr_delta, p, len) int line_delta; addressT addr_delta; char *p; int len;{ unsigned int tmp, opcode; int need_copy = 0; char *end = p + len;#if DWARF2_LINE_MIN_INSN_LENGTH > 1 /* Scale the address delta by the minimum instruction length. */ assert (addr_delta % DWARF2_LINE_MIN_INSN_LENGTH == 0); addr_delta /= DWARF2_LINE_MIN_INSN_LENGTH;#endif /* INT_MAX is a signal that this is actually a DW_LNE_end_sequence. We cannot use special opcodes here, since we want the end_sequence to emit the matrix entry. */ if (line_delta == INT_MAX) { if (addr_delta == MAX_SPECIAL_ADDR_DELTA) *p++ = DW_LNS_const_add_pc; else { *p++ = DW_LNS_advance_pc; p += output_leb128 (p, addr_delta, 0); } *p++ = DW_LNS_extended_op; *p++ = 1; *p++ = DW_LNE_end_sequence; goto done; } /* Bias the line delta by the base. */ tmp = line_delta - DWARF2_LINE_BASE; /* If the line increment is out of range of a special opcode, we must encode it with DW_LNS_advance_line. */ if (tmp >= DWARF2_LINE_RANGE) { *p++ = DW_LNS_advance_line; p += output_leb128 (p, line_delta, 1); /* Prettier, I think, to use DW_LNS_copy instead of a "line +0, addr +0" special opcode. */ if (addr_delta == 0) { *p++ = DW_LNS_copy; goto done; } line_delta = 0; tmp = 0 - DWARF2_LINE_BASE; need_copy = 1; } /* Bias the opcode by the special opcode base. */ tmp += DWARF2_LINE_OPCODE_BASE; /* Avoid overflow when addr_delta is large. */ if (addr_delta < 256 + MAX_SPECIAL_ADDR_DELTA) { /* Try using a special opcode. */ opcode = tmp + addr_delta * DWARF2_LINE_RANGE; if (opcode <= 255) { *p++ = opcode; goto done; } /* Try using DW_LNS_const_add_pc followed by special op. */ opcode = tmp + (addr_delta - MAX_SPECIAL_ADDR_DELTA) * DWARF2_LINE_RANGE; if (opcode <= 255) { *p++ = DW_LNS_const_add_pc; *p++ = opcode; goto done; } } /* Otherwise use DW_LNS_advance_pc. */ *p++ = DW_LNS_advance_pc; p += output_leb128 (p, addr_delta, 0); if (need_copy) *p++ = DW_LNS_copy; else *p++ = tmp; done: assert (p == end);}/* Handy routine to combine calls to the above two routines. */static voidout_inc_line_addr (line_delta, addr_delta) int line_delta; addressT addr_delta;{ int len = size_inc_line_addr (line_delta, addr_delta); emit_inc_line_addr (line_delta, addr_delta, frag_more (len), len);}/* Generate a variant frag that we can use to relax address/line increments between fragments of the target segment. */static voidrelax_inc_line_addr (line_delta, seg, to_frag, to_ofs, from_frag, from_ofs) int line_delta; segT seg; fragS *to_frag, *from_frag; addressT to_ofs, from_ofs;{ symbolS *to_sym, *from_sym; expressionS expr; int max_chars; to_sym = symbol_new (fake_label_name, seg, to_ofs, to_frag); from_sym = symbol_new (fake_label_name, 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);}/* The function estimates the size of a rs_dwarf2dbg variant frag based on the current values of the symbols. It is called before the relaxation loop. We set fr_subtype to the expected length. */intdwarf2dbg_estimate_size_before_relax (frag) fragS *frag;{ offsetT addr_delta; int size; addr_delta = resolve_symbol_value (frag->fr_symbol, 0); size = size_inc_line_addr (frag->fr_offset, addr_delta); frag->fr_subtype = size; return size;}/* This function relaxes a rs_dwarf2dbg variant frag based on the current values of the symbols. fr_subtype is the current length of the frag. This returns the change in frag length. */intdwarf2dbg_relax_frag (frag) fragS *frag;{ int old_size, new_size; old_size = frag->fr_subtype; new_size = dwarf2dbg_estimate_size_before_relax (frag); return new_size - old_size;}/* This function converts a rs_dwarf2dbg variant frag into a normal fill frag. This is called after all relaxation has been done. fr_subtype will be the desired length of the frag. */voiddwarf2dbg_convert_frag (frag) fragS *frag;{ offsetT addr_diff; addr_diff = resolve_symbol_value (frag->fr_symbol, 1); /* fr_var carries the max_chars that we created the fragment with. fr_subtype carries the current expected length. We must, of course, have allocated enough memory earlier. */ assert (frag->fr_var >= (int) frag->fr_subtype); emit_inc_line_addr (frag->fr_offset, addr_diff, frag->fr_literal + frag->fr_fix, frag->fr_subtype); frag->fr_fix += frag->fr_subtype; frag->fr_type = rs_fill; frag->fr_var = 0; frag->fr_offset = 0;}/* Generate .debug_line content for the chain of line number entries beginning at E, for segment SEG. */static voidprocess_entries (seg, e) segT seg; struct line_entry *e;{ unsigned filenum = 1; unsigned line = 1; unsigned column = 0; unsigned flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_BEGIN_STMT : 0; fragS *frag = NULL; fragS *last_frag; addressT frag_ofs = 0; addressT last_frag_ofs; struct line_entry *next; while (e) { int changed = 0; if (filenum != e->loc.filenum) { filenum = e->loc.filenum; out_opcode (DW_LNS_set_file); out_uleb128 (filenum); changed = 1; } if (column != e->loc.column) { column = e->loc.column; out_opcode (DW_LNS_set_column); out_uleb128 (column); changed = 1; } if ((e->loc.flags ^ flags) & DWARF2_FLAG_BEGIN_STMT) { flags = e->loc.flags; out_opcode (DW_LNS_negate_stmt); changed = 1; } if (e->loc.flags & DWARF2_FLAG_BEGIN_BLOCK) { out_opcode (DW_LNS_set_basic_block); changed = 1; } /* Don't try to optimize away redundant entries; gdb wants two
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?