[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
PATCH: fix incorrect PC-relative relocations with '.word'
From: |
Mat Hostetter |
Subject: |
PATCH: fix incorrect PC-relative relocations with '.word' |
Date: |
11 Nov 2008 15:23:10 -0500 |
This is for gas 2.18, but it looks like the same bug is present in 2.19.
emit_expr, used by '.word' and others, grabs dot_value for the current
frag, does some processing, and later calls frag_more. Unfortunately,
the frag_more call can realize the frag is not big enough and switch
to a new frag. That's bad because the dot_value already recorded an
offset into the old frag, which is completely wrong for the new frag.
The result is that you can get PC-relative relocations with incorrect
offsets if they happen to span the byte boundary where a frag fills
up. I saw this with a PC-relative relocation at a large odd byte
offset, which is probably the only time this can happen. Unaligned
PC-relative offsets are an unusual case, which is why this probably
hasn't been reported before.
My fix is simply to reserve enough space before calling frag_now_fix
that the frag won't run out of room if frag_more is called later.
--- gas/read.c~ 2008-08-18 12:56:22.864271000 -0400
+++ gas/read.c 2008-11-11 15:00:33.487833000 -0500
@@ -3891,30 +3891,33 @@
/* Put the contents of expression EXP into the object file using
NBYTES bytes. If need_pass_2 is 1, this does nothing. */
void
emit_expr (expressionS *exp, unsigned int nbytes)
{
operatorT op;
register char *p;
valueT extra_digit = 0;
/* Don't do anything if we are going to make another pass. */
if (need_pass_2)
return;
+ /* Grow the current frag now so that dot_value does not get invalidated
+ if the frag were to fill up in the frag_more() call below. */
+ frag_grow (nbytes);
dot_value = frag_now_fix ();
#ifndef NO_LISTING
#ifdef OBJ_ELF
/* When gcc emits DWARF 1 debugging pseudo-ops, a line number will
appear as a four byte positive constant in the .line section,
followed by a 2 byte 0xffff. Look for that case here. */
{
static int dwarf_line = -1;
if (strcmp (segment_name (now_seg), ".line") != 0)
dwarf_line = -1;
else if (dwarf_line >= 0
&& nbytes == 2
&& exp->X_op == O_constant
- PATCH: fix incorrect PC-relative relocations with '.word',
Mat Hostetter <=