This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Patch ping: Scale DW_CFA_advance_loc[124] output values
Hi!
Ping, this is quite urgent bug that GCC needs to check for in
its configury and apply workarounds.
Below is the final version of both patches (only the (offsetT)
cast has been added) together.
2008-11-28 Jakub Jelinek <jakub@redhat.com>
* Makefile.am (ehopt.o): Add struc-symbol.h.
* Makefile.in: Regenerated.
* ehopt.c: Include struc-symbol.h.
(check_eh_frame): For very small O_constant DW_CFA_advance_loc4
create correct DW_CFA_advance_loc. Handle O_subtract only
for code alignment factor 1, otherwise handle O_divide or
O_right_shift of O_subtract and O_constant.
(eh_frame_estimate_size_before_relax): Always divide by ca.
(eh_frame_convert_frag): Likewise.
2008-11-28 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
* dw2gencfi.c (output_cfi_insn): Scale DW_CFA_advance_loc1,
DW_CFA_advance_loc2 and DW_CFA_advance_loc4 outputs.
--- gas/Makefile.am.jj 2008-11-19 15:50:40.000000000 +0100
+++ gas/Makefile.am 2008-11-19 16:57:49.000000000 +0100
@@ -2159,7 +2159,8 @@ dwarf2dbg.o: dwarf2dbg.c $(INCDIR)/safe-
dw2gencfi.o: dw2gencfi.c dw2gencfi.h $(INCDIR)/elf/dwarf2.h \
subsegs.h $(INCDIR)/obstack.h
ecoff.o: ecoff.c ecoff.h
-ehopt.o: ehopt.c subsegs.h $(INCDIR)/obstack.h $(INCDIR)/elf/dwarf2.h
+ehopt.o: ehopt.c subsegs.h $(INCDIR)/obstack.h $(INCDIR)/elf/dwarf2.h \
+ struc-symbol.h
expr.o: expr.c $(INCDIR)/safe-ctype.h $(INCDIR)/obstack.h
flonum-copy.o: flonum-copy.c
flonum-konst.o: flonum-konst.c
--- gas/Makefile.in.jj 2008-11-19 15:50:40.000000000 +0100
+++ gas/Makefile.in 2008-11-19 16:58:03.000000000 +0100
@@ -3015,7 +3015,8 @@ dwarf2dbg.o: dwarf2dbg.c $(INCDIR)/safe-
dw2gencfi.o: dw2gencfi.c dw2gencfi.h $(INCDIR)/elf/dwarf2.h \
subsegs.h $(INCDIR)/obstack.h
ecoff.o: ecoff.c ecoff.h
-ehopt.o: ehopt.c subsegs.h $(INCDIR)/obstack.h $(INCDIR)/elf/dwarf2.h
+ehopt.o: ehopt.c subsegs.h $(INCDIR)/obstack.h $(INCDIR)/elf/dwarf2.h \
+ struc-symbol.h
expr.o: expr.c $(INCDIR)/safe-ctype.h $(INCDIR)/obstack.h
flonum-copy.o: flonum-copy.c
flonum-konst.o: flonum-konst.c
--- gas/ehopt.c.jj 2007-12-28 09:31:47.000000000 +0100
+++ gas/ehopt.c 2008-11-19 17:03:48.000000000 +0100
@@ -1,5 +1,6 @@
/* ehopt.c--optimize gcc exception frame information.
- Copyright 1998, 2000, 2001, 2003, 2005, 2007 Free Software Foundation, Inc.
+ Copyright 1998, 2000, 2001, 2003, 2005, 2007, 2008
+ Free Software Foundation, Inc.
Written by Ian Lance Taylor <ian@cygnus.com>.
This file is part of GAS, the GNU Assembler.
@@ -21,6 +22,7 @@
#include "as.h"
#include "subsegs.h"
+#include "struc-symbol.h"
/* We include this ELF file, even though we may not be assembling for
ELF, since the exception frame information is always in a format
@@ -398,13 +400,10 @@ check_eh_frame (expressionS *exp, unsign
subtracted were in the same frag and the expression was
reduced to a constant. We can do the optimization entirely
in this function. */
- if (d->cie_info.code_alignment > 0
- && exp->X_add_number % d->cie_info.code_alignment == 0
- && exp->X_add_number / d->cie_info.code_alignment < 0x40)
+ if (exp->X_add_number < 0x40)
{
d->loc4_frag->fr_literal[d->loc4_fix]
- = DW_CFA_advance_loc
- | (exp->X_add_number / d->cie_info.code_alignment);
+ = DW_CFA_advance_loc | exp->X_add_number;
/* No more bytes needed. */
return 1;
}
@@ -419,23 +418,39 @@ check_eh_frame (expressionS *exp, unsign
*pnbytes = 2;
}
}
- else if (exp->X_op == O_subtract)
+ else if (exp->X_op == O_subtract && d->cie_info.code_alignment == 1)
{
/* This is a case we can optimize. The expression was not
reduced, so we can not finish the optimization until the end
of the assembly. We set up a variant frag which we handle
later. */
- int fr_subtype;
-
- if (d->cie_info.code_alignment > 0)
- fr_subtype = d->cie_info.code_alignment << 3;
- else
- fr_subtype = 0;
-
- frag_var (rs_cfa, 4, 0, fr_subtype, make_expr_symbol (exp),
+ frag_var (rs_cfa, 4, 0, 1 << 3, make_expr_symbol (exp),
d->loc4_fix, (char *) d->loc4_frag);
return 1;
}
+ else if ((exp->X_op == O_divide
+ || exp->X_op == O_right_shift)
+ && d->cie_info.code_alignment > 1)
+ {
+ if (exp->X_add_symbol->bsym
+ && exp->X_op_symbol->bsym
+ && exp->X_add_symbol->sy_value.X_op == O_subtract
+ && exp->X_op_symbol->sy_value.X_op == O_constant
+ && ((exp->X_op == O_divide
+ ? exp->X_op_symbol->sy_value.X_add_number
+ : (offsetT) 1 << exp->X_op_symbol->sy_value.X_add_number)
+ == (offsetT) d->cie_info.code_alignment))
+ {
+ /* This is a case we can optimize as well. The expression was
+ not reduced, so we can not finish the optimization until the
+ end of the assembly. We set up a variant frag which we
+ handle later. */
+ frag_var (rs_cfa, 4, 0, d->cie_info.code_alignment << 3,
+ make_expr_symbol (&exp->X_add_symbol->sy_value),
+ d->loc4_fix, (char *) d->loc4_frag);
+ return 1;
+ }
+ }
break;
case state_error:
@@ -459,7 +474,9 @@ eh_frame_estimate_size_before_relax (fra
diff = resolve_symbol_value (frag->fr_symbol);
- if (ca > 0 && diff % ca == 0 && diff / ca < 0x40)
+ assert (ca > 0);
+ diff /= ca;
+ if (diff < 0x40)
ret = 0;
else if (diff < 0x100)
ret = 1;
@@ -496,21 +513,21 @@ eh_frame_convert_frag (fragS *frag)
{
offsetT diff;
fragS *loc4_frag;
- int loc4_fix;
+ int loc4_fix, ca;
loc4_frag = (fragS *) frag->fr_opcode;
loc4_fix = (int) frag->fr_offset;
diff = resolve_symbol_value (frag->fr_symbol);
+ ca = frag->fr_subtype >> 3;
+ assert (ca > 0);
+ diff /= ca;
switch (frag->fr_subtype & 7)
{
case 0:
- {
- int ca = frag->fr_subtype >> 3;
- assert (ca > 0 && diff % ca == 0 && diff / ca < 0x40);
- loc4_frag->fr_literal[loc4_fix] = DW_CFA_advance_loc | (diff / ca);
- }
+ assert (diff < 0x40);
+ loc4_frag->fr_literal[loc4_fix] = DW_CFA_advance_loc | diff;
break;
case 1:
--- gas/dw2gencfi.c.jj 2008-11-19 15:50:40.000000000 +0100
+++ gas/dw2gencfi.c 2008-11-19 16:01:28.000000000 +0100
@@ -1,5 +1,5 @@
/* dw2gencfi.c - Support for generating Dwarf2 CFI information.
- Copyright 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+ Copyright 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
Contributed by Michal Ludvig <mludvig@suse.cz>
This file is part of GAS, the GNU Assembler.
@@ -972,20 +972,20 @@ output_cfi_insn (struct cfi_insn_data *i
if (scaled <= 0x3F)
out_one (DW_CFA_advance_loc + scaled);
- else if (delta <= 0xFF)
+ else if (scaled <= 0xFF)
{
out_one (DW_CFA_advance_loc1);
- out_one (delta);
+ out_one (scaled);
}
- else if (delta <= 0xFFFF)
+ else if (scaled <= 0xFFFF)
{
out_one (DW_CFA_advance_loc2);
- out_two (delta);
+ out_two (scaled);
}
else
{
out_one (DW_CFA_advance_loc4);
- out_four (delta);
+ out_four (scaled);
}
}
else
Jakub