* write.c (relax_segment): Add pass count arg. Don't error on
negative org/space on first two passes. (relax_seg_info): New struct. (relax_seg, write_object_file): Adjust. * write.h (relax_segment): Update prototype.
This commit is contained in:
parent
692b141ccb
commit
32638454a7
3 changed files with 56 additions and 17 deletions
|
@ -1,3 +1,11 @@
|
|||
2006-05-08 Alan Modra <amodra@bigpond.net.au>
|
||||
|
||||
* write.c (relax_segment): Add pass count arg. Don't error on
|
||||
negative org/space on first two passes.
|
||||
(relax_seg_info): New struct.
|
||||
(relax_seg, write_object_file): Adjust.
|
||||
* write.h (relax_segment): Update prototype.
|
||||
|
||||
2006-05-05 Julian Brown <julian@codesourcery.com>
|
||||
|
||||
* config/tc-arm.c (parse_vfp_reg_list): Improve register bounds
|
||||
|
|
61
gas/write.c
61
gas/write.c
|
@ -512,19 +512,21 @@ cvt_frag_to_fill (segT sec ATTRIBUTE_UNUSED, fragS *fragP)
|
|||
#endif
|
||||
}
|
||||
|
||||
static void relax_seg (bfd *, asection *, PTR);
|
||||
struct relax_seg_info
|
||||
{
|
||||
int pass;
|
||||
int changed;
|
||||
};
|
||||
|
||||
static void
|
||||
relax_seg (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, PTR xxx)
|
||||
relax_seg (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, void *xxx)
|
||||
{
|
||||
segment_info_type *seginfo = seg_info (sec);
|
||||
struct relax_seg_info *info = (struct relax_seg_info *) xxx;
|
||||
|
||||
if (seginfo && seginfo->frchainP
|
||||
&& relax_segment (seginfo->frchainP->frch_root, sec))
|
||||
{
|
||||
int *result = (int *) xxx;
|
||||
*result = 1;
|
||||
}
|
||||
&& relax_segment (seginfo->frchainP->frch_root, sec, info->pass))
|
||||
info->changed = 1;
|
||||
}
|
||||
|
||||
static void size_seg (bfd *, asection *, PTR);
|
||||
|
@ -1206,6 +1208,7 @@ subsegs_finish (void)
|
|||
void
|
||||
write_object_file (void)
|
||||
{
|
||||
struct relax_seg_info rsi;
|
||||
#ifndef WORKING_DOT_WORD
|
||||
fragS *fragP; /* Track along all frags. */
|
||||
#endif
|
||||
|
@ -1264,10 +1267,9 @@ write_object_file (void)
|
|||
merge_data_into_text ();
|
||||
}
|
||||
|
||||
rsi.pass = 0;
|
||||
while (1)
|
||||
{
|
||||
int changed;
|
||||
|
||||
#ifndef WORKING_DOT_WORD
|
||||
/* We need to reset the markers in the broken word list and
|
||||
associated frags between calls to relax_segment (via
|
||||
|
@ -1288,9 +1290,10 @@ write_object_file (void)
|
|||
}
|
||||
#endif
|
||||
|
||||
changed = 0;
|
||||
bfd_map_over_sections (stdoutput, relax_seg, &changed);
|
||||
if (!changed)
|
||||
rsi.changed = 0;
|
||||
bfd_map_over_sections (stdoutput, relax_seg, &rsi);
|
||||
rsi.pass++;
|
||||
if (!rsi.changed)
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1721,7 +1724,7 @@ relax_align (register relax_addressT address, /* Address now. */
|
|||
addresses. */
|
||||
|
||||
int
|
||||
relax_segment (struct frag *segment_frag_root, segT segment)
|
||||
relax_segment (struct frag *segment_frag_root, segT segment, int pass)
|
||||
{
|
||||
unsigned long frag_count;
|
||||
struct frag *fragP;
|
||||
|
@ -1835,6 +1838,7 @@ relax_segment (struct frag *segment_frag_root, segT segment)
|
|||
if (max_iterations < frag_count)
|
||||
max_iterations = frag_count;
|
||||
|
||||
ret = 0;
|
||||
do
|
||||
{
|
||||
stretch = 0;
|
||||
|
@ -1964,6 +1968,26 @@ relax_segment (struct frag *segment_frag_root, segT segment)
|
|||
growth = target - after;
|
||||
if (growth < 0)
|
||||
{
|
||||
growth = 0;
|
||||
|
||||
/* Don't error on first few frag relax passes.
|
||||
The symbol might be an expression involving
|
||||
symbol values from other sections. If those
|
||||
sections have not yet been processed their
|
||||
frags will all have zero addresses, so we
|
||||
will calculate incorrect values for them. The
|
||||
number of passes we allow before giving an
|
||||
error is somewhat arbitrary. It should be at
|
||||
least one, with larger values requiring
|
||||
increasingly contrived dependencies between
|
||||
frags to trigger a false error. */
|
||||
if (pass < 2)
|
||||
{
|
||||
/* Force another pass. */
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Growth may be negative, but variable part of frag
|
||||
cannot have fewer than 0 chars. That is, we can't
|
||||
.org backwards. */
|
||||
|
@ -1976,7 +2000,7 @@ relax_segment (struct frag *segment_frag_root, segT segment)
|
|||
fragP->fr_subtype = 0;
|
||||
fragP->fr_offset = 0;
|
||||
fragP->fr_fix = after - was_address;
|
||||
growth = stretch;
|
||||
break;
|
||||
}
|
||||
|
||||
/* This is an absolute growth factor */
|
||||
|
@ -2002,6 +2026,14 @@ relax_segment (struct frag *segment_frag_root, segT segment)
|
|||
}
|
||||
else if (amount < 0)
|
||||
{
|
||||
/* Don't error on first few frag relax passes.
|
||||
See rs_org comment for a longer explanation. */
|
||||
if (pass < 2)
|
||||
{
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
as_warn_where (fragP->fr_file, fragP->fr_line,
|
||||
_(".space or .fill with negative value, ignored"));
|
||||
fragP->fr_symbol = 0;
|
||||
|
@ -2063,7 +2095,6 @@ relax_segment (struct frag *segment_frag_root, segT segment)
|
|||
segment_name (segment));
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
for (fragP = segment_frag_root; fragP; fragP = fragP->fr_next)
|
||||
if (fragP->last_fr_address != fragP->fr_address)
|
||||
{
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* write.h
|
||||
Copyright 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1999, 2000, 2001,
|
||||
2002, 2003, 2005 Free Software Foundation, Inc.
|
||||
2002, 2003, 2005, 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GAS, the GNU Assembler.
|
||||
|
||||
|
@ -156,7 +156,7 @@ extern int get_recorded_alignment (segT seg);
|
|||
extern void subsegs_finish (void);
|
||||
extern void write_object_file (void);
|
||||
extern long relax_frag (segT, fragS *, long);
|
||||
extern int relax_segment (struct frag * seg_frag_root, segT seg_type);
|
||||
extern int relax_segment (struct frag *, segT, int);
|
||||
extern void number_to_chars_littleendian (char *, valueT, int);
|
||||
extern void number_to_chars_bigendian (char *, valueT, int);
|
||||
extern fixS *fix_new
|
||||
|
|
Loading…
Reference in a new issue