PATCH: [Bug gas/4029] relax_segment can't stabilize .gcc_except_table
H. J. Lu
hjl@lucon.org
Mon Mar 12 00:51:00 GMT 2007
More information about the Binutils mailing list
Mon Mar 12 00:51:00 GMT 2007
- Previous message (by thread): committed: remove confusing #line in ld/emultempl/mmixelf.em
- Next message (by thread): PATCH: [Bug gas/4029] relax_segment can't stabilize .gcc_except_table
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
On Sun, Mar 11, 2007 at 01:37:04PM -0000, amodra at bigpond dot net dot au wrote: > > Yes, we can modify the output, but we must do so in a way that does not confuse > consumers of .gcc_except_table. I don't believe changing the .align is correct, > because data normally follows the .align (a number of .long's before the end > label). Changing alignment in a way that cures the uleb128 problem necessarily > inserts zero bytes, which I think will confuse the unwinder. > I don't think increasing alignment should break any well formed assembly codes. This patch breaks the infinite loop by increasing alignment before the left symbol in leb128. H.J. ----- gas/ 2007-02-19 H.J. Lu <hongjiu.lu@intel.com> PR gas/4029 * symbols.c (symbol_get_subtract_frags): New. * symbols.h (symbol_get_subtract_frags): Likewise. * write.c (relax_segment): Break infinite loop for rs_leb128 by increasing alignment. gas/testsuite/ 2007-02-19 Alan Modra <amodra@bigpond.net.au> H.J. Lu <hongjiu.lu@intel.com> PR gas/4029 * gas/all/gas.exp: Add relax. * gas/all/relax.d: New file. * gas/all/relax.s: Likewise. --- gas/symbols.c.relax 2007-03-08 06:16:17.000000000 -0800 +++ gas/symbols.c 2007-03-11 16:59:39.000000000 -0700 @@ -3153,3 +3153,24 @@ symbol_relc_make_expr (expressionS * exp } #endif + +/* Get frags of left and right symbols in subtraction. */ + +void +symbol_get_subtract_frags (symbolS *sym, fragS **left, fragS **right) +{ + if (sym->sy_value.X_op == O_subtract) + { + if (left) + *left = symbol_get_frag (sym->sy_value.X_add_symbol); + if (right) + *right = symbol_get_frag (sym->sy_value.X_op_symbol); + } + else + { + if (left) + *left = NULL; + if (right) + *right = NULL; + } +} --- gas/symbols.h.relax 2007-02-05 17:27:16.000000000 -0800 +++ gas/symbols.h 2007-03-11 16:53:37.000000000 -0700 @@ -177,6 +177,7 @@ extern offsetT *symbol_X_add_number (sym extern void symbol_set_value_now (symbolS *); extern void symbol_set_frag (symbolS *, fragS *); extern fragS *symbol_get_frag (symbolS *); +extern void symbol_get_subtract_frags (symbolS *, fragS **, fragS **); extern void symbol_mark_used (symbolS *); extern void symbol_clear_used (symbolS *); extern int symbol_used_p (symbolS *); --- gas/testsuite/gas/all/gas.exp.relax 2007-02-06 07:53:27.000000000 -0800 +++ gas/testsuite/gas/all/gas.exp 2007-03-11 17:37:31.000000000 -0700 @@ -264,6 +264,7 @@ if { ([istarget "i*86-*-*pe*"] && ![ist run_dump_test assign run_dump_test sleb128 +run_dump_test relax # .quad is 16 bytes on i960. if { ![istarget "i960-*-*"] } { --- gas/testsuite/gas/all/relax.d.relax 2007-03-11 17:27:00.000000000 -0700 +++ gas/testsuite/gas/all/relax.d 2007-03-11 17:31:12.000000000 -0700 @@ -0,0 +1,11 @@ +#objdump : -s -j .data -j "\$DATA\$" +#name : relax .sleb128 + +.*: .* + +Contents of section (\.data|\$DATA\$): + 0000 00008380 01070000 00000000 00000000 ................ + 0010 00000000 00000000 00000000 00000000 ................ +#... + 4000 00000000 00000000 ........ +#pass --- gas/testsuite/gas/all/relax.s.relax 2007-03-11 17:25:51.000000000 -0700 +++ gas/testsuite/gas/all/relax.s 2007-03-11 17:25:37.000000000 -0700 @@ -0,0 +1,9 @@ + .data + .align 4 + .byte 0, 0 + .uleb128 end - start +start: + .byte 7 + .space 128*128 - 3 /* or -2 or -3 */ + .align 4 +end: --- gas/write.c.relax 2007-03-01 14:53:14.000000000 -0800 +++ gas/write.c 2007-03-11 17:43:43.000000000 -0700 @@ -1985,6 +1985,7 @@ relax_segment (struct frag *segment_frag ret = 0; do { +restart: stretch = 0; stretched = 0; @@ -2209,6 +2210,36 @@ relax_segment (struct frag *segment_frag size = sizeof_leb128 (value, fragP->fr_subtype); growth = size - fragP->fr_offset; fragP->fr_offset = size; + if (growth < 0) + { + struct frag *left; + + /* We started it at size 1. If it shrinks now, + it means that we will go into an infinite + loop. We try to adjust aligment before + the left symbol. */ + symbol_get_subtract_frags (fragP->fr_symbol, + &left, NULL); + if (left) + { + struct frag *alignP = NULL, *nextP; + + for (nextP = fragP; + nextP && nextP != left; + nextP = nextP->fr_next) + if (nextP->fr_type == rs_align + && nextP->fr_offset != 0) + alignP = nextP; + + if (alignP) + { + /* FIXME: Is it 100% safe to increase + alignment? */ + alignP->fr_offset++; + goto restart; + } + } + } } break;
- Previous message (by thread): committed: remove confusing #line in ld/emultempl/mmixelf.em
- Next message (by thread): PATCH: [Bug gas/4029] relax_segment can't stabilize .gcc_except_table
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
More information about the Binutils mailing list