This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[PATCH] Fix .cfi_* directive skip over >= 64KB (PR gas/10255)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: binutils at sources dot redhat dot com
- Date: Tue, 9 Jun 2009 14:28:34 +0200
- Subject: [PATCH] Fix .cfi_* directive skip over >= 64KB (PR gas/10255)
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
Hi!
When .cfi_* directives need to skip from one fragment to another one and
that skip in the end turns to be >= 64KB, the generated .eh_frame section
is incorrect. The problem is that we add the needed 1 byte fragment
before rs_cfa fragment, but don't initialize it, so it often remains
at DW_CFA_nop (or could be any other opcode). Later on when
eh_frame_convert_frag is called, if the skip is small, the previous
fragment's byte is changed into DW_CFA_advance_loc | distance,
DW_CFA_advance_loc1 or DW_CFA_advance_loc2. But if it is >= 65536,
ehopt.c assumes (IMHO correctly) that the byte before it is
DW_CFA_advance_loc4 and doesn't change it, so we end up with a random opcode
(usually DW_CFA_nop) followed by the 4 byte skip value (which is
interpreted as random, often invalid, opcodes).
Ok for trunk?
2009-06-09 Jakub Jelinek <jakub@redhat.com>
PR gas/10255
* dw2gencfi.c (output_cfi_insn): Initialize fragment before rs_cfa
to DW_CFA_advance_loc4.
* gas/cfi/cfi-common-7.d: New test.
* gas/cfi/cfi-common-7.s: New.
* gas/cfi/cfi.exp: Add cfi-common-7 test.
--- gas/dw2gencfi.c.jj 2009-01-27 17:50:43.000000000 +0100
+++ gas/dw2gencfi.c 2009-06-09 13:51:19.000000000 +0200
@@ -1,5 +1,6 @@
/* dw2gencfi.c - Support for generating Dwarf2 CFI information.
- Copyright 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+ Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009
+ Free Software Foundation, Inc.
Contributed by Michal Ludvig <mludvig@suse.cz>
This file is part of GAS, the GNU Assembler.
@@ -1001,7 +1002,7 @@ output_cfi_insn (struct cfi_insn_data *i
is already allocated to the frag. This comes from the way
that it scans the .eh_frame section looking first for the
.byte DW_CFA_advance_loc4. */
- frag_more (1);
+ *frag_more (1) = DW_CFA_advance_loc4;
frag_var (rs_cfa, 4, 0, DWARF2_LINE_MIN_INSN_LENGTH << 3,
make_expr_symbol (&exp), frag_now_fix () - 1,
--- gas/testsuite/gas/cfi/cfi.exp.jj 2008-09-25 20:39:42.000000000 +0200
+++ gas/testsuite/gas/cfi/cfi.exp 2009-06-09 14:07:08.000000000 +0200
@@ -89,6 +89,7 @@ if { ![istarget "hppa64*-*"] } then {
run_dump_test "cfi-common-3"
run_dump_test "cfi-common-4"
run_dump_test "cfi-common-5"
+ run_dump_test "cfi-common-7"
}
# MIPS doesn't support PC relative cfi directives.
--- gas/testsuite/gas/cfi/cfi-common-7.d.jj 2009-06-09 13:58:25.000000000 +0200
+++ gas/testsuite/gas/cfi/cfi-common-7.d 2009-06-09 14:04:33.000000000 +0200
@@ -0,0 +1,22 @@
+#readelf: -wf
+#name: CFI common 7
+Contents of the .eh_frame section:
+
+00000000 00000010 00000000 CIE
+ Version: 1
+ Augmentation: "zR"
+ Code alignment factor: .*
+ Data alignment factor: .*
+ Return address column: .*
+ Augmentation data: [01]b
+
+ DW_CFA_nop
+ DW_CFA_nop
+ DW_CFA_nop
+
+00000014 000000(1c|20) 00000018 FDE cie=00000000 pc=.*
+ DW_CFA_advance_loc: 16 to .*
+ DW_CFA_def_cfa: r0( \([er]ax\)|) ofs 16
+ DW_CFA_advance_loc4: 75031 to .*
+ DW_CFA_def_cfa: r0( \([er]ax\)|) ofs 64
+#...
--- gas/testsuite/gas/cfi/cfi-common-7.s.jj 2009-06-09 13:57:19.000000000 +0200
+++ gas/testsuite/gas/cfi/cfi-common-7.s 2009-06-09 13:59:34.000000000 +0200
@@ -0,0 +1,6 @@
+ .cfi_startproc simple
+ .skip 16
+ .cfi_def_cfa 0, 16
+ .skip 75031
+ .cfi_def_cfa 0, 64
+ .cfi_endproc
Jakub