* ehopt.c: New file.
* as.h (enum _relax_state): Add rs_cfa. (check_eh_frame, eh_frame_estimate_size_before_relax): Declare. (eh_frame_relax_frag, eh_frame_convert_frag): Declare. * read.c (emit_expr): Call check_eh_frame. * write.c (cvt_frag_to_fill): Handle rs_cfa. (relax_segment): Likewise. * Makefile.am: Rebuild dependencies. (GAS_CFILES): Add ehopt.c. (GENERIC_OBJS): Add ehopt.o. * doc/internals.texi (Frags): Document rs_cfa. * as.c (show_usage): Mention --traditional-format. (parse_args): Accept --traditional-format. * as.h (flag_traditional_format): Declare. * output-file.c (output_file_create): If flag_traditional_format, set BFD_TRADITIONAL_FORMAT on stdoutput. * doc/as.texinfo, doc/as.1: Document --traditional-format.
This commit is contained in:
parent
44d33d559e
commit
ffd652c313
9 changed files with 435 additions and 8 deletions
|
@ -63,6 +63,7 @@ depend.c
|
|||
doc
|
||||
ecoff.c
|
||||
ecoff.h
|
||||
ehopt.c
|
||||
emul-target.h
|
||||
emul.h
|
||||
expr.c
|
||||
|
|
|
@ -1,5 +1,24 @@
|
|||
Thu Feb 5 12:39:08 1998 Ian Lance Taylor <ian@cygnus.com>
|
||||
|
||||
* ehopt.c: New file.
|
||||
* as.h (enum _relax_state): Add rs_cfa.
|
||||
(check_eh_frame, eh_frame_estimate_size_before_relax): Declare.
|
||||
(eh_frame_relax_frag, eh_frame_convert_frag): Declare.
|
||||
* read.c (emit_expr): Call check_eh_frame.
|
||||
* write.c (cvt_frag_to_fill): Handle rs_cfa.
|
||||
(relax_segment): Likewise.
|
||||
* Makefile.am: Rebuild dependencies.
|
||||
(GAS_CFILES): Add ehopt.c.
|
||||
(GENERIC_OBJS): Add ehopt.o.
|
||||
* doc/internals.texi (Frags): Document rs_cfa.
|
||||
|
||||
* as.c (show_usage): Mention --traditional-format.
|
||||
(parse_args): Accept --traditional-format.
|
||||
* as.h (flag_traditional_format): Declare.
|
||||
* output-file.c (output_file_create): If flag_traditional_format,
|
||||
set BFD_TRADITIONAL_FORMAT on stdoutput.
|
||||
* doc/as.texinfo, doc/as.1: Document --traditional-format.
|
||||
|
||||
* config/tc-mips.c (append_insn): Make sure that if we have a
|
||||
fixup for an unmatched %hi reloc, it does not associated with a
|
||||
variant frag.
|
||||
|
|
|
@ -128,6 +128,7 @@ GAS_CFILES = \
|
|||
cond.c \
|
||||
depend.c \
|
||||
ecoff.c \
|
||||
ehopt.c \
|
||||
expr.c \
|
||||
flonum-copy.c \
|
||||
flonum-konst.c \
|
||||
|
@ -315,6 +316,7 @@ GENERIC_OBJS = \
|
|||
bignum-copy.o \
|
||||
cond.o \
|
||||
depend.o \
|
||||
ehopt.o \
|
||||
expr.o \
|
||||
flonum-konst.o \
|
||||
flonum-copy.o \
|
||||
|
|
|
@ -203,6 +203,7 @@ GAS_CFILES = \
|
|||
cond.c \
|
||||
depend.c \
|
||||
ecoff.c \
|
||||
ehopt.c \
|
||||
expr.c \
|
||||
flonum-copy.c \
|
||||
flonum-konst.c \
|
||||
|
@ -390,6 +391,7 @@ GENERIC_OBJS = \
|
|||
bignum-copy.o \
|
||||
cond.o \
|
||||
depend.o \
|
||||
ehopt.o \
|
||||
expr.o \
|
||||
flonum-konst.o \
|
||||
flonum-copy.o \
|
||||
|
@ -1191,10 +1193,10 @@ itbl_test_DEPENDENCIES = itbl-test-ops.o itbl-test.o \
|
|||
../libiberty/libiberty.a
|
||||
itbl_test_LDFLAGS =
|
||||
as_new_OBJECTS = app.o as.o atof-generic.o bignum-copy.o cond.o \
|
||||
depend.o ecoff.o expr.o flonum-copy.o flonum-konst.o flonum-mult.o \
|
||||
frags.o hash.o input-file.o input-scrub.o listing.o literal.o macro.o \
|
||||
messages.o output-file.o read.o sb.o stabs.o subsegs.o symbols.o \
|
||||
write.o
|
||||
depend.o ecoff.o ehopt.o expr.o flonum-copy.o flonum-konst.o \
|
||||
flonum-mult.o frags.o hash.o input-file.o input-scrub.o listing.o \
|
||||
literal.o macro.o messages.o output-file.o read.o sb.o stabs.o \
|
||||
subsegs.o symbols.o write.o
|
||||
as_new_LDFLAGS =
|
||||
gasp_new_OBJECTS = gasp.o macro.o sb.o hash.o
|
||||
gasp_new_DEPENDENCIES = ../libiberty/libiberty.a
|
||||
|
|
3
gas/NEWS
3
gas/NEWS
|
@ -4,6 +4,9 @@ Changes in 2.9:
|
|||
|
||||
Texas Instruction c30 (tms320c30) support added.
|
||||
|
||||
The assembler now optimizes the exception frame information generated by egcs
|
||||
and gcc 2.8. The new --traditional-format disables this optimization.
|
||||
|
||||
Added --gstabs option to generates stabs debugging information.
|
||||
|
||||
The -a option takes a new suboption, m (e.g., -alm) to expand macros in a
|
||||
|
|
11
gas/as.c
11
gas/as.c
|
@ -1,5 +1,5 @@
|
|||
/* as.c - GAS main program.
|
||||
Copyright (C) 1987, 90, 91, 92, 93, 94, 95, 96, 1997
|
||||
Copyright (C) 1987, 90, 91, 92, 93, 94, 95, 96, 97, 1998
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GAS, the GNU Assembler.
|
||||
|
@ -159,6 +159,7 @@ Options:\n\
|
|||
-R fold data section into text section\n\
|
||||
--statistics print various measured statistics from execution\n\
|
||||
--strip-local-absolute strip local absolute symbols\n\
|
||||
--traditional-format Use same format as native assembler when possible\n\
|
||||
--version print assembler version number and exit\n\
|
||||
-W suppress warnings\n\
|
||||
--itbl INSTTBL extend instruction set to include instructions\n\
|
||||
|
@ -356,7 +357,9 @@ parse_args (pargc, pargv)
|
|||
#define OPTION_GSTABS (OPTION_STD_BASE + 14)
|
||||
{"gstabs", no_argument, NULL, OPTION_GSTABS},
|
||||
#define OPTION_STRIP_LOCAL_ABSOLUTE (OPTION_STD_BASE + 15)
|
||||
{"strip-local-absolute", no_argument, NULL, OPTION_STRIP_LOCAL_ABSOLUTE}
|
||||
{"strip-local-absolute", no_argument, NULL, OPTION_STRIP_LOCAL_ABSOLUTE},
|
||||
#define OPTION_TRADITIONAL_FORMAT (OPTION_STD_BASE + 16)
|
||||
{"traditional-format", no_argument, NULL, OPTION_TRADITIONAL_FORMAT}
|
||||
};
|
||||
|
||||
/* Construct the option lists from the standard list and the
|
||||
|
@ -441,6 +444,10 @@ parse_args (pargc, pargv)
|
|||
flag_strip_local_absolute = 1;
|
||||
break;
|
||||
|
||||
case OPTION_TRADITIONAL_FORMAT:
|
||||
flag_traditional_format = 1;
|
||||
break;
|
||||
|
||||
case OPTION_VERSION:
|
||||
/* This output is intended to follow the GNU standards document. */
|
||||
printf ("GNU assembler %s\n", VERSION);
|
||||
|
|
13
gas/as.h
13
gas/as.h
|
@ -381,7 +381,10 @@ enum _relax_state
|
|||
|
||||
/* A DWARF leb128 value; only ELF uses this. The subtype is 0 for
|
||||
unsigned, 1 for signed. */
|
||||
rs_leb128
|
||||
rs_leb128,
|
||||
|
||||
/* Exception frame information which we may be able to optimize. */
|
||||
rs_cfa
|
||||
};
|
||||
|
||||
typedef enum _relax_state relax_stateT;
|
||||
|
@ -432,6 +435,9 @@ COMMON unsigned char flag_print_statistics;
|
|||
/* True if local absolute symbols are to be stripped. */
|
||||
COMMON int flag_strip_local_absolute;
|
||||
|
||||
/* True if we should generate a traditional format object file. */
|
||||
COMMON int flag_traditional_format;
|
||||
|
||||
/* name of emitted object file */
|
||||
COMMON char *out_file_name;
|
||||
|
||||
|
@ -585,6 +591,11 @@ typedef struct frag fragS;
|
|||
valueT add_to_literal_pool PARAMS ((struct symbol *, valueT, segT, int));
|
||||
#endif
|
||||
|
||||
int check_eh_frame PARAMS ((struct expressionS *, unsigned int *));
|
||||
int eh_frame_estimate_size_before_relax PARAMS ((fragS *));
|
||||
int eh_frame_relax_frag PARAMS ((fragS *));
|
||||
void eh_frame_convert_frag PARAMS ((fragS *));
|
||||
|
||||
#include "expr.h" /* Before targ-*.h */
|
||||
|
||||
/* this one starts the chain of target dependant headers */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
.\" Copyright (c) 1991, 1992, 1996, 1997 Free Software Foundation
|
||||
.\" Copyright (c) 1991, 1992, 1996, 1997, 1998 Free Software Foundation
|
||||
.\" See section COPYING for conditions for redistribution
|
||||
.TH as 1 "29 March 1996" "cygnus support" "GNU Development Tools"
|
||||
|
||||
|
@ -26,6 +26,7 @@ GNU as \- the portable GNU assembler.
|
|||
.I objfile\c
|
||||
\&\|]
|
||||
.RB "[\|" \-R "\|]"
|
||||
.RB "[\|" \-\-traditional\-format "\|]"
|
||||
.RB "[\|" \-v "\|]"
|
||||
.RB "[\|" \-w "\|]"
|
||||
.RB "[\|" \-\^\- "\ |\ " \c
|
||||
|
@ -186,6 +187,9 @@ Name the object-file output from \c
|
|||
.B \-R
|
||||
Fold data section into text section
|
||||
.TP
|
||||
.B \-\-traditional\-format
|
||||
Use same format as native assembler, when possible.
|
||||
.TP
|
||||
.B \-v
|
||||
Announce \c
|
||||
.B as\c
|
||||
|
|
378
gas/ehopt.c
Normal file
378
gas/ehopt.c
Normal file
|
@ -0,0 +1,378 @@
|
|||
/* ehopt.c--optimize gcc exception frame information.
|
||||
Copyright (C) 1998 Free Software Foundation, Inc.
|
||||
Written by Ian Lance Taylor <ian@cygnus.com>.
|
||||
|
||||
This file is part of GAS, the GNU Assembler.
|
||||
|
||||
GAS is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GAS is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
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, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA. */
|
||||
|
||||
#include "as.h"
|
||||
#include "subsegs.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
|
||||
derived from DWARF. */
|
||||
|
||||
#include "elf/dwarf2.h"
|
||||
|
||||
/* Try to optimize gcc 2.8 exception frame information.
|
||||
|
||||
Exception frame information is emitted for every function in the
|
||||
.eh_frame section. Simple information for a function with no
|
||||
exceptions looks like this:
|
||||
|
||||
__FRAME_BEGIN__:
|
||||
.4byte .LLCIE1 / Length of Common Information Entry
|
||||
.LSCIE1:
|
||||
.4byte 0x0 / CIE Identifier Tag
|
||||
.byte 0x1 / CIE Version
|
||||
.byte 0x0 / CIE Augmentation (none)
|
||||
.byte 0x1 / ULEB128 0x1 (CIE Code Alignment Factor)
|
||||
.byte 0x7c / SLEB128 -4 (CIE Data Alignment Factor)
|
||||
.byte 0x8 / CIE RA Column
|
||||
.byte 0xc / DW_CFA_def_cfa
|
||||
.byte 0x4 / ULEB128 0x4
|
||||
.byte 0x4 / ULEB128 0x4
|
||||
.byte 0x88 / DW_CFA_offset, column 0x8
|
||||
.byte 0x1 / ULEB128 0x1
|
||||
.align 4
|
||||
.LECIE1:
|
||||
.set .LLCIE1,.LECIE1-.LSCIE1 / CIE Length Symbol
|
||||
.4byte .LLFDE1 / FDE Length
|
||||
.LSFDE1:
|
||||
.4byte .LSFDE1-__FRAME_BEGIN__ / FDE CIE offset
|
||||
.4byte .LFB1 / FDE initial location
|
||||
.4byte .LFE1-.LFB1 / FDE address range
|
||||
.byte 0x4 / DW_CFA_advance_loc4
|
||||
.4byte .LCFI0-.LFB1
|
||||
.byte 0xe / DW_CFA_def_cfa_offset
|
||||
.byte 0x8 / ULEB128 0x8
|
||||
.byte 0x85 / DW_CFA_offset, column 0x5
|
||||
.byte 0x2 / ULEB128 0x2
|
||||
.byte 0x4 / DW_CFA_advance_loc4
|
||||
.4byte .LCFI1-.LCFI0
|
||||
.byte 0xd / DW_CFA_def_cfa_register
|
||||
.byte 0x5 / ULEB128 0x5
|
||||
.byte 0x4 / DW_CFA_advance_loc4
|
||||
.4byte .LCFI2-.LCFI1
|
||||
.byte 0x2e / DW_CFA_GNU_args_size
|
||||
.byte 0x4 / ULEB128 0x4
|
||||
.byte 0x4 / DW_CFA_advance_loc4
|
||||
.4byte .LCFI3-.LCFI2
|
||||
.byte 0x2e / DW_CFA_GNU_args_size
|
||||
.byte 0x0 / ULEB128 0x0
|
||||
.align 4
|
||||
.LEFDE1:
|
||||
.set .LLFDE1,.LEFDE1-.LSFDE1 / FDE Length Symbol
|
||||
|
||||
The immediate issue we can address in the assembler is the
|
||||
DW_CFA_advance_loc4 followed by a four byte value. The value is
|
||||
the difference of two addresses in the function. Since gcc does
|
||||
not know this value, it always uses four bytes. We will know the
|
||||
value at the end of assembly, so we can do better. */
|
||||
|
||||
static int eh_frame_code_alignment PARAMS ((void));
|
||||
|
||||
/* Get the code alignment factor from the CIE. */
|
||||
|
||||
static int
|
||||
eh_frame_code_alignment ()
|
||||
{
|
||||
static int code_alignment;
|
||||
segT current_seg;
|
||||
subsegT current_subseg;
|
||||
fragS *f;
|
||||
int offset;
|
||||
|
||||
if (code_alignment != 0)
|
||||
return code_alignment;
|
||||
|
||||
/* We should find the CIE at the start of the .eh_frame section. */
|
||||
|
||||
current_seg = now_seg;
|
||||
current_subseg = now_subseg;
|
||||
subseg_new (".eh_frame", 0);
|
||||
f = seg_info (now_seg)->frchainP->frch_root;
|
||||
subseg_set (current_seg, current_subseg);
|
||||
|
||||
/* Look through the frags of the section to find the code alignment. */
|
||||
|
||||
/* First make sure that the CIE Identifier Tag is 0. */
|
||||
|
||||
offset = 4;
|
||||
while (f != NULL && offset >= f->fr_fix)
|
||||
{
|
||||
offset -= f->fr_fix;
|
||||
f = f->fr_next;
|
||||
}
|
||||
if (f == NULL
|
||||
|| f->fr_fix - offset < 4
|
||||
|| f->fr_literal[offset] != 0
|
||||
|| f->fr_literal[offset + 1] != 0
|
||||
|| f->fr_literal[offset + 2] != 0
|
||||
|| f->fr_literal[offset + 3] != 0)
|
||||
{
|
||||
code_alignment = -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Next make sure the CIE version number is 1. */
|
||||
|
||||
offset += 4;
|
||||
while (f != NULL && offset >= f->fr_fix)
|
||||
{
|
||||
offset -= f->fr_fix;
|
||||
f = f->fr_next;
|
||||
}
|
||||
if (f == NULL
|
||||
|| f->fr_fix - offset < 1
|
||||
|| f->fr_literal[offset] != 1)
|
||||
{
|
||||
code_alignment = -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Skip the augmentation (a null terminated string). */
|
||||
|
||||
++offset;
|
||||
while (1)
|
||||
{
|
||||
while (f != NULL && offset >= f->fr_fix)
|
||||
{
|
||||
offset -= f->fr_fix;
|
||||
f = f->fr_next;
|
||||
}
|
||||
if (f == NULL)
|
||||
{
|
||||
code_alignment = -1;
|
||||
return -1;
|
||||
}
|
||||
while (offset < f->fr_fix && f->fr_literal[offset] != '\0')
|
||||
++offset;
|
||||
if (offset < f->fr_fix)
|
||||
break;
|
||||
}
|
||||
++offset;
|
||||
while (f != NULL && offset >= f->fr_fix)
|
||||
{
|
||||
offset -= f->fr_fix;
|
||||
f = f->fr_next;
|
||||
}
|
||||
if (f == NULL)
|
||||
{
|
||||
code_alignment = -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* We're now at the code alignment factor, which is a ULEB128. If
|
||||
it isn't a single byte, forget it. */
|
||||
|
||||
code_alignment = f->fr_literal[offset] & 0xff;
|
||||
if ((code_alignment & 0x80) != 0 || code_alignment == 0)
|
||||
{
|
||||
code_alignment = -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return code_alignment;
|
||||
}
|
||||
|
||||
/* This function is called from emit_expr. It looks for cases which
|
||||
we can optimize.
|
||||
|
||||
Rather than try to parse all this information as we read it, we
|
||||
look for a single byte DW_CFA_advance_loc4 followed by a 4 byte
|
||||
difference. We turn that into a rs_cfa_advance frag, and handle
|
||||
those frags at the end of the assembly. If the gcc output changes
|
||||
somewhat, this optimization may stop working.
|
||||
|
||||
This function returns non-zero if it handled the expression and
|
||||
emit_expr should not do anything, or zero otherwise. It can also
|
||||
change *EXP and *PNBYTES. */
|
||||
|
||||
int
|
||||
check_eh_frame (exp, pnbytes)
|
||||
expressionS *exp;
|
||||
unsigned int *pnbytes;
|
||||
{
|
||||
static int saw_advance_loc4;
|
||||
static fragS *loc4_frag;
|
||||
static int loc4_fix;
|
||||
|
||||
if (flag_traditional_format)
|
||||
{
|
||||
/* Don't optimize. */
|
||||
}
|
||||
else if (strcmp (segment_name (now_seg), ".eh_frame") != 0)
|
||||
saw_advance_loc4 = 0;
|
||||
else if (*pnbytes == 1
|
||||
&& exp->X_op == O_constant
|
||||
&& exp->X_add_number == DW_CFA_advance_loc4)
|
||||
{
|
||||
/* This might be a DW_CFA_advance_loc4. Record the frag and the
|
||||
position within the frag, so that we can change it later. */
|
||||
saw_advance_loc4 = 1;
|
||||
frag_grow (1);
|
||||
loc4_frag = frag_now;
|
||||
loc4_fix = frag_now_fix ();
|
||||
}
|
||||
else if (saw_advance_loc4
|
||||
&& *pnbytes == 4
|
||||
&& exp->X_op == O_constant)
|
||||
{
|
||||
int ca;
|
||||
|
||||
/* This is a case which we can optimize. The two symbols being
|
||||
subtracted were in the same frag and the expression was
|
||||
reduced to a constant. We can do the optimization entirely
|
||||
in this function. */
|
||||
|
||||
saw_advance_loc4 = 0;
|
||||
|
||||
ca = eh_frame_code_alignment ();
|
||||
if (ca < 0)
|
||||
{
|
||||
/* Don't optimize. */
|
||||
}
|
||||
else if (exp->X_add_number % ca == 0
|
||||
&& exp->X_add_number / ca < 0x40)
|
||||
{
|
||||
loc4_frag->fr_literal[loc4_fix]
|
||||
= DW_CFA_advance_loc | (exp->X_add_number / ca);
|
||||
/* No more bytes needed. */
|
||||
return 1;
|
||||
}
|
||||
else if (exp->X_add_number < 0x100)
|
||||
{
|
||||
loc4_frag->fr_literal[loc4_fix] = DW_CFA_advance_loc1;
|
||||
*pnbytes = 1;
|
||||
}
|
||||
else if (exp->X_add_number < 0x10000)
|
||||
{
|
||||
loc4_frag->fr_literal[loc4_fix] = DW_CFA_advance_loc2;
|
||||
*pnbytes = 2;
|
||||
}
|
||||
}
|
||||
else if (saw_advance_loc4
|
||||
&& *pnbytes == 4
|
||||
&& exp->X_op == O_subtract)
|
||||
{
|
||||
|
||||
/* 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. */
|
||||
|
||||
saw_advance_loc4 = 0;
|
||||
|
||||
frag_var (rs_cfa, 4, 0, 0, make_expr_symbol (exp),
|
||||
loc4_fix, (char *) loc4_frag);
|
||||
}
|
||||
else
|
||||
saw_advance_loc4 = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The function estimates the size of a rs_cfa variant frag based on
|
||||
the current values of the symbols. It is called before the
|
||||
relaxation loop. We set fr_subtype to the expected length. */
|
||||
|
||||
int
|
||||
eh_frame_estimate_size_before_relax (frag)
|
||||
fragS *frag;
|
||||
{
|
||||
int ca;
|
||||
offsetT diff;
|
||||
int ret;
|
||||
|
||||
ca = eh_frame_code_alignment ();
|
||||
diff = resolve_symbol_value (frag->fr_symbol, 0);
|
||||
|
||||
if (ca < 0)
|
||||
ret = 4;
|
||||
else if (diff % ca == 0 && diff / ca < 0x40)
|
||||
ret = 0;
|
||||
else if (diff < 0x100)
|
||||
ret = 1;
|
||||
else if (diff < 0x10000)
|
||||
ret = 2;
|
||||
else
|
||||
ret = 4;
|
||||
|
||||
frag->fr_subtype = ret;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* This function relaxes a rs_cfa variant frag based on the current
|
||||
values of the symbols. fr_subtype is the current length of the
|
||||
frag. This returns the change in frag length. */
|
||||
|
||||
int
|
||||
eh_frame_relax_frag (frag)
|
||||
fragS *frag;
|
||||
{
|
||||
int oldsize, newsize;
|
||||
|
||||
oldsize = frag->fr_subtype;
|
||||
newsize = eh_frame_estimate_size_before_relax (frag);
|
||||
return newsize - oldsize;
|
||||
}
|
||||
|
||||
/* This function converts a rs_cfa variant frag into a normal fill
|
||||
frag. This is called after all relaxation has been done.
|
||||
fr_subtype will be the desired length of the frag. */
|
||||
|
||||
void
|
||||
eh_frame_convert_frag (frag)
|
||||
fragS *frag;
|
||||
{
|
||||
offsetT diff;
|
||||
fragS *loc4_frag;
|
||||
int loc4_fix;
|
||||
|
||||
loc4_frag = (fragS *) frag->fr_opcode;
|
||||
loc4_fix = (int) frag->fr_offset;
|
||||
|
||||
diff = resolve_symbol_value (frag->fr_symbol, 1);
|
||||
|
||||
if (frag->fr_subtype == 0)
|
||||
{
|
||||
int ca;
|
||||
|
||||
ca = eh_frame_code_alignment ();
|
||||
assert (ca > 0 && diff % ca == 0 && diff / ca < 0x40);
|
||||
loc4_frag->fr_literal[loc4_fix] = DW_CFA_advance_loc | (diff / ca);
|
||||
}
|
||||
else if (frag->fr_subtype == 1)
|
||||
{
|
||||
assert (diff < 0x100);
|
||||
loc4_frag->fr_literal[loc4_fix] = DW_CFA_advance_loc1;
|
||||
frag->fr_literal[frag->fr_fix] = diff;
|
||||
}
|
||||
else if (frag->fr_subtype == 2)
|
||||
{
|
||||
assert (diff < 0x10000);
|
||||
loc4_frag->fr_literal[loc4_fix] = DW_CFA_advance_loc2;
|
||||
md_number_to_chars (frag->fr_literal + frag->fr_fix, diff, 2);
|
||||
}
|
||||
else
|
||||
md_number_to_chars (frag->fr_literal + frag->fr_fix, diff, 4);
|
||||
|
||||
frag->fr_fix += frag->fr_subtype;
|
||||
frag->fr_type = rs_fill;
|
||||
}
|
Loading…
Reference in a new issue