static struct frag *bss_last_frag; /* Last frag in segment. */
#endif
+#if ! defined (BFD_ASSEMBLER) && ! defined (BFD)
static object_headers headers;
-long string_byte_count;
static char *the_object_file;
+#endif
+
+long string_byte_count;
char *next_object_file_charP; /* Tracks object file bytes. */
#ifndef OBJ_VMS
#endif /* BFD_ASSEMBLER */
+#ifdef BFD_ASSEMBLER
+static fixS *fix_new_internal PARAMS ((fragS *, int where, int size,
+ symbolS *add, symbolS *sub,
+ offsetT offset, int pcrel,
+ bfd_reloc_code_real_type r_type));
+#else
+static fixS *fix_new_internal PARAMS ((fragS *, int where, int size,
+ symbolS *add, symbolS *sub,
+ offsetT offset, int pcrel,
+ int r_type));
+#endif
+#if defined (BFD_ASSEMBLER) || !defined (BFD)
static long fixup_segment PARAMS ((fixS * fixP, segT this_segment_type));
+#endif
static relax_addressT relax_align PARAMS ((relax_addressT addr, int align));
-void relax_segment PARAMS ((struct frag * seg_frag_root, segT seg_type));
/*
* fix_new()
*
* Create a fixS in obstack 'notes'.
*/
-fixS *
-fix_new (frag, where, size, add_symbol, sub_symbol, offset, pcrel, r_type)
+static fixS *
+fix_new_internal (frag, where, size, add_symbol, sub_symbol, offset, pcrel,
+ r_type)
fragS *frag; /* Which frag? */
int where; /* Where in that frag? */
- short int size; /* 1, 2, or 4 usually. */
+ int size; /* 1, 2, or 4 usually. */
symbolS *add_symbol; /* X_add_symbol. */
- symbolS *sub_symbol; /* X_subtract_symbol. */
+ symbolS *sub_symbol; /* X_op_symbol. */
offsetT offset; /* X_add_number. */
int pcrel; /* TRUE if PC-relative relocation. */
#ifdef BFD_ASSEMBLER
fixP->fx_callj = 0;
#endif
+ as_where (&fixP->fx_file, &fixP->fx_line);
+
/* Usually, we want relocs sorted numerically, but while
comparing to older versions of gas that have relocs
reverse sorted, it is convenient to have this compile
return fixP;
}
+/* Create a fixup relative to a symbol (plus a constant). */
+
+fixS *
+fix_new (frag, where, size, add_symbol, offset, pcrel, r_type)
+ fragS *frag; /* Which frag? */
+ int where; /* Where in that frag? */
+ short int size; /* 1, 2, or 4 usually. */
+ symbolS *add_symbol; /* X_add_symbol. */
+ offsetT offset; /* X_add_number. */
+ int pcrel; /* TRUE if PC-relative relocation. */
+#ifdef BFD_ASSEMBLER
+ bfd_reloc_code_real_type r_type; /* Relocation type */
+#else
+ int r_type; /* Relocation type */
+#endif
+{
+ return fix_new_internal (frag, where, size, add_symbol,
+ (symbolS *) NULL, offset, pcrel, r_type);
+}
+
+/* Create a fixup for an expression. Currently we only support fixups
+ for difference expressions. That is itself more than most object
+ file formats support anyhow. */
+
+fixS *
+fix_new_exp (frag, where, size, exp, pcrel, r_type)
+ fragS *frag; /* Which frag? */
+ int where; /* Where in that frag? */
+ short int size; /* 1, 2, or 4 usually. */
+ expressionS *exp; /* Expression. */
+ int pcrel; /* TRUE if PC-relative relocation. */
+#ifdef BFD_ASSEMBLER
+ bfd_reloc_code_real_type r_type; /* Relocation type */
+#else
+ int r_type; /* Relocation type */
+#endif
+{
+ symbolS *add = NULL;
+ symbolS *sub = NULL;
+ offsetT off = 0;
+
+ switch (exp->X_op)
+ {
+ case O_absent:
+ break;
+
+ case O_uminus:
+ sub = exp->X_add_symbol;
+ off = exp->X_add_number;
+ break;
+
+ case O_subtract:
+ sub = exp->X_op_symbol;
+ /* Fall through. */
+ case O_symbol:
+ add = exp->X_add_symbol;
+ /* Fall through. */
+ case O_constant:
+ off = exp->X_add_number;
+ break;
+
+ default:
+ as_bad ("expression too complex for fixup");
+ }
+
+ return fix_new_internal (frag, where, size, add, sub, off,
+ pcrel, r_type);
+}
+
/* Append a string onto another string, bumping the pointer along. */
void
append (charPP, fromP, length)
if (length == 0)
return;
- memcpy (*charPP, fromP, (int) length);
+ memcpy (*charPP, fromP, length);
*charPP += length;
}
#endif /* BFD */
-static void
-cvt_frag_to_fill (x, fragP)
+#if defined (BFD_ASSEMBLER) || !defined (BFD)
+
#ifdef BFD_ASSEMBLER
- segT x;
-#else
- object_headers *x;
-#endif
+static void
+cvt_frag_to_fill (sec, fragP)
+ segT sec;
fragS *fragP;
-{
-#ifdef BFD_ASSEMBLER
- segT sec = x;
#else
- object_headers *headers = x;
+static void
+cvt_frag_to_fill (headers, fragP)
+ object_headers *headers;
+ fragS *fragP;
#endif
-
+{
switch (fragP->fr_type)
{
case rs_align:
}
}
+#endif /* defined (BFD_ASSEMBLER) || !defined (BFD) */
+
#ifdef BFD_ASSEMBLER
static void
relax_and_size_seg (abfd, sec, xxx)
char *xxx;
{
flagword flags;
+ fragS *fragp;
+ segment_info_type *seginfo;
+ int x;
+ valueT size, newsize;
flags = bfd_get_section_flags (abfd, sec);
- if (/*flags & SEC_ALLOC*/ 1)
+ seginfo = (segment_info_type *) bfd_get_section_userdata (abfd, sec);
+ if (seginfo && seginfo->frchainP)
{
- fragS *fragp;
- segment_info_type *seginfo;
- int x;
- valueT size, newsize;
-
- seginfo = (segment_info_type *) bfd_get_section_userdata (abfd, sec);
- if (seginfo && seginfo->frchainP)
- {
- relax_segment (seginfo->frchainP->frch_root, sec);
- for (fragp = seginfo->frchainP->frch_root; fragp; fragp = fragp->fr_next)
- cvt_frag_to_fill (sec, fragp);
- for (fragp = seginfo->frchainP->frch_root;
- fragp->fr_next;
- fragp = fragp->fr_next)
- /* walk to last elt */;
- size = fragp->fr_address + fragp->fr_fix;
- }
+ relax_segment (seginfo->frchainP->frch_root, sec);
+ for (fragp = seginfo->frchainP->frch_root; fragp; fragp = fragp->fr_next)
+ cvt_frag_to_fill (sec, fragp);
+ for (fragp = seginfo->frchainP->frch_root;
+ fragp->fr_next;
+ fragp = fragp->fr_next)
+ /* walk to last elt */;
+ size = fragp->fr_address + fragp->fr_fix;
+ }
+ else
+ size = 0;
+ if (size > 0)
+ {
+ flags |= SEC_HAS_CONTENTS;
+ /* @@ This is just an approximation. */
+ if (seginfo->fix_root)
+ flags |= SEC_RELOC;
else
- size = 0;
- if (size > 0)
- {
- flags |= SEC_HAS_CONTENTS;
- /* @@ This is just an approximation. */
- if (seginfo->fix_root)
- flags |= SEC_RELOC;
- else
- flags &= ~SEC_RELOC;
- x = bfd_set_section_flags (abfd, sec, flags);
- assert (x == true);
- }
- size = md_section_align (sec, size);
- x = bfd_set_section_size (abfd, sec, size);
+ flags &= ~SEC_RELOC;
+ x = bfd_set_section_flags (abfd, sec, flags);
assert (x == true);
-
- /* If the size had to be rounded up, add some padding in the last
- non-empty frag. */
- newsize = bfd_get_section_size_before_reloc (sec);
- assert (newsize >= size);
- if (size != newsize)
- {
- fragS *last = seginfo->frchainP->frch_last;
- fragp = seginfo->frchainP->frch_root;
- while (fragp->fr_next != last)
- fragp = fragp->fr_next;
- last->fr_address = size;
- fragp->fr_offset += newsize - size;
- }
}
+ size = md_section_align (sec, size);
+ x = bfd_set_section_size (abfd, sec, size);
+ assert (x == true);
+
+ /* If the size had to be rounded up, add some padding in the last
+ non-empty frag. */
+ newsize = bfd_get_section_size_before_reloc (sec);
+ assert (newsize >= size);
+ if (size != newsize)
+ {
+ fragS *last = seginfo->frchainP->frch_last;
+ fragp = seginfo->frchainP->frch_root;
+ while (fragp->fr_next != last)
+ fragp = fragp->fr_next;
+ last->fr_address = size;
+ fragp->fr_offset += newsize - size;
+ }
+
#ifdef tc_frob_section
tc_frob_section (sec);
#endif
if (symsec == &bfd_und_section
|| symsec == &bfd_abs_section
|| bfd_is_com_section (symsec))
- continue;
+ {
+ fixp->fx_addsy->sy_used_in_reloc = 1;
+ continue;
+ }
/* Since we're reducing to section symbols, don't attempt to reduce
anything that's already using one. */
if (sym->bsym == symsec->symbol)
- continue;
+ {
+ fixp->fx_addsy->sy_used_in_reloc = 1;
+ continue;
+ }
/* Is there some other reason we can't adjust this one? (E.g.,
call/bal links in i960-bout symbols.) */
#ifdef obj_fix_adjustable
if (! obj_fix_adjustable (fixp))
+ {
+ fixp->fx_addsy->sy_used_in_reloc = 1;
+ continue;
+ }
+#endif
+
+ /* Is there some other (target cpu dependent) reason we can't adjust
+ this one? (E.g. relocations involving function addresses on
+ the PA. */
+#ifdef tc_fix_adjustable
+ if (! tc_fix_adjustable (fixp))
continue;
#endif
+
/* If the section symbol isn't going to be output, the relocs
at least should still work. If not, figure out what to do
when we run into that case. */
}
symseginfo->sym = fixp->fx_addsy;
}
+ fixp->fx_addsy->sy_used_in_reloc = 1;
}
dump_section_relocs (abfd, sec, stderr);
}
static void
-write_contents (abfd, sec, xxx)
+write_relocs (abfd, sec, xxx)
bfd *abfd;
asection *sec;
char *xxx;
{
segment_info_type *seginfo = seg_info (sec);
- unsigned long offset = 0;
- fragS *frags;
- int i, n;
+ int i;
+ unsigned int n;
arelent **relocs;
fixS *fixp;
/* Set up reloc information as well. */
relocs = (arelent **) bfd_alloc_by_size_t (stdoutput,
n * sizeof (arelent *));
- bzero ((char*)relocs, n * sizeof (arelent*));
+ memset ((char*)relocs, 0, n * sizeof (arelent*));
i = 0;
for (fixp = seginfo->fix_root; fixp != (fixS *) NULL; fixp = fixp->fx_next)
{
arelent *reloc;
- extern arelent *tc_gen_reloc ();
char *data;
bfd_reloc_status_type s;
continue;
}
data = fixp->fx_frag->fr_literal + fixp->fx_where;
+ /* @@ Assumes max size of reloc is 4. */
if (fixp->fx_where + 4
> fixp->fx_frag->fr_fix + fixp->fx_frag->fr_offset)
abort ();
/* Pass bogus address so that when bfd_perform_relocation adds
`address' back in, it'll come up with `data', which is where
we want it to operate. */
+ if (reloc->howto->partial_inplace == false
+ && reloc->howto->pcrel_offset == true
+ && reloc->howto->pc_relative == true)
+ {
+ /* bfd_perform_relocation screws this up */
+ reloc->addend += reloc->address;
+ }
s = bfd_perform_relocation (stdoutput, reloc, data - reloc->address,
sec, stdoutput);
switch (s)
for (fixp = seginfo->fix_root; fixp != (fixS *) NULL; fixp = fixp->fx_next)
{
arelent **reloc;
- extern arelent *tc_gen_reloc ();
char *data;
bfd_reloc_status_type s;
int j;
bfd_set_reloc (stdoutput, sec, relocs, n);
else
bfd_set_section_flags (abfd, sec,
- bfd_get_section_flags (abfd, sec) & ~SEC_RELOC);
+ (bfd_get_section_flags (abfd, sec)
+ & (flagword) ~SEC_RELOC));
#ifdef DEBUG2
{
int i;
}
}
#endif
+}
- /* Force calculations (size, vma) to get done. */
- bfd_set_section_contents (stdoutput, sec, "", 0, (addressT) 0);
+static void
+write_contents (abfd, sec, xxx)
+ bfd *abfd;
+ asection *sec;
+ char *xxx;
+{
+ segment_info_type *seginfo = seg_info (sec);
+ unsigned long offset = 0;
+ fragS *f;
/* Write out the frags. */
- if (! (bfd_get_section_flags (abfd, sec) & SEC_HAS_CONTENTS))
+ if (seginfo == NULL
+ || ! (bfd_get_section_flags (abfd, sec) & SEC_HAS_CONTENTS))
return;
- for (frags = seginfo->frchainP->frch_root;
- frags;
- frags = frags->fr_next)
+ for (f = seginfo->frchainP->frch_root;
+ f;
+ f = f->fr_next)
{
int x;
unsigned long fill_size;
char *fill_literal;
long count;
- assert (frags->fr_type == rs_fill);
- if (frags->fr_fix)
+ assert (f->fr_type == rs_fill);
+ if (f->fr_fix)
{
x = bfd_set_section_contents (stdoutput, sec,
- frags->fr_literal, offset,
- frags->fr_fix);
+ f->fr_literal, (file_ptr) offset,
+ (bfd_size_type) f->fr_fix);
assert (x == true);
- offset += frags->fr_fix;
+ offset += f->fr_fix;
}
- fill_literal = frags->fr_literal + frags->fr_fix;
- fill_size = frags->fr_var;
- count = frags->fr_offset;
+ fill_literal = f->fr_literal + f->fr_fix;
+ fill_size = f->fr_var;
+ count = f->fr_offset;
assert (count >= 0);
if (fill_size && count)
while (count--)
{
x = bfd_set_section_contents (stdoutput, sec,
- fill_literal, offset,
+ fill_literal, (file_ptr) offset,
(bfd_size_type) fill_size);
assert (x == true);
offset += fill_size;
}
#endif
+#if defined(BFD_ASSEMBLER) || (!defined (BFD) && !defined(OBJ_AOUT))
+static void
+merge_data_into_text ()
+{
+#if defined(BFD_ASSEMBLER) || defined(MANY_SEGMENTS)
+ seg_info (text_section)->frchainP->frch_last->fr_next =
+ seg_info (data_section)->frchainP->frch_root;
+ seg_info (text_section)->frchainP->frch_last =
+ seg_info (data_section)->frchainP->frch_last;
+ seg_info (data_section)->frchainP = 0;
+#else
+ fixS *tmp;
+
+ text_last_frag->fr_next = data_frag_root;
+ text_last_frag = data_last_frag;
+ data_last_frag = NULL;
+ data_frag_root = NULL;
+ if (text_fix_root)
+ {
+ for (tmp = text_fix_root; tmp->fx_next; tmp = tmp->fx_next);;
+ tmp->fx_next = data_fix_root;
+ text_fix_tail = data_fix_tail;
+ }
+ else
+ text_fix_root = data_fix_root;
+ data_fix_root = NULL;
+#endif
+}
+#endif /* BFD_ASSEMBLER || (! BFD && ! OBJ_AOUT) */
+
+#if !defined (BFD_ASSEMBLER) && !defined (BFD)
+static void
+relax_and_size_all_segments ()
+{
+ fragS *fragP;
+
+ relax_segment (text_frag_root, SEG_TEXT);
+ relax_segment (data_frag_root, SEG_DATA);
+ relax_segment (bss_frag_root, SEG_BSS);
+ /*
+ * Now the addresses of frags are correct within the segment.
+ */
+
+ know (text_last_frag->fr_type == rs_fill && text_last_frag->fr_offset == 0);
+ H_SET_TEXT_SIZE (&headers, text_last_frag->fr_address);
+ text_last_frag->fr_address = H_GET_TEXT_SIZE (&headers);
+
+ /*
+ * Join the 2 segments into 1 huge segment.
+ * To do this, re-compute every rn_address in the SEG_DATA frags.
+ * Then join the data frags after the text frags.
+ *
+ * Determine a_data [length of data segment].
+ */
+ if (data_frag_root)
+ {
+ register relax_addressT slide;
+
+ know ((text_last_frag->fr_type == rs_fill) && (text_last_frag->fr_offset == 0));
+
+ H_SET_DATA_SIZE (&headers, data_last_frag->fr_address);
+ data_last_frag->fr_address = H_GET_DATA_SIZE (&headers);
+ slide = H_GET_TEXT_SIZE (&headers); /* & in file of the data segment. */
+#ifdef OBJ_BOUT
+#define RoundUp(N,S) (((N)+(S)-1)&-(S))
+ /* For b.out: If the data section has a strict alignment
+ requirement, its load address in the .o file will be
+ rounded up from the size of the text section. These
+ two values are *not* the same! Similarly for the bss
+ section.... */
+ slide = RoundUp (slide, 1 << section_alignment[SEG_DATA]);
+#endif
+
+ for (fragP = data_frag_root; fragP; fragP = fragP->fr_next)
+ {
+ fragP->fr_address += slide;
+ } /* for each data frag */
+
+ know (text_last_frag != 0);
+ text_last_frag->fr_next = data_frag_root;
+ }
+ else
+ {
+ H_SET_DATA_SIZE (&headers, 0);
+ }
+
+#ifdef OBJ_BOUT
+ /* See above comments on b.out data section address. */
+ {
+ long bss_vma;
+ if (data_last_frag == 0)
+ bss_vma = H_GET_TEXT_SIZE (&headers);
+ else
+ bss_vma = data_last_frag->fr_address;
+ bss_vma = RoundUp (bss_vma, 1 << section_alignment[SEG_BSS]);
+ bss_address_frag.fr_address = bss_vma;
+ }
+#else /* ! OBJ_BOUT */
+ bss_address_frag.fr_address = (H_GET_TEXT_SIZE (&headers) +
+ H_GET_DATA_SIZE (&headers));
+
+#endif /* ! OBJ_BOUT */
+
+ /* Slide all the frags */
+ if (bss_frag_root)
+ {
+ relax_addressT slide = bss_address_frag.fr_address;
+
+ for (fragP = bss_frag_root; fragP; fragP = fragP->fr_next)
+ {
+ fragP->fr_address += slide;
+ } /* for each bss frag */
+ }
+
+ if (bss_last_frag)
+ H_SET_BSS_SIZE (&headers,
+ bss_last_frag->fr_address - bss_frag_root->fr_address);
+ else
+ H_SET_BSS_SIZE (&headers, 0);
+}
+#endif /* ! BFD_ASSEMBLER && ! BFD */
+
#if defined (BFD_ASSEMBLER) || !defined (BFD)
void
write_object_file ()
{
register struct frchain *frchainP; /* Track along all frchains. */
+#if ! defined (BFD_ASSEMBLER) || ! defined (WORKING_DOT_WORD)
register fragS *fragP; /* Track along all frags. */
-
+#endif
#if !defined (BFD_ASSEMBLER) && !defined (OBJ_VMS)
long object_file_size;
#endif
#endif
for (frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next)
{
-#ifdef BFD_ASSEMBLER
subseg_set (frchainP->frch_seg, frchainP->frch_subseg);
-#else
- subseg_new (frchainP->frch_seg, frchainP->frch_subseg);
-#endif
frag_align (SUB_SEGMENT_ALIGN (now_seg), NOP_OPCODE);
/* frag_align will have left a new frag.
Use this last frag for an empty ".fill".
frag_wane (frag_now);
frag_now->fr_fix = 0;
know (frag_now->fr_next == NULL);
- /* know( frags . obstack_c_base == frags . obstack_c_next_free ); */
- /* Above shows we haven't left a half-completed object on obstack. */
}
/* From now on, we don't care about sub-segments. Build one frag chain
while (seclist && *seclist)
{
sec = *seclist;
- while (sec == big_section
- || sec == reg_section
- || sec == pass1_section
- || sec == diff_section
- || sec == absent_section)
+ while (sec == reg_section || sec == expr_section)
{
sec = sec->next;
*seclist = sec;
#if !defined (OBJ_AOUT) || defined (BFD_ASSEMBLER)
if (flagseen['R'])
{
-#ifdef BFD_ASSEMBLER
- seg_info (text_section)->frchainP->frch_last->fr_next =
- seg_info (data_section)->frchainP->frch_root;
- seg_info (text_section)->frchainP->frch_last =
- seg_info (data_section)->frchainP->frch_last;
- seg_info (data_section)->frchainP = 0;
-#else
- fixS *tmp;
-
- text_last_frag->fr_next = data_frag_root;
- text_last_frag = data_last_frag;
- data_last_frag = NULL;
- data_frag_root = NULL;
- if (text_fix_root)
- {
- for (tmp = text_fix_root; tmp->fx_next; tmp = tmp->fx_next);;
- tmp->fx_next = data_fix_root;
- text_fix_tail = data_fix_tail;
- }
- else
- text_fix_root = data_fix_root;
- data_fix_root = NULL;
-#endif
+ merge_data_into_text ();
}
#endif
#ifdef BFD_ASSEMBLER
-
bfd_map_over_sections (stdoutput, relax_and_size_seg, (char *) 0);
#else
- relax_segment (text_frag_root, SEG_TEXT);
- relax_segment (data_frag_root, SEG_DATA);
- relax_segment (bss_frag_root, SEG_BSS);
- /*
- * Now the addresses of frags are correct within the segment.
- */
-
- know (text_last_frag->fr_type == rs_fill && text_last_frag->fr_offset == 0);
- H_SET_TEXT_SIZE (&headers, text_last_frag->fr_address);
- text_last_frag->fr_address = H_GET_TEXT_SIZE (&headers);
-
- /*
- * Join the 2 segments into 1 huge segment.
- * To do this, re-compute every rn_address in the SEG_DATA frags.
- * Then join the data frags after the text frags.
- *
- * Determine a_data [length of data segment].
- */
- if (data_frag_root)
- {
- register relax_addressT slide;
-
- know ((text_last_frag->fr_type == rs_fill) && (text_last_frag->fr_offset == 0));
-
- H_SET_DATA_SIZE (&headers, data_last_frag->fr_address);
- data_last_frag->fr_address = H_GET_DATA_SIZE (&headers);
- slide = H_GET_TEXT_SIZE (&headers); /* & in file of the data segment. */
-#ifdef OBJ_BOUT
-#define RoundUp(N,S) (((N)+(S)-1)&-(S))
- /* For b.out: If the data section has a strict alignment
- requirement, its load address in the .o file will be
- rounded up from the size of the text section. These
- two values are *not* the same! Similarly for the bss
- section.... */
- slide = RoundUp (slide, 1 << section_alignment[SEG_DATA]);
-#endif
-
- for (fragP = data_frag_root; fragP; fragP = fragP->fr_next)
- {
- fragP->fr_address += slide;
- } /* for each data frag */
-
- know (text_last_frag != 0);
- text_last_frag->fr_next = data_frag_root;
- }
- else
- {
- H_SET_DATA_SIZE (&headers, 0);
- }
-
-#ifdef OBJ_BOUT
- /* See above comments on b.out data section address. */
- {
- long bss_vma;
- if (data_last_frag == 0)
- bss_vma = H_GET_TEXT_SIZE (&headers);
- else
- bss_vma = data_last_frag->fr_address;
- bss_vma = RoundUp (bss_vma, 1 << section_alignment[SEG_BSS]);
- bss_address_frag.fr_address = bss_vma;
- }
-#else /* ! OBJ_BOUT */
- bss_address_frag.fr_address = (H_GET_TEXT_SIZE (&headers) +
- H_GET_DATA_SIZE (&headers));
-
-
- /* Slide all the frags */
- if (bss_frag_root)
- {
- relax_addressT slide = bss_address_frag.fr_address;
-
- for (fragP = bss_frag_root; fragP; fragP = fragP->fr_next)
- {
- fragP->fr_address += slide;
- } /* for each bss frag */
- }
-
-#endif /* ! OBJ_BOUT */
-
- if (bss_last_frag)
- H_SET_BSS_SIZE (&headers,
- bss_last_frag->fr_address - bss_frag_root->fr_address);
- else
- H_SET_BSS_SIZE (&headers, 0);
+ relax_and_size_all_segments ();
#endif /* BFD_ASSEMBLER */
#ifndef BFD_ASSEMBLER
for (lie = broken_words; lie; lie = lie->next_broken_word)
if (!lie->added)
{
+ expressionS exp;
+
+ exp.X_op = O_subtract;
+ exp.X_add_symbol = lie->add;
+ exp.X_op_symbol = lie->sub;
+ exp.X_add_number = lie->addnum;
#ifdef BFD_ASSEMBLER
- fix_new (lie->frag, lie->word_goes_here - lie->frag->fr_literal,
- 2, lie->add, lie->sub, lie->addnum, 0,
- BFD_RELOC_NONE);
+ fix_new_exp (lie->frag,
+ lie->word_goes_here - lie->frag->fr_literal,
+ 2, &exp, 0, BFD_RELOC_NONE);
#else
#if defined(TC_SPARC) || defined(TC_A29K) || defined(NEED_FX_R_TYPE)
- fix_new (lie->frag, lie->word_goes_here - lie->frag->fr_literal,
- 2, lie->add,
- lie->sub, lie->addnum,
- 0, NO_RELOC);
+ fix_new_exp (lie->frag,
+ lie->word_goes_here - lie->frag->fr_literal,
+ 2, &exp, 0, NO_RELOC);
#else
#ifdef TC_NS32K
- fix_new_ns32k (lie->frag,
- lie->word_goes_here - lie->frag->fr_literal,
- 2,
- lie->add,
- lie->sub,
- lie->addnum,
- 0, 0, 2, 0, 0);
+ fix_new_ns32k_exp (lie->frag,
+ lie->word_goes_here - lie->frag->fr_literal,
+ 2, &exp, 0, 0, 2, 0, 0);
#else
- fix_new (lie->frag, lie->word_goes_here - lie->frag->fr_literal,
- 2, lie->add,
- lie->sub, lie->addnum,
- 0, 0);
+ fix_new_exp (lie->frag,
+ lie->word_goes_here - lie->frag->fr_literal,
+ 2, &exp, 0, 0);
#endif /* TC_NS32K */
#endif /* TC_SPARC|TC_A29K|NEED_FX_R_TYPE */
#endif /* BFD_ASSEMBLER */
/* Set up symbol table, and write it out. */
if (symbol_rootP)
{
- int i = 0, n;
+ unsigned int i = 0;
+ unsigned int n;
symbolS *symp;
for (symp = symbol_rootP; symp; symp = symbol_next (symp))
{
- int keep = 0;
+ if (! symp->sy_resolved)
+ {
+ if (symp->sy_value.X_op == O_constant)
+ {
+ /* This is the normal case; skip the call. */
+ S_SET_VALUE (symp,
+ (S_GET_VALUE (symp)
+ + symp->sy_frag->fr_address));
+ symp->sy_resolved = 1;
+ }
+ else
+ resolve_symbol_value (symp);
+ }
- S_SET_VALUE (symp, S_GET_VALUE (symp) + symp->sy_frag->fr_address);
/* So far, common symbols have been treated like undefined symbols.
Put them in the common section now. */
if (S_IS_DEFINED (symp) == 0
&& S_GET_VALUE (symp) != 0)
S_SET_SEGMENT (symp, &bfd_com_section);
#if 0
- printf ("symbol `%s'\n\t@%x: value=%d flags=%x forward=%x seg=%s\n",
+ printf ("symbol `%s'\n\t@%x: value=%d flags=%x seg=%s\n",
S_GET_NAME (symp), symp,
S_GET_VALUE (symp),
symp->bsym->flags,
- symp->sy_forward,
segment_name (symp->bsym->section));
#endif
- {
- int punt = 0;
+ if (! symp->sy_used_in_reloc)
+ {
#ifdef obj_frob_symbol
- obj_frob_symbol (symp, punt);
- if (punt)
- goto punt_it;
+ {
+ int punt = 0;
+ obj_frob_symbol (symp, punt);
+ if (punt)
+ goto punt_it;
+ }
#endif
#ifdef tc_frob_symbol
- tc_frob_symbol (symp, punt);
- if (punt)
- goto punt_it;
+ {
+ int punt = 0;
+ tc_frob_symbol (symp, punt);
+ if (punt)
+ goto punt_it;
+ }
#endif
- }
+ }
+
/* If we don't want to keep this symbol, splice it out of the
chain now. */
- if (S_IS_LOCAL (symp))
+ if (! symp->sy_used_in_reloc
+ && S_IS_LOCAL (symp))
{
symbolS *prev, *next;
+#if defined (obj_frob_symbol) || defined (tc_frob_symbol)
punt_it:
+#endif
prev = symbol_previous (symp);
next = symbol_next (symp);
-#ifdef DEBUG
+#ifdef DEBUG_SYMS
verify_symbol_chain_2 (symp);
#endif
if (prev)
symbol_previous (next) = prev;
else
symbol_lastP = prev;
-#ifdef DEBUG
+#ifdef DEBUG_SYMS
if (prev)
verify_symbol_chain_2 (prev);
else if (next)
#endif
continue;
}
+
+ /* Make sure we really got a value for the symbol. */
+ if (! symp->sy_resolved)
+ {
+ as_bad ("can't resolve value for symbol \"%s\"",
+ S_GET_NAME (symp));
+ symp->sy_resolved = 1;
+ }
+
+ /* Set the value into the BFD symbol. Up til now the value
+ has only been kept in the gas symbolS struct. */
+ symp->bsym->value = S_GET_VALUE (symp);
+
i++;
}
n = i;
#ifdef obj_frob_file
+ /* If obj_frob_file changes the symbol value at this point, it is
+ responsible for moving the changed value into symp->bsym->value
+ as well. Hopefully all symbol value changing can be done in
+ {obj,tc}_frob_symbol. */
obj_frob_file ();
#endif
/* Now that all the sizes are known, and contents correct, we can
start writing the file. */
+ bfd_map_over_sections (stdoutput, write_relocs, (char *) 0);
+
bfd_map_over_sections (stdoutput, write_contents, (char *) 0);
output_file_close (out_file_name);
symbolS *symbolP;
long target;
long after;
- long aim;
was_address = fragP->fr_address;
address = fragP->fr_address += stretch;
if (flagseen['K'])
{
char buf[50];
- sprint_value (buf, lie->addnum);
+ sprint_value (buf, (addressT) lie->addnum);
as_warn (".word %s-%s+%s didn't fit",
S_GET_NAME (lie->add),
S_GET_NAME (lie->sub),
const relax_typeS *start_type;
relax_substateT next_state;
relax_substateT this_state;
+ long aim;
this_state = fragP->fr_subtype;
start_type = this_type = md_relax_table + this_state;
if (symbolP)
{
+#ifndef DIFF_EXPR_OK
#if !defined (MANY_SEGMENTS) && !defined (BFD_ASSEMBLER)
know ((S_GET_SEGMENT (symbolP) == SEG_ABSOLUTE)
|| (S_GET_SEGMENT (symbolP) == SEG_DATA)
|| (S_GET_SEGMENT (symbolP) == SEG_TEXT));
#endif
know (symbolP->sy_frag);
+#endif
know (!(S_GET_SEGMENT (symbolP) == absolute_section)
|| symbolP->sy_frag == &zero_address_frag);
target +=
*/
} /* relax_segment() */
+#if defined (BFD_ASSEMBLER) || !defined (BFD)
+
/* fixup_segment()
Go through all the fixS's in a segment and see which ones can be
register segT add_symbol_segment = absolute_section;
seg_reloc_count = 0;
- /* If the linker is doing the relaxing, we must not do any fixups */
+ /* If the linker is doing the relaxing, we must not do any fixups. */
+ /* Well, strictly speaking that's not true -- we could do any that
+ are PC-relative and don't cross regions that could change size.
+ And for the i960 (the only machine for which we've got a relaxing
+ linker right now), we might be able to turn callx/callj into bal
+ in cases where we know the maximum displacement. */
if (linkrelax)
for (; fixP; fixP = fixP->fx_next)
seg_reloc_count++;
if (!add_symbolP)
{
/* Its just -sym */
+ /* @@ Should try converting to pcrel ref to fixed addr. */
if (S_GET_SEGMENT (sub_symbolP) != absolute_section)
as_bad ("Negative of non-absolute symbol %s",
S_GET_NAME (sub_symbolP));
add_symbolP = NULL;
fixP->fx_addsy = NULL;
}
+#if !defined(SEG_DIFF_ALLOWED) && !defined (GLOBAL_DIFF_ALLOWED)
else
{
/* Different segments in subtraction. */
{
add_number -= S_GET_VALUE (sub_symbolP);
}
+#ifdef DIFF_EXPR_OK
+ else if (!pcrel
+ && S_GET_SEGMENT (sub_symbolP) == this_segment_type)
+ {
+ /* Make it pc-relative. */
+ add_number += (md_pcrel_from (fixP)
+ - S_GET_VALUE (sub_symbolP));
+ pcrel = 1;
+ fixP->fx_pcrel = 1;
+ sub_symbolP = 0;
+ fixP->fx_subsy = 0;
+ }
+#endif
else
{
char buf[50];
segment_name (S_GET_SEGMENT (sub_symbolP)),
S_GET_NAME (sub_symbolP), buf);
}
+#else
+ else
+ {
+ seg_reloc_count++;
+ fixP->fx_addnumber = add_number; /* Remember value for emit_reloc */
+ continue;
+ } /* if absolute */
+#endif
}
}
add_number += S_GET_VALUE (add_symbolP);
add_number -= md_pcrel_from (fixP);
pcrel = 0; /* Lie. Don't want further pcrel processing. */
+#ifndef TC_HPPA
fixP->fx_addsy = NULL; /* No relocations please. */
+#endif
}
else
{
}
else if (add_symbol_segment == undefined_section
#ifdef BFD_ASSEMBLER
- || add_symbol_segment == &bfd_com_section
+ || bfd_is_com_section (add_symbol_segment)
#endif
)
{
seg_reloc_count++;
add_number += S_GET_VALUE (add_symbolP);
}
- } /* if not in local seg */
- } /* if there was a + symbol */
+ }
+ }
if (pcrel)
{
if (!fixP->fx_bit_fixP)
{
- if ((size == 1
- && (add_number & ~0xFF)
- && ((add_number & ~0xFF) != (-1 & ~0xFF)))
- || (size == 2
- && (add_number & ~0xFFFF)
- && ((add_number & ~0xFFFF) != (-1 & ~0xFFFF)))
- || (size == 4
- && (add_number & ~(valueT)0xFFFFFFFF)
- && ((add_number & ~(valueT)0xFFFFFFFF) != (-1 & ~(valueT)0xFFFFFFFF)))
- )
+ valueT mask = 0;
+ /* set all bits to one */
+ mask--;
+ /* Technically speaking, combining these produces an
+ undefined result if size is sizeof (valueT), though I
+ think these two half-way operations should both be
+ defined. */
+ mask <<= size * 4;
+ mask <<= size * 4;
+ if ((add_number & mask) != 0
+ && (add_number & mask) != mask)
{
- char buf[50];
+ char buf[50], buf2[50];
sprint_value (buf, fragP->fr_address + where);
- as_bad ("Value of %d too large for field of %d bytes at %s",
- add_number, size, buf);
+ if (add_number > 1000)
+ sprint_value (buf2, add_number);
+ else
+ sprintf (buf2, "%ld", (long) add_number);
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ "Value of %s too large for field of %d bytes at %s",
+ buf2, size, buf);
} /* generic error checking */
#ifdef WARN_SIGNED_OVERFLOW_WORD
/* Warn if a .word value is too large when treated as a signed
if (!flagseen['J']
&& size == 2
&& add_number > 0x7fff)
- as_bad ("Signed .word overflow; switch may be too large; %d at 0x%x",
- add_number, fragP->fr_address + where);
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ "Signed .word overflow; switch may be too large; %ld at 0x%lx",
+ (long) add_number,
+ (unsigned long) (fragP->fr_address + where));
#endif
} /* not a bit fix */
#endif
} /* For each fixS in this segment. */
-#ifdef OBJ_COFF
-#ifdef TC_I960
+#if defined (OBJ_COFF) && defined (TC_I960)
{
fixS *topP = fixP;
/* two relocs per callj under coff. */
for (fixP = topP; fixP; fixP = fixP->fx_next)
- {
- if (fixP->fx_callj && fixP->fx_addsy != 0)
- {
- ++seg_reloc_count;
- } /* if callj and not already fixed. */
- } /* for each fix */
+ if (fixP->fx_callj && fixP->fx_addsy != 0)
+ ++seg_reloc_count;
}
-#endif /* TC_I960 */
+#endif /* OBJ_COFF && TC_I960 */
-#endif /* OBJ_COFF */
return (seg_reloc_count);
}
+#endif /* defined (BFD_ASSEMBLER) || !defined (BFD) */
+
/* end of write.c */