From e410add4157311809c0b580cf2303bd07c55ea1e Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Fri, 14 Jun 2013 13:30:28 +0000 Subject: [PATCH] gas/ * dwarf2dbg.h (dwarf2_move_insn): Declare. * dwarf2dbg.c (line_subseg): Add pmove_tail. (get_line_subseg): Add create_p argument. Initialize pmove_tail. (dwarf2_gen_line_info_1): Update call accordingly. (dwarf2_move_insn): New function. * config/tc-mips.c (append_insn): Use dwarf2_move_insn. gas/testsuite/ * gas/mips/loc-swap-3.d, gas/mips/loc-swap-3.s: New test. * gas/mips/mips.exp: Run it. --- gas/ChangeLog | 9 +++++++ gas/config/tc-mips.c | 29 ++++++++++------------ gas/dwarf2dbg.c | 38 ++++++++++++++++++++++++++--- gas/dwarf2dbg.h | 2 ++ gas/testsuite/ChangeLog | 5 ++++ gas/testsuite/gas/mips/loc-swap-3.d | 16 ++++++++++++ gas/testsuite/gas/mips/loc-swap-3.s | 6 +++++ gas/testsuite/gas/mips/mips.exp | 1 + 8 files changed, 87 insertions(+), 19 deletions(-) create mode 100644 gas/testsuite/gas/mips/loc-swap-3.d create mode 100644 gas/testsuite/gas/mips/loc-swap-3.s diff --git a/gas/ChangeLog b/gas/ChangeLog index dbe82bb2e7c..fb59e46317f 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,12 @@ +2013-06-14 Richard Sandiford + + * dwarf2dbg.h (dwarf2_move_insn): Declare. + * dwarf2dbg.c (line_subseg): Add pmove_tail. + (get_line_subseg): Add create_p argument. Initialize pmove_tail. + (dwarf2_gen_line_info_1): Update call accordingly. + (dwarf2_move_insn): New function. + * config/tc-mips.c (append_insn): Use dwarf2_move_insn. + 2013-06-14 Richard Sandiford Revert: diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c index 468e40f5b2a..106f7545ee4 100644 --- a/gas/config/tc-mips.c +++ b/gas/config/tc-mips.c @@ -4373,22 +4373,19 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr, branch_disp = method == APPEND_SWAP ? insn_length (history) : 0; #ifdef OBJ_ELF - /* The value passed to dwarf2_emit_insn is the distance between - the beginning of the current instruction and the address that - should be recorded in the debug tables. This is normally the - current address. - - For MIPS16/microMIPS debug info we want to use ISA-encoded - addresses, so we use -1 for an address higher by one than the - current one. - - If the instruction produced is a branch that we will swap with - the preceding instruction, then we add the displacement by which - the branch will be moved backwards. This is more appropriate - and for MIPS16/microMIPS code also prevents a debugger from - placing a breakpoint in the middle of the branch (and corrupting - code if software breakpoints are used). */ - dwarf2_emit_insn ((HAVE_CODE_COMPRESSION ? -1 : 0) + branch_disp); + dwarf2_emit_insn (0); + /* We want MIPS16 and microMIPS debug info to use ISA-encoded addresses, + so "move" the instruction address accordingly. + + Also, it doesn't seem appropriate for the assembler to reorder .loc + entries. If this instruction is a branch that we are going to swap + with the previous instruction, the two instructions should be + treated as a unit, and the debug information for both instructions + should refer to the start of the branch sequence. Using the + current position is certainly wrong when swapping a 32-bit branch + and a 16-bit delay slot, since the current position would then be + in the middle of a branch. */ + dwarf2_move_insn ((HAVE_CODE_COMPRESSION ? 1 : 0) - branch_disp); #endif relax32 = (mips_relax_branch diff --git a/gas/dwarf2dbg.c b/gas/dwarf2dbg.c index f5623f6c5a5..6d6ee2dd198 100644 --- a/gas/dwarf2dbg.c +++ b/gas/dwarf2dbg.c @@ -169,6 +169,7 @@ struct line_subseg { subsegT subseg; struct line_entry *head; struct line_entry **ptail; + struct line_entry **pmove_tail; }; struct line_seg { @@ -238,10 +239,10 @@ generic_dwarf2_emit_offset (symbolS *symbol, unsigned int size) } #endif -/* Find or create an entry for SEG+SUBSEG in ALL_SEGS. */ +/* Find or create (if CREATE_P) an entry for SEG+SUBSEG in ALL_SEGS. */ static struct line_subseg * -get_line_subseg (segT seg, subsegT subseg) +get_line_subseg (segT seg, subsegT subseg, bfd_boolean create_p) { static segT last_seg; static subsegT last_subseg; @@ -256,6 +257,9 @@ get_line_subseg (segT seg, subsegT subseg) s = (struct line_seg *) hash_find (all_segs_hash, seg->name); if (s == NULL) { + if (!create_p) + return NULL; + s = (struct line_seg *) xmalloc (sizeof (*s)); s->next = NULL; s->seg = seg; @@ -279,6 +283,7 @@ get_line_subseg (segT seg, subsegT subseg) lss->subseg = subseg; lss->head = NULL; lss->ptail = &lss->head; + lss->pmove_tail = &lss->head; *pss = lss; found_subseg: @@ -302,7 +307,7 @@ dwarf2_gen_line_info_1 (symbolS *label, struct dwarf2_line_info *loc) e->label = label; e->loc = *loc; - lss = get_line_subseg (now_seg, now_subseg); + lss = get_line_subseg (now_seg, now_subseg, TRUE); *lss->ptail = e; lss->ptail = &e->next; } @@ -396,6 +401,33 @@ dwarf2_emit_insn (int size) dwarf2_consume_line_info (); } +/* Move all previously-emitted line entries for the current position by + DELTA bytes. This function cannot be used to move the same entries + twice. */ + +void +dwarf2_move_insn (int delta) +{ + struct line_subseg *lss; + struct line_entry *e; + valueT now; + + if (delta == 0) + return; + + lss = get_line_subseg (now_seg, now_subseg, FALSE); + if (!lss) + return; + + now = frag_now_fix (); + while ((e = *lss->pmove_tail)) + { + if (S_GET_VALUE (e->label) == now) + S_SET_VALUE (e->label, now + delta); + lss->pmove_tail = &e->next; + } +} + /* Called after the current line information has been either used with dwarf2_gen_line_info or saved with a machine instruction for later use. This resets the state of the line number information to reflect that diff --git a/gas/dwarf2dbg.h b/gas/dwarf2dbg.h index 05c7bee562b..84ef8f6d52c 100644 --- a/gas/dwarf2dbg.h +++ b/gas/dwarf2dbg.h @@ -74,6 +74,8 @@ extern void dwarf2_gen_line_info (addressT addr, struct dwarf2_line_info *l); /* Must be called for each generated instruction. */ extern void dwarf2_emit_insn (int); +void dwarf2_move_insn (int); + /* Reset the state of the line number information to reflect that it has been used. */ extern void dwarf2_consume_line_info (void); diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog index 9a11bb16422..aa57f275f40 100644 --- a/gas/testsuite/ChangeLog +++ b/gas/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2013-06-14 Richard Sandiford + + * gas/mips/loc-swap-3.d, gas/mips/loc-swap-3.s: New test. + * gas/mips/mips.exp: Run it. + 2013-06-13 Chao-ying Fu * gas/mips/micromips@virt.d: New file. diff --git a/gas/testsuite/gas/mips/loc-swap-3.d b/gas/testsuite/gas/mips/loc-swap-3.d new file mode 100644 index 00000000000..9fc5e56567d --- /dev/null +++ b/gas/testsuite/gas/mips/loc-swap-3.d @@ -0,0 +1,16 @@ +#PROG: readelf +#readelf: -wl +#name: MIPS DWARF-2 location information with branch swapping (3) +#... + Line Number Statements: +.* Set prologue_end to true +.* Extended opcode 2: set Address to 0x[01] +.* Copy +#------------------------------------------------------------------------ +# There used to be a bogus: +# Set prologue_end to true +# here +#------------------------------------------------------------------------ +.* Special opcode 6: advance Address by 0 to 0x[01] and Line by 1 to 2 +.* Advance PC by .* +.* Extended opcode 1: End of Sequence diff --git a/gas/testsuite/gas/mips/loc-swap-3.s b/gas/testsuite/gas/mips/loc-swap-3.s new file mode 100644 index 00000000000..1e4eb9a562a --- /dev/null +++ b/gas/testsuite/gas/mips/loc-swap-3.s @@ -0,0 +1,6 @@ + .file 1 "test.cpp" + + .text + .loc 1 1 0 prologue_end + .loc 1 2 0 + nop diff --git a/gas/testsuite/gas/mips/mips.exp b/gas/testsuite/gas/mips/mips.exp index a0ba48125ca..e00b3f2e02c 100644 --- a/gas/testsuite/gas/mips/mips.exp +++ b/gas/testsuite/gas/mips/mips.exp @@ -999,6 +999,7 @@ if { [istarget mips*-*-vxworks*] } { run_dump_test_arches "loc-swap-dis" \ [mips_arch_list_all] run_dump_test_arches "loc-swap-2" [mips_arch_list_all] + run_dump_test_arches "loc-swap-3" [mips_arch_list_all] } if $has_newabi { -- 2.30.2