aboutsummaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@airs.com>1998-02-06 06:54:01 +0000
committerIan Lance Taylor <ian@airs.com>1998-02-06 06:54:01 +0000
commit1430b6ed3a210ad84f4534340e228e31b138b163 (patch)
tree8130617f5a5c800f2662868d980ee2ddd7915815 /gas
parent9961ca7ab5d24d4b80206aeee50c7aea5a741824 (diff)
downloadgdb-1430b6ed3a210ad84f4534340e228e31b138b163.zip
gdb-1430b6ed3a210ad84f4534340e228e31b138b163.tar.gz
gdb-1430b6ed3a210ad84f4534340e228e31b138b163.tar.bz2
improvements
Diffstat (limited to 'gas')
-rw-r--r--gas/ehopt.c51
1 files changed, 49 insertions, 2 deletions
diff --git a/gas/ehopt.c b/gas/ehopt.c
index d339a30..efc9337 100644
--- a/gas/ehopt.c
+++ b/gas/ehopt.c
@@ -95,7 +95,9 @@ eh_frame_code_alignment ()
segT current_seg;
subsegT current_subseg;
fragS *f;
+ fixS *fix;
int offset;
+ int eh_state;
if (code_alignment != 0)
return code_alignment;
@@ -106,6 +108,7 @@ eh_frame_code_alignment ()
current_subseg = now_subseg;
subseg_new (".eh_frame", 0);
f = seg_info (now_seg)->frchainP->frch_root;
+ fix = seg_info (now_seg)->frchainP->fix_root;
subseg_set (current_seg, current_subseg);
/* Look through the frags of the section to find the code alignment. */
@@ -148,6 +151,7 @@ eh_frame_code_alignment ()
/* Skip the augmentation (a null terminated string). */
++offset;
+ eh_state = 0;
while (1)
{
while (f != NULL && offset >= f->fr_fix)
@@ -161,7 +165,23 @@ eh_frame_code_alignment ()
return -1;
}
while (offset < f->fr_fix && f->fr_literal[offset] != '\0')
- ++offset;
+ {
+ switch (eh_state)
+ {
+ case 0:
+ if (f->fr_literal[offset] == 'e')
+ eh_state = 1;
+ break;
+ case 1:
+ if (f->fr_literal[offset] == 'h')
+ eh_state = 2;
+ break;
+ default:
+ eh_state = 3;
+ break;
+ }
+ ++offset;
+ }
if (offset < f->fr_fix)
break;
}
@@ -177,6 +197,30 @@ eh_frame_code_alignment ()
return -1;
}
+ /* If the augmentation field is "eh", then we have to skip a
+ pointer. Unfortunately, we don't know how large it is. We find
+ out by looking for a matching fixup. */
+ if (eh_state == 2)
+ {
+ while (fix != NULL
+ && (fix->fx_frag != f || fix->fx_where != offset))
+ fix = fix->fx_next;
+ if (fix == NULL)
+ offset += 4;
+ else
+ offset += fix->fx_size;
+ 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. */
@@ -248,7 +292,7 @@ check_eh_frame (exp, pnbytes)
/* Don't optimize. */
}
else if (exp->X_add_number % ca == 0
- && exp->X_add_number / ca < 0x40)
+ && exp->X_add_number / ca < 0x40)
{
loc4_frag->fr_literal[loc4_fix]
= DW_CFA_advance_loc | (exp->X_add_number / ca);
@@ -280,6 +324,8 @@ check_eh_frame (exp, pnbytes)
frag_var (rs_cfa, 4, 0, 0, make_expr_symbol (exp),
loc4_fix, (char *) loc4_frag);
+
+ return 1;
}
else
saw_advance_loc4 = 0;
@@ -375,4 +421,5 @@ eh_frame_convert_frag (frag)
frag->fr_fix += frag->fr_subtype;
frag->fr_type = rs_fill;
+ frag->fr_offset = 0;
}