[RFA, ARM] Fix line number data for PIC register setup code
Richard Earnshaw
rearnsha@arm.com
Mon Dec 20 21:15:00 GMT 2010
On Mon, 2010-12-20 at 19:13 +0100, Ulrich Weigand wrote:
> Hello,
>
> we've been seeing problems with GDB being unable to correctly identify
> the first line of a function that are caused by an issue with ARM PIC
> code generation.
>
> As a small example, the following test case:
>
> int foo (char* s);
> extern char hello[];
>
> void test (int x)
> {
> int y = x + 4;
> foo(hello);
> }
>
> compiles to a function with the following prologue (using -fPIC):
>
> .loc 1 6 0
> .cfi_startproc
> @ args = 0, pretend = 0, frame = 16
> @ frame_needed = 1, uses_anonymous_args = 0
> stmfd sp!, {fp, lr}
> .LCFI0:
> .cfi_def_cfa_offset 8
> .cfi_offset 14, -4
> .cfi_offset 11, -8
> add fp, sp, #4
> .LCFI1:
> .cfi_def_cfa 11, 4
> sub sp, sp, #16
> .loc 1 8 0
> ldr r3, .L2
> .LPIC0:
> add r3, pc, r3
> .loc 1 6 0
> str r0, [fp, #-16]
>
> Note how --while the majority of the prologue code is correctly
> identified at line 6-- the two instructions used to set up the
> PIC register are identified as belonging to line 8. This causes
> GDB to set a breakpoint at line 8, instead of line 7, as the
> first "real" line of the function.
>
> The reason for this is code in require_pic_register, which constructs
> the insns corresponding to those two lines. The insns are injected into
> the function prologue via
> insert_insn_on_edge (seq, single_succ_edge (ENTRY_BLOCK_PTR));
>
> However, these days each instruction carries "locator" information
> to link back to the source line it originates from. Since the
> require_pic_register does not explicitly set the locator data,
> by default this information points back to whatever line was
> "current" when require_pic_register was called, which will usually
> be the first source line that uses some construct that requires
> the PIC register to be initialized.
>
> It seems to me the proper fix for this is to reset the locator
> information for those instructions generated in require_pic_register
> to "prologue_locator", just as is done for all other prologue code
> in thread_prologue_and_epilogue_insns.
>
> The following patch implements this change, leading to this
> assembler code:
>
> .loc 1 6 0
> .cfi_startproc
> @ args = 0, pretend = 0, frame = 16
> @ frame_needed = 1, uses_anonymous_args = 0
> stmfd sp!, {fp, lr}
> .LCFI0:
> .cfi_def_cfa_offset 8
> .cfi_offset 14, -4
> .cfi_offset 11, -8
> add fp, sp, #4
> .LCFI1:
> .cfi_def_cfa 11, 4
> sub sp, sp, #16
> ldr r3, .L2
> .LPIC0:
> add r3, pc, r3
> str r0, [fp, #-16]
>
> which makes the GDB problems go away.
>
> Tested on armv7l-linux-gnueabi with no regressions.
> OK for mainline?
>
> Bye,
> Ulrich
>
>
> ChangeLog:
>
> * config/arm/arm.c (require_pic_register): Set INSN_LOCATOR for all
> instructions injected into the prologue to prologue_locator.
>
> Index: gcc/config/arm/arm.c
> ===================================================================
> --- gcc/config/arm/arm.c (revision 167799)
> +++ gcc/config/arm/arm.c (working copy)
> @@ -5116,7 +5116,7 @@
> }
> else
> {
> - rtx seq;
> + rtx seq, insn;
>
> if (!cfun->machine->pic_reg)
> cfun->machine->pic_reg = gen_reg_rtx (Pmode);
> @@ -5133,6 +5133,11 @@
>
> seq = get_insns ();
> end_sequence ();
> +
> + for (insn = seq; insn; insn = NEXT_INSN (insn))
> + if (INSN_P (insn))
> + INSN_LOCATOR (insn) = prologue_locator;
> +
Hmm, what if get_insns() doesn't return an INSN_P(), which is presumably
what the test in the 'if' clause is for? Won't it then abort in
NEXT_INSN()?
I think the for loop should be controlled by (insn && INSN_P (insn)) to
guard against that case.
R.
More information about the Gcc-patches
mailing list