* write.c (subsegs_finish): New function, broken out of
write_object_file. (write_object_file): Some code moves into subsegs_finish. * write.c (subsegs_finish): Declare. * as.c (main): Call subsegs_finish. Fixes last frag when generating a listing for a file with an error.
This commit is contained in:
parent
891a158431
commit
66a6a38139
3 changed files with 218 additions and 99 deletions
|
@ -1,5 +1,11 @@
|
|||
Sun Oct 19 13:50:50 1997 Ian Lance Taylor <ian@cygnus.com>
|
||||
|
||||
* write.c (subsegs_finish): New function, broken out of
|
||||
write_object_file.
|
||||
(write_object_file): Some code moves into subsegs_finish.
|
||||
* write.c (subsegs_finish): Declare.
|
||||
* as.c (main): Call subsegs_finish.
|
||||
|
||||
* read.c (s_include): Check for error return from
|
||||
demand_copy_string.
|
||||
|
||||
|
|
117
gas/write.c
117
gas/write.c
|
@ -502,6 +502,22 @@ cvt_frag_to_fill (headersP, sec, fragP)
|
|||
case rs_fill:
|
||||
break;
|
||||
|
||||
case rs_leb128:
|
||||
{
|
||||
valueT value = S_GET_VALUE (fragP->fr_symbol);
|
||||
int size;
|
||||
|
||||
size = output_leb128 (fragP->fr_literal + fragP->fr_fix, value,
|
||||
fragP->fr_subtype);
|
||||
|
||||
fragP->fr_fix += size;
|
||||
fragP->fr_type = rs_fill;
|
||||
fragP->fr_var = 0;
|
||||
fragP->fr_offset = 0;
|
||||
fragP->fr_symbol = NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
case rs_machine_dependent:
|
||||
#ifdef BFD_ASSEMBLER
|
||||
md_convert_frag (stdoutput, sec, fragP);
|
||||
|
@ -695,9 +711,9 @@ adjust_reloc_syms (abfd, sec, xxx)
|
|||
symbols, though, since they are not in the regular symbol
|
||||
table. */
|
||||
if (sym != NULL && ! sym->sy_resolved)
|
||||
resolve_symbol_value (sym);
|
||||
resolve_symbol_value (sym, 1);
|
||||
if (fixp->fx_subsy != NULL && ! fixp->fx_subsy->sy_resolved)
|
||||
resolve_symbol_value (fixp->fx_subsy);
|
||||
resolve_symbol_value (fixp->fx_subsy, 1);
|
||||
|
||||
/* If this symbol is equated to an undefined symbol, convert
|
||||
the fixup to being against that symbol. */
|
||||
|
@ -1301,10 +1317,47 @@ set_symtab ()
|
|||
}
|
||||
#endif
|
||||
|
||||
/* Finish the subsegments. After every sub-segment, we fake an
|
||||
".align ...". This conforms to BSD4.2 brane-damage. We then fake
|
||||
".fill 0" because that is the kind of frag that requires least
|
||||
thought. ".align" frags like to have a following frag since that
|
||||
makes calculating their intended length trivial. */
|
||||
|
||||
#ifndef SUB_SEGMENT_ALIGN
|
||||
#ifdef BFD_ASSEMBLER
|
||||
#define SUB_SEGMENT_ALIGN(SEG) (0)
|
||||
#else
|
||||
#define SUB_SEGMENT_ALIGN(SEG) (2)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void
|
||||
subsegs_finish ()
|
||||
{
|
||||
struct frchain *frchainP;
|
||||
|
||||
for (frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next)
|
||||
{
|
||||
subseg_set (frchainP->frch_seg, frchainP->frch_subseg);
|
||||
frag_align (SUB_SEGMENT_ALIGN (now_seg), NOP_OPCODE, 0);
|
||||
|
||||
/* frag_align will have left a new frag.
|
||||
Use this last frag for an empty ".fill".
|
||||
|
||||
For this segment ...
|
||||
Create a last frag. Do not leave a "being filled in frag". */
|
||||
|
||||
frag_wane (frag_now);
|
||||
frag_now->fr_fix = 0;
|
||||
know (frag_now->fr_next == NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* Write the object file. */
|
||||
|
||||
void
|
||||
write_object_file ()
|
||||
{
|
||||
struct frchain *frchainP; /* Track along all frchains. */
|
||||
#if ! defined (BFD_ASSEMBLER) || ! defined (WORKING_DOT_WORD)
|
||||
fragS *fragP; /* Track along all frags. */
|
||||
#endif
|
||||
|
@ -1339,34 +1392,6 @@ write_object_file ()
|
|||
vms_check_for_main ();
|
||||
#endif /* OBJ_VMS */
|
||||
|
||||
/* After every sub-segment, we fake an ".align ...". This conforms to
|
||||
BSD4.2 brane-damage. We then fake ".fill 0" because that is the kind of
|
||||
frag that requires least thought. ".align" frags like to have a
|
||||
following frag since that makes calculating their intended length
|
||||
trivial.
|
||||
|
||||
@@ Is this really necessary?? */
|
||||
#ifndef SUB_SEGMENT_ALIGN
|
||||
#ifdef BFD_ASSEMBLER
|
||||
#define SUB_SEGMENT_ALIGN(SEG) (0)
|
||||
#else
|
||||
#define SUB_SEGMENT_ALIGN(SEG) (2)
|
||||
#endif
|
||||
#endif
|
||||
for (frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next)
|
||||
{
|
||||
subseg_set (frchainP->frch_seg, frchainP->frch_subseg);
|
||||
frag_align (SUB_SEGMENT_ALIGN (now_seg), NOP_OPCODE, 0);
|
||||
/* frag_align will have left a new frag.
|
||||
Use this last frag for an empty ".fill".
|
||||
|
||||
For this segment ...
|
||||
Create a last frag. Do not leave a "being filled in frag". */
|
||||
frag_wane (frag_now);
|
||||
frag_now->fr_fix = 0;
|
||||
know (frag_now->fr_next == NULL);
|
||||
}
|
||||
|
||||
/* From now on, we don't care about sub-segments. Build one frag chain
|
||||
for each segment. Linked thru fr_next. */
|
||||
|
||||
|
@ -1711,7 +1736,7 @@ write_object_file ()
|
|||
|
||||
for (symp = symbol_rootP; symp; symp = symbol_next (symp))
|
||||
if (!symp->sy_resolved)
|
||||
resolve_symbol_value (symp);
|
||||
resolve_symbol_value (symp, 1);
|
||||
}
|
||||
|
||||
PROGRESS (1);
|
||||
|
@ -1768,7 +1793,7 @@ write_object_file ()
|
|||
symp->sy_resolved = 1;
|
||||
}
|
||||
else
|
||||
resolve_symbol_value (symp);
|
||||
resolve_symbol_value (symp, 1);
|
||||
}
|
||||
|
||||
/* Skip symbols which were equated to undefined or common
|
||||
|
@ -2094,6 +2119,12 @@ relax_segment (segment_frag_root, segment)
|
|||
break;
|
||||
#endif
|
||||
|
||||
case rs_leb128:
|
||||
/* Initial guess is always 1; doing otherwise can result in
|
||||
stable solutions that are larger than the minimum. */
|
||||
address += fragP->fr_offset = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
BAD_CASE (fragP->fr_type);
|
||||
break;
|
||||
|
@ -2283,6 +2314,18 @@ relax_segment (segment_frag_root, segment)
|
|||
#endif
|
||||
break;
|
||||
|
||||
case rs_leb128:
|
||||
{
|
||||
valueT value;
|
||||
int size;
|
||||
|
||||
value = resolve_symbol_value (fragP->fr_symbol, 0);
|
||||
size = sizeof_leb128 (value, fragP->fr_subtype);
|
||||
growth = size - fragP->fr_offset;
|
||||
fragP->fr_offset = size;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
BAD_CASE (fragP->fr_type);
|
||||
break;
|
||||
|
@ -2390,7 +2433,7 @@ fixup_segment (fixP, this_segment_type)
|
|||
|
||||
if (sub_symbolP)
|
||||
{
|
||||
resolve_symbol_value (sub_symbolP);
|
||||
resolve_symbol_value (sub_symbolP, 1);
|
||||
if (add_symbolP == NULL || add_symbol_segment == absolute_section)
|
||||
{
|
||||
if (add_symbolP != NULL)
|
||||
|
@ -2588,15 +2631,11 @@ fixup_segment (fixP, this_segment_type)
|
|||
else
|
||||
{
|
||||
seg_reloc_count++;
|
||||
/* start-sanitize-v850 */
|
||||
#if !(defined (TC_V850) && defined (OBJ_ELF))
|
||||
/* end-sanitize-v850 */
|
||||
#if !(defined (TC_M68K) && defined (OBJ_ELF))
|
||||
#if !defined (TC_I386) || !(defined (OBJ_ELF) || defined (OBJ_COFF))
|
||||
#if !defined (TC_I386) || !(defined (OBJ_ELF) || defined (OBJ_COFF)) || defined (TE_PE)
|
||||
add_number += S_GET_VALUE (add_symbolP);
|
||||
/* start-sanitize-v850 */
|
||||
#endif
|
||||
/* end-sanitize-v850 */
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
|
194
gas/write.h
194
gas/write.h
|
@ -1,6 +1,5 @@
|
|||
/* write.h
|
||||
|
||||
Copyright (C) 1987, 1992, 1993 Free Software Foundation, Inc.
|
||||
Copyright (C) 1987, 92, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GAS, the GNU Assembler.
|
||||
|
||||
|
@ -15,8 +14,9 @@
|
|||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GAS; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
along with GAS; see the file COPYING. If not, write to the Free
|
||||
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA. */
|
||||
|
||||
#ifndef TC_I960
|
||||
#ifdef hpux
|
||||
|
@ -24,16 +24,19 @@
|
|||
#endif
|
||||
#endif /* TC_I960 */
|
||||
|
||||
#ifndef LOCAL_LABEL
|
||||
#ifdef DOT_LABEL_PREFIX
|
||||
#define LOCAL_LABEL(name) (name[0] =='.' \
|
||||
&& ( name [1] == 'L' || name [1] == '.' ))
|
||||
#else /* not defined DOT_LABEL_PREFIX */
|
||||
#define LOCAL_LABEL(name) (name [0] == 'L' )
|
||||
#endif /* not defined DOT_LABEL_PREFIX */
|
||||
#endif /* LOCAL_LABEL */
|
||||
#ifndef BFD_ASSEMBLER
|
||||
|
||||
#define S_LOCAL_NAME(s) (LOCAL_LABEL(S_GET_NAME(s)))
|
||||
#ifndef LOCAL_LABEL
|
||||
#define LOCAL_LABEL(name) (name [0] == 'L' )
|
||||
#endif
|
||||
|
||||
#define S_LOCAL_NAME(s) (LOCAL_LABEL (S_GET_NAME (s)))
|
||||
|
||||
#endif /* ! BFD_ASSEMBLER */
|
||||
|
||||
/* This is the name of a fake symbol which will never appear in the
|
||||
assembler output. S_IS_LOCAL detects it because of the \001. */
|
||||
#define FAKE_LABEL_NAME "L0\001"
|
||||
|
||||
#include "bit_fix.h"
|
||||
|
||||
|
@ -42,43 +45,102 @@
|
|||
*/
|
||||
|
||||
struct fix
|
||||
{
|
||||
/* These small fields are grouped together for compactness of
|
||||
this structure, and efficiency of access on some architectures. */
|
||||
char fx_pcrel_adjust; /* pc-relative offset adjust */
|
||||
unsigned fx_pcrel : 1; /* TRUE: pc-relative. */
|
||||
unsigned fx_im_disp : 1; /* TRUE: value is a displacement */
|
||||
unsigned fx_bsr : 1; /* sequent-hack */
|
||||
/* TRUE if target is a 'callj' (used by i960) */
|
||||
unsigned fx_callj : 1;
|
||||
short int fx_size; /* How many bytes are involved? */
|
||||
{
|
||||
/* These small fields are grouped together for compactness of
|
||||
this structure, and efficiency of access on some architectures. */
|
||||
|
||||
/* pc-relative offset adjust */
|
||||
char fx_pcrel_adjust;
|
||||
|
||||
/* How many bytes are involved? */
|
||||
unsigned char fx_size;
|
||||
|
||||
/* Is this a pc-relative relocation? */
|
||||
unsigned fx_pcrel : 1;
|
||||
|
||||
/* Is this a relocation to a procedure linkage table entry? If so,
|
||||
some of the reductions we try to apply are invalid. A better way
|
||||
might be to represent PLT entries with different kinds of
|
||||
symbols, and use normal relocations (with undefined symbols);
|
||||
look into it for version 2.6. */
|
||||
unsigned fx_plt : 1;
|
||||
|
||||
/* Is this value an immediate displacement? */
|
||||
/* Only used on i960 and ns32k; merge it into TC_FIX_TYPE sometime. */
|
||||
unsigned fx_im_disp : 2;
|
||||
|
||||
/* A bit for the CPU specific code.
|
||||
This probably can be folded into tc_fix_data, below. */
|
||||
unsigned fx_tcbit : 1;
|
||||
|
||||
/* Has this relocation already been applied? */
|
||||
unsigned fx_done : 1;
|
||||
|
||||
/* Suppress overflow complaints on large addends. This is used
|
||||
in the PowerPC ELF config to allow large addends on the
|
||||
BFD_RELOC_{LO16,HI16,HI16_S} relocations.
|
||||
|
||||
@@ Can this be determined from BFD? */
|
||||
unsigned fx_no_overflow : 1;
|
||||
|
||||
/* The value is signed when checking for overflow. */
|
||||
unsigned fx_signed : 1;
|
||||
|
||||
/* Which frag does this fix apply to? */
|
||||
fragS *fx_frag;
|
||||
|
||||
/* Where is the first byte to fix up? */
|
||||
long fx_where;
|
||||
|
||||
/* NULL or Symbol whose value we add in. */
|
||||
symbolS *fx_addsy;
|
||||
|
||||
/* NULL or Symbol whose value we subtract. */
|
||||
symbolS *fx_subsy;
|
||||
|
||||
/* Absolute number we add in. */
|
||||
valueT fx_offset;
|
||||
|
||||
/* Next fixS in linked list, or NULL. */
|
||||
struct fix *fx_next;
|
||||
|
||||
/* If NULL, no bitfix's to do. */
|
||||
/* Only i960-coff and ns32k use this, and i960-coff stores an
|
||||
integer. This can probably be folded into tc_fix_data, below.
|
||||
@@ Alpha also uses it, but only to disable certain relocation
|
||||
processing. */
|
||||
bit_fixS *fx_bit_fixP;
|
||||
|
||||
fragS *fx_frag; /* Which frag? */
|
||||
long fx_where; /* Where is the 1st byte to fix up? */
|
||||
symbolS *fx_addsy; /* NULL or Symbol whose value we add in. */
|
||||
symbolS *fx_subsy; /* NULL or Symbol whose value we subtract. */
|
||||
valueT fx_offset; /* Absolute number we add in. */
|
||||
struct fix *fx_next; /* NULL or -> next fixS. */
|
||||
bit_fixS *fx_bit_fixP; /* IF NULL no bitfix's to do */
|
||||
#ifdef BFD_ASSEMBLER
|
||||
bfd_reloc_code_real_type fx_r_type;
|
||||
bfd_reloc_code_real_type fx_r_type;
|
||||
#else
|
||||
#ifdef NEED_FX_R_TYPE
|
||||
/* Hack for machines where the type of reloc can't be
|
||||
worked out by looking at how big it is. */
|
||||
int fx_r_type;
|
||||
/* Hack for machines where the type of reloc can't be
|
||||
worked out by looking at how big it is. */
|
||||
int fx_r_type;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* This field is sort of misnamed. It appears to be a sort of random
|
||||
scratch field, for use by the back ends. The main gas code doesn't
|
||||
do anything but initialize it to zero. The use of it does need to
|
||||
be coordinated between the cpu and format files, though. E.g., some
|
||||
coff targets pass the `addend' field from the cpu file via this
|
||||
field. I don't know why the `fx_offset' field above can't be used
|
||||
for that; investigate later and document. KR */
|
||||
valueT fx_addnumber;
|
||||
};
|
||||
/* This field is sort of misnamed. It appears to be a sort of random
|
||||
scratch field, for use by the back ends. The main gas code doesn't
|
||||
do anything but initialize it to zero. The use of it does need to
|
||||
be coordinated between the cpu and format files, though. E.g., some
|
||||
coff targets pass the `addend' field from the cpu file via this
|
||||
field. I don't know why the `fx_offset' field above can't be used
|
||||
for that; investigate later and document. KR */
|
||||
valueT fx_addnumber;
|
||||
|
||||
/* The location of the instruction which created the reloc, used
|
||||
in error messages. */
|
||||
char *fx_file;
|
||||
unsigned fx_line;
|
||||
|
||||
#ifdef TC_FIX_TYPE
|
||||
/* Location where a backend can attach additional data
|
||||
needed to perform fixups. */
|
||||
TC_FIX_TYPE tc_fix_data;
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef struct fix fixS;
|
||||
|
||||
|
@ -89,6 +151,8 @@ extern char *next_object_file_charP;
|
|||
COMMON fixS *text_fix_root, *text_fix_tail; /* Chains fixSs. */
|
||||
COMMON fixS *data_fix_root, *data_fix_tail; /* Chains fixSs. */
|
||||
COMMON fixS *bss_fix_root, *bss_fix_tail; /* Chains fixSs. */
|
||||
extern struct frag *text_last_frag; /* Last frag in segment. */
|
||||
extern struct frag *data_last_frag; /* Last frag in segment. */
|
||||
#endif
|
||||
COMMON fixS **seg_fix_rootP, **seg_fix_tailP; /* -> one of above. */
|
||||
#endif
|
||||
|
@ -96,26 +160,36 @@ COMMON fixS **seg_fix_rootP, **seg_fix_tailP; /* -> one of above. */
|
|||
extern long string_byte_count;
|
||||
extern int section_alignment[];
|
||||
|
||||
bit_fixS *bit_fix_new PARAMS ((int size, int offset, long base_type,
|
||||
long base_adj, long min, long max, long add));
|
||||
void append PARAMS ((char **charPP, char *fromP, unsigned long length));
|
||||
void record_alignment PARAMS ((segT seg, int align));
|
||||
void write_object_file PARAMS ((void));
|
||||
void relax_segment PARAMS ((struct frag * seg_frag_root, segT seg_type));
|
||||
extern bit_fixS *bit_fix_new
|
||||
PARAMS ((int size, int offset, long base_type, long base_adj, long min,
|
||||
long max, long add));
|
||||
extern void append PARAMS ((char **charPP, char *fromP, unsigned long length));
|
||||
extern void record_alignment PARAMS ((segT seg, int align));
|
||||
extern void subsegs_finish PARAMS ((void));
|
||||
extern void write_object_file PARAMS ((void));
|
||||
extern long relax_frag PARAMS ((fragS *, long));
|
||||
extern void relax_segment
|
||||
PARAMS ((struct frag * seg_frag_root, segT seg_type));
|
||||
|
||||
extern void number_to_chars_littleendian PARAMS ((char *, valueT, int));
|
||||
extern void number_to_chars_bigendian PARAMS ((char *, valueT, int));
|
||||
|
||||
#ifdef BFD_ASSEMBLER
|
||||
fixS *fix_new PARAMS ((fragS * frag, int where, int size,
|
||||
symbolS * add_symbol, offsetT offset, int pcrel,
|
||||
bfd_reloc_code_real_type r_type));
|
||||
fixS *fix_new_exp PARAMS ((fragS * frag, int where, int size,
|
||||
expressionS *exp, int pcrel,
|
||||
bfd_reloc_code_real_type r_type));
|
||||
extern fixS *fix_new
|
||||
PARAMS ((fragS * frag, int where, int size, symbolS * add_symbol,
|
||||
offsetT offset, int pcrel, bfd_reloc_code_real_type r_type));
|
||||
extern fixS *fix_new_exp
|
||||
PARAMS ((fragS * frag, int where, int size, expressionS *exp, int pcrel,
|
||||
bfd_reloc_code_real_type r_type));
|
||||
#else
|
||||
fixS *fix_new PARAMS ((fragS * frag, int where, int size,
|
||||
symbolS * add_symbol, offsetT offset, int pcrel,
|
||||
int r_type));
|
||||
fixS *fix_new_exp PARAMS ((fragS * frag, int where, int size,
|
||||
expressionS *exp, int pcrel, int r_type));
|
||||
extern fixS *fix_new
|
||||
PARAMS ((fragS * frag, int where, int size, symbolS * add_symbol,
|
||||
offsetT offset, int pcrel, int r_type));
|
||||
extern fixS *fix_new_exp
|
||||
PARAMS ((fragS * frag, int where, int size, expressionS *exp, int pcrel,
|
||||
int r_type));
|
||||
#endif
|
||||
|
||||
extern void write_print_statistics PARAMS ((FILE *));
|
||||
|
||||
/* end of write.h */
|
||||
|
|
Loading…
Add table
Reference in a new issue