X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gas%2Ffrags.c;h=f35cc80a386ed0dd6e04af32e9ba7cb520ecb437;hb=cedfc77485dbb566619dc1e2d729ce0a70d1a4ad;hp=e14099dda45c49ab2bcb192d224e355acb677b63;hpb=a82c7d9030b67a6a76a5403d0e1641f9e42141ac;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/frags.c b/gas/frags.c index e14099dda4..f35cc80a38 100644 --- a/gas/frags.c +++ b/gas/frags.c @@ -1,5 +1,5 @@ /* frags.c - manage frags - - Copyright (C) 1987-2014 Free Software Foundation, Inc. + Copyright (C) 1987-2019 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -94,12 +94,12 @@ frag_alloc (struct obstack *ob) do not return. Do not set up any fields of *now_frag. */ void -frag_grow (unsigned int nchars) +frag_grow (size_t nchars) { if (obstack_room (&frchain_now->frch_obstack) < nchars) { - long oldc; - long newc; + size_t oldc; + size_t newc; /* Try to allocate a bit more than needed right now. But don't do this if we would waste too much memory. Especially necessary @@ -111,8 +111,11 @@ frag_grow (unsigned int nchars) newc += SIZEOF_STRUCT_FRAG; /* Check for possible overflow. */ - if (newc < 0) - as_fatal (_("can't extend frag %u chars"), nchars); + if (newc < nchars) + as_fatal (ngettext ("can't extend frag %lu char", + "can't extend frag %lu chars", + (unsigned long) nchars), + (unsigned long) nchars); /* Force to allocate at least NEWC bytes, but not less than the default. */ @@ -152,7 +155,7 @@ frag_grow (unsigned int nchars) of frchain_now. */ void -frag_new (int old_frags_var_max_size +frag_new (size_t old_frags_var_max_size /* Number of chars (already allocated on obstack frags) in variable_length part of frag. */) { @@ -162,7 +165,9 @@ frag_new (int old_frags_var_max_size gas_assert (frchain_now->frch_last == frag_now); /* Fix up old frag's fr_fix. */ - frag_now->fr_fix = frag_now_fix_octets () - old_frags_var_max_size; + frag_now->fr_fix = frag_now_fix_octets (); + gas_assert (frag_now->fr_fix >= old_frags_var_max_size); + frag_now->fr_fix -= old_frags_var_max_size; /* Make sure its type is valid. */ gas_assert (frag_now->fr_type != 0); @@ -176,7 +181,7 @@ frag_new (int old_frags_var_max_size gas_assert (former_last_fragP == frag_now); frag_now = frag_alloc (&frchP->frch_obstack); - as_where (&frag_now->fr_file, &frag_now->fr_line); + frag_now->fr_file = as_where (&frag_now->fr_line); /* Generally, frag_now->points to an address rounded up to next alignment. However, characters will add to obstack frags @@ -204,23 +209,23 @@ frag_new (int old_frags_var_max_size frag_now_growth past the new chars. */ char * -frag_more (int nchars) +frag_more (size_t nchars) { - register char *retval; + char *retval; frag_alloc_check (&frchain_now->frch_obstack); frag_grow (nchars); retval = obstack_next_free (&frchain_now->frch_obstack); obstack_blank_fast (&frchain_now->frch_obstack, nchars); - return (retval); + return retval; } /* Close the current frag, setting its fields for a relaxable frag. Start a new frag. */ static void -frag_var_init (relax_stateT type, int max_chars, int var, - relax_substateT subtype, symbolS *symbol, offsetT offset, +frag_var_init (relax_stateT type, size_t max_chars, size_t var, + relax_substateT subtype, symbolS *symbol, offsetT offset, char *opcode) { frag_now->fr_var = var; @@ -235,9 +240,9 @@ frag_var_init (relax_stateT type, int max_chars, int var, frag_now->fr_cgen.opinfo = 0; #endif #ifdef TC_FRAG_INIT - TC_FRAG_INIT (frag_now); + TC_FRAG_INIT (frag_now, max_chars); #endif - as_where (&frag_now->fr_file, &frag_now->fr_line); + frag_now->fr_file = as_where (&frag_now->fr_line); frag_new (max_chars); } @@ -250,10 +255,11 @@ frag_var_init (relax_stateT type, int max_chars, int var, to write into. */ char * -frag_var (relax_stateT type, int max_chars, int var, relax_substateT subtype, - symbolS *symbol, offsetT offset, char *opcode) +frag_var (relax_stateT type, size_t max_chars, size_t var, + relax_substateT subtype, symbolS *symbol, offsetT offset, + char *opcode) { - register char *retval; + char *retval; frag_grow (max_chars); retval = obstack_next_free (&frchain_now->frch_obstack); @@ -267,11 +273,11 @@ frag_var (relax_stateT type, int max_chars, int var, relax_substateT subtype, No call to frag_grow is done. */ char * -frag_variant (relax_stateT type, int max_chars, int var, +frag_variant (relax_stateT type, size_t max_chars, size_t var, relax_substateT subtype, symbolS *symbol, offsetT offset, char *opcode) { - register char *retval; + char *retval; retval = obstack_next_free (&frchain_now->frch_obstack); frag_var_init (type, max_chars, var, subtype, symbol, offset, opcode); @@ -282,7 +288,7 @@ frag_variant (relax_stateT type, int max_chars, int var, /* Reduce the variable end of a frag to a harmless state. */ void -frag_wane (register fragS *fragP) +frag_wane (fragS *fragP) { fragP->fr_type = rs_fill; fragP->fr_offset = 0; @@ -291,7 +297,7 @@ frag_wane (register fragS *fragP) /* Return the number of bytes by which the current frag can be grown. */ -int +size_t frag_room (void) { return obstack_room (&frchain_now->frch_obstack); @@ -336,7 +342,7 @@ frag_align (int alignment, int fill_character, int max) void frag_align_pattern (int alignment, const char *fill_pattern, - int n_fill, int max) + size_t n_fill, int max) { char *p; @@ -389,7 +395,12 @@ frag_now_fix_octets (void) addressT frag_now_fix (void) { - return frag_now_fix_octets () / OCTETS_PER_BYTE; + /* Symbols whose section has SEC_ELF_OCTETS set, + resolve to octets instead of target bytes. */ + if (now_seg->flags & SEC_OCTETS) + return frag_now_fix_octets (); + else + return frag_now_fix_octets () / OCTETS_PER_BYTE; } void @@ -456,3 +467,58 @@ frag_offset_fixed_p (const fragS *frag1, const fragS *frag2, offsetT *offset) return FALSE; } + +/* Return TRUE if we can determine whether FRAG2 OFF2 appears after + (strict >, not >=) FRAG1 OFF1, assuming it is not before. Set + *OFFSET so that resolve_expression will resolve an O_gt operation + between them to false (0) if they are guaranteed to be at the same + location, or to true (-1) if they are guaranteed to be at different + locations. Return FALSE conservatively, e.g. if neither result can + be guaranteed (yet). + + They are known to be in the same segment, and not the same frag + (this is a fallback for frag_offset_fixed_p, that always takes care + of this case), and it is expected (from the uses this is designed + to simplify, namely location view increments) that frag2 is + reachable from frag1 following the fr_next links, rather than the + other way round. */ + +bfd_boolean +frag_gtoffset_p (valueT off2, const fragS *frag2, + valueT off1, const fragS *frag1, offsetT *offset) +{ + /* Insanity check. */ + if (frag2 == frag1 || off1 > frag1->fr_fix) + return FALSE; + + /* If the first symbol offset is at the end of the first frag and + the second symbol offset at the beginning of the second frag then + it is possible they are at the same address. Go looking for a + non-zero fr_fix in any frag between these frags. If found then + we can say the O_gt result will be true. If no such frag is + found we assume that frag1 or any of the following frags might + have a variable tail and thus the answer is unknown. This isn't + strictly true; some frags don't have a variable tail, but it + doesn't seem worth optimizing for those cases. */ + const fragS *frag = frag1; + offsetT delta = off2 - off1; + for (;;) + { + delta += frag->fr_fix; + frag = frag->fr_next; + if (frag == frag2) + { + if (delta == 0) + return FALSE; + break; + } + /* If we run off the end of the frag chain then we have a case + where frag2 is not after frag1, ie. an O_gt expression not + created for .loc view. */ + if (frag == NULL) + return FALSE; + } + + *offset = (off2 - off1 - delta) * OCTETS_PER_BYTE; + return TRUE; +}