/* coff object file format with bfd
- Copyright (C) 1989, 1990, 1991 Free Software Foundation, Inc.
+ Copyright (C) 1989, 1990, 1991, 1993 Free Software Foundation, Inc.
This file is part of GAS.
9,
10,
C_UNDEF_SECTION, /* SEG_UNKNOWN */
- C_UNDEF_SECTION, /* SEG_ABSENT */
- C_UNDEF_SECTION, /* SEG_PASS1 */
C_UNDEF_SECTION, /* SEG_GOOF */
- C_UNDEF_SECTION, /* SEG_BIG */
- C_UNDEF_SECTION, /* SEG_DIFFERENCE */
+ C_UNDEF_SECTION, /* SEG_EXPR */
C_DEBUG_SECTION, /* SEG_DEBUG */
C_NTV_SECTION, /* SEG_NTV */
C_PTV_SECTION, /* SEG_PTV */
static void EXFUN( obj_coff_ident,(void));
static void EXFUN (obj_coff_endef, (void));
static void EXFUN (obj_coff_line, (void));
-static void EXFUN (obj_coff_ln, (void));
+static void EXFUN (obj_coff_ln, (int));
static void EXFUN (obj_coff_scl, (void));
static void EXFUN (obj_coff_size, (void));
static void EXFUN (obj_coff_tag, (void));
{"endef", obj_coff_endef, 0},
{"line", obj_coff_line, 0},
{"ln", obj_coff_ln, 0},
+ {"appline", obj_coff_ln, 1},
{"scl", obj_coff_scl, 0},
{"size", obj_coff_size, 0},
{"tag", obj_coff_tag, 0},
{"ident", obj_coff_ident, 0},
{"ABORT", s_abort, 0},
{"lcomm", obj_coff_lcomm, 0},
+#ifdef TC_M88K
+ /* The m88k uses sdef instead of def. */
+ {"sdef", obj_coff_def, 0},
+#endif
{NULL} /* end sentinel */
}; /* obj_pseudo_table */
struct external_reloc *ext_ptr;
struct external_reloc *external_reloc_vec;
unsigned int external_reloc_size;
- unsigned int count = 0;
unsigned int base = segment_info[idx].scnhdr.s_paddr;
fixS *fix_ptr = segment_info[idx].fix_root;
nrelocs = count_entries_in_chain (idx);
- external_reloc_size = nrelocs * RELSZ;
- external_reloc_vec =
- (struct external_reloc *) malloc (external_reloc_size);
-
- ext_ptr = external_reloc_vec;
-
- /* Fill in the internal coff style reloc struct from the
- internal fix list. */
- while (fix_ptr)
+ if (nrelocs)
+ /* Bypass this stuff if no relocs. This also incidentally
+ avoids a SCO bug, where free(malloc(0)) tends to crash. */
{
- symbolS *symbol_ptr;
- struct internal_reloc intr;
+ external_reloc_size = nrelocs * RELSZ;
+ external_reloc_vec =
+ (struct external_reloc *) malloc (external_reloc_size);
- /* Only output some of the relocations */
- if (TC_COUNT_RELOC (fix_ptr))
+ ext_ptr = external_reloc_vec;
+
+ /* Fill in the internal coff style reloc struct from the
+ internal fix list. */
+ while (fix_ptr)
{
+ symbolS *symbol_ptr;
+ struct internal_reloc intr;
+
+ /* Only output some of the relocations */
+ if (TC_COUNT_RELOC (fix_ptr))
+ {
#ifdef TC_RELOC_MANGLE
- TC_RELOC_MANGLE (fix_ptr, &intr, base);
+ TC_RELOC_MANGLE (fix_ptr, &intr, base);
#else
- symbolS *dot;
- symbol_ptr = fix_ptr->fx_addsy;
-
- intr.r_type = TC_COFF_FIX2RTYPE (fix_ptr);
- intr.r_vaddr =
- base + fix_ptr->fx_frag->fr_address + fix_ptr->fx_where;
+ symbolS *dot;
+ symbol_ptr = fix_ptr->fx_addsy;
- intr.r_offset = fix_ptr->fx_offset;
+ intr.r_type = TC_COFF_FIX2RTYPE (fix_ptr);
+ intr.r_vaddr =
+ base + fix_ptr->fx_frag->fr_address + fix_ptr->fx_where;
- intr.r_offset = 0;
+#ifdef TC_M88K
+ intr.r_offset = fix_ptr->fx_offset;
+#else
+ intr.r_offset = 0;
+#endif
- /* Turn the segment of the symbol into an offset. */
- if (symbol_ptr)
- {
- dot = segment_info[S_GET_SEGMENT (symbol_ptr)].dot;
- if (dot)
+ /* Turn the segment of the symbol into an offset. */
+ if (symbol_ptr)
{
- intr.r_symndx = dot->sy_number;
+ dot = segment_info[S_GET_SEGMENT (symbol_ptr)].dot;
+ if (dot)
+ {
+ intr.r_symndx = dot->sy_number;
+ }
+ else
+ {
+ intr.r_symndx = symbol_ptr->sy_number;
+ }
+
}
else
{
- intr.r_symndx = symbol_ptr->sy_number;
+ intr.r_symndx = -1;
}
-
- }
- else
- {
- intr.r_symndx = -1;
- }
#endif
- (void) bfd_coff_swap_reloc_out (abfd, &intr, ext_ptr);
- ext_ptr++;
+ (void) bfd_coff_swap_reloc_out (abfd, &intr, ext_ptr);
+ ext_ptr++;
#if defined(TC_A29K)
- /* The 29k has a special kludge for the high 16 bit
- reloc. Two relocations are emited, R_IHIHALF,
- and R_IHCONST. The second one doesn't contain a
- symbol, but uses the value for offset. */
+ /* The 29k has a special kludge for the high 16 bit
+ reloc. Two relocations are emited, R_IHIHALF,
+ and R_IHCONST. The second one doesn't contain a
+ symbol, but uses the value for offset. */
- if (intr.r_type == R_IHIHALF)
- {
- /* now emit the second bit */
- intr.r_type = R_IHCONST;
- intr.r_symndx = fix_ptr->fx_addnumber;
-
- /* The offset to the segment holding the symbol
- has already been counted in the R_IHIHALF.
- We don't want to add it in again for the
- R_IHCONST. */
- if (symbol_ptr)
- intr.r_symndx -=
- segment_info[S_GET_SEGMENT (symbol_ptr)].scnhdr.s_paddr;
- (void) bfd_coff_swap_reloc_out (abfd, &intr, ext_ptr);
- ext_ptr++;
- }
+ if (intr.r_type == R_IHIHALF)
+ {
+ /* now emit the second bit */
+ intr.r_type = R_IHCONST;
+ intr.r_symndx = fix_ptr->fx_addnumber;
+ (void) bfd_coff_swap_reloc_out (abfd, &intr, ext_ptr);
+ ext_ptr++;
+ }
#endif
+ }
+
+ fix_ptr = fix_ptr->fx_next;
}
- fix_ptr = fix_ptr->fx_next;
- }
+ /* Write out the reloc table */
+ bfd_write ((PTR) external_reloc_vec, 1, external_reloc_size,
+ abfd);
+ free (external_reloc_vec);
- /* Write out the reloc table */
- segment_info[idx].scnhdr.s_relptr = nrelocs ? *file_cursor : 0;
- segment_info[idx].scnhdr.s_nreloc = nrelocs;
- bfd_write ((PTR) external_reloc_vec, 1, external_reloc_size, abfd);
- *file_cursor += external_reloc_size;
- free (external_reloc_vec);
+ /* Fill in section header info. */
+ segment_info[idx].scnhdr.s_relptr = *file_cursor;
+ *file_cursor += external_reloc_size;
+ segment_info[idx].scnhdr.s_nreloc = nrelocs;
+ }
+ else
+ {
+ /* No relocs */
+ segment_info[idx].scnhdr.s_relptr = 0;
+ }
}
}
/* Set relocation_size field in file headers */
}
know (s->s_paddr == paddr);
- s->s_flags = STYP_REG;
if (strcmp (s->s_name, ".text") == 0)
s->s_flags |= STYP_TEXT;
else if (strcmp (s->s_name, ".data") == 0)
s->s_scnptr = 0;
s->s_flags |= STYP_BSS;
#ifndef TC_I386
+#ifndef TC_A29K
/* Apparently the SVR3 linker is confused by noload
- sections. */
+ sections. So is the UDI mondfe program. */
s->s_flags |= STYP_NOLOAD;
+#endif
#endif
}
else if (strcmp (s->s_name, ".lit") == 0)
}
fill_size = frag->fr_var;
- if (fill_size)
+ if (fill_size && frag->fr_offset > 0)
{
unsigned int count;
unsigned int off = frag->fr_fix;
{
unsigned int numaux = symbolP->sy_symbol.ost_entry.n_numaux;
unsigned int i;
+ valueT val;
/* Turn any symbols with register attributes into abs symbols */
if (S_GET_SEGMENT (symbolP) == SEG_REGISTER)
}
/* At the same time, relocate all symbols to their output value */
- S_SET_VALUE (symbolP,
- segment_info[S_GET_SEGMENT (symbolP)].scnhdr.s_paddr
- + S_GET_VALUE (symbolP));
+ val = (segment_info[S_GET_SEGMENT (symbolP)].scnhdr.s_paddr
+ + S_GET_VALUE (symbolP));
+
+ S_SET_VALUE (symbolP, val);
+
+ symbolP->sy_symbol.ost_entry.n_value = val;
where += bfd_coff_swap_sym_out (abfd, &symbolP->sy_symbol.ost_entry,
where);
}
-
-
void
obj_symbol_new_hook (symbolP)
symbolS *symbolP;
*/
static void
-obj_coff_ln ()
+obj_coff_ln (appline)
+ int appline;
{
int l;
- if (def_symbol_in_progress != NULL)
+ if (! appline && def_symbol_in_progress != NULL)
{
as_warn (".ln pseudo-op inside .def/.endef: ignored.");
demand_empty_rest_of_line ();
if (listing)
{
- listing_source_line (l + line_base - 1);
+ if (! appline)
+ l += line_base - 1;
+ listing_source_line (l);
}
}
def_symbol_in_progress->sy_name_offset = ~0;
def_symbol_in_progress->sy_number = ~0;
def_symbol_in_progress->sy_frag = &zero_address_frag;
+ S_SET_VALUE (def_symbol_in_progress, 0);
if (S_IS_STRING (def_symbol_in_progress))
{
break;
} /* switch on storage class */
- /* Now that we have built a debug symbol, try to find if
- we should merge with an existing symbol or not. If a
- symbol is C_EFCN or SEG_ABSOLUTE or untagged
- SEG_DEBUG it never merges. We also don't merge
- labels, which are in a different namespace, nor
- symbols which have not yet been defined since they
- are typically unique, nor do we merge tags with
- non-tags. */
-
- /* Two cases for functions. Either debug followed
- by definition or definition followed by debug.
- For definition first, we will merge the debug
- symbol into the definition. For debug first, the
- lineno entry MUST point to the definition
- function or else it will point off into space
- when crawl_symbols() merges the debug
- symbol into the real symbol. Therefor, let's
- presume the debug symbol is a real function
- reference. */
-
- /* FIXME-SOON If for some reason the definition
- label/symbol is never seen, this will probably
- leave an undefined symbol at link time. */
+ /* Now that we have built a debug symbol, try to find if we should
+ merge with an existing symbol or not. If a symbol is C_EFCN or
+ SEG_ABSOLUTE or untagged SEG_DEBUG it never merges. We also
+ don't merge labels, which are in a different namespace, nor
+ symbols which have not yet been defined since they are typically
+ unique, nor do we merge tags with non-tags. */
+
+ /* Two cases for functions. Either debug followed by definition or
+ definition followed by debug. For definition first, we will
+ merge the debug symbol into the definition. For debug first, the
+ lineno entry MUST point to the definition function or else it
+ will point off into space when crawl_symbols() merges the debug
+ symbol into the real symbol. Therefor, let's presume the debug
+ symbol is a real function reference. */
+
+ /* FIXME-SOON If for some reason the definition label/symbol is
+ never seen, this will probably leave an undefined symbol at link
+ time. */
if (S_GET_STORAGE_CLASS (def_symbol_in_progress) == C_EFCN
|| S_GET_STORAGE_CLASS (def_symbol_in_progress) == C_LABEL
|| (S_GET_SEGMENT (def_symbol_in_progress) == SEG_DEBUG
&& !SF_GET_TAG (def_symbol_in_progress))
|| S_GET_SEGMENT (def_symbol_in_progress) == SEG_ABSOLUTE
- || def_symbol_in_progress->sy_forward != NULL
+ || def_symbol_in_progress->sy_value.X_op != O_constant
|| (symbolP = symbol_find_base (S_GET_NAME (def_symbol_in_progress), DO_NOT_STRIP)) == NULL
|| (SF_GET_TAG (def_symbol_in_progress) != SF_GET_TAG (symbolP)))
{
-
- symbol_append (def_symbol_in_progress, symbol_lastP, &symbol_rootP, &symbol_lastP);
-
+ symbol_append (def_symbol_in_progress, symbol_lastP, &symbol_rootP,
+ &symbol_lastP);
}
else
{
- /* This symbol already exists, merge the
- newly created symbol into the old one.
- This is not mandatory. The linker can
- handle duplicate symbols correctly. But I
- guess that it save a *lot* of space if
- the assembly file defines a lot of
- symbols. [loic] */
+ /* This symbol already exists, merge the newly created symbol
+ into the This is not mandatory. The linker can handle
+ duplicate symbols correctly. But I guess that it save a *lot*
+ of space if the assembly file defines a lot of
+ symbols. [loic] */
- /* The debug entry (def_symbol_in_progress)
- is merged into the previous definition. */
+ /* The debug entry (def_symbol_in_progress) is merged into the
+ previous definition. */
c_symbol_merge (def_symbol_in_progress, symbolP);
/* FIXME-SOON Should *def_symbol_in_progress be free'd? xoxorich. */
if (SF_GET_FUNCTION (def_symbol_in_progress)
|| SF_GET_TAG (def_symbol_in_progress))
{
- /* For functions, and tags, the symbol *must* be where the debug symbol
- appears. Move the existing symbol to the current place. */
+ /* For functions, and tags, the symbol *must* be where the
+ debug symbol appears. Move the existing symbol to the
+ current place. */
/* If it already is at the end of the symbol list, do nothing */
if (def_symbol_in_progress != symbol_lastP)
{
- symbol_remove (def_symbol_in_progress, &symbol_rootP, &symbol_lastP);
- symbol_append (def_symbol_in_progress, symbol_lastP, &symbol_rootP, &symbol_lastP);
+ symbol_remove (def_symbol_in_progress, &symbol_rootP,
+ &symbol_lastP);
+ symbol_append (def_symbol_in_progress, symbol_lastP,
+ &symbol_rootP, &symbol_lastP);
} /* if not already in place */
} /* if function */
} /* normal or mergable */
&& symbol_find_base (S_GET_NAME (def_symbol_in_progress), DO_NOT_STRIP) == NULL)
{
tag_insert (S_GET_NAME (def_symbol_in_progress), def_symbol_in_progress);
- } /* If symbol is a {structure,union} tag, associate symbol to its name. */
+ }
if (SF_GET_FUNCTION (def_symbol_in_progress))
{
function_lineoff
= c_line_new (def_symbol_in_progress, 0, 0, &zero_address_frag);
-
-
SF_SET_PROCESS (def_symbol_in_progress);
if (symbolP == NULL)
{
- /* That is, if this is the first
- time we've seen the function... */
+ /* That is, if this is the first time we've seen the
+ function... */
symbol_table_insert (def_symbol_in_progress);
} /* definition follows debug */
} /* Create the line number entry pointing to the function being defined */
def_symbol_in_progress = NULL;
demand_empty_rest_of_line ();
return;
-} /* obj_coff_endef() */
+}
static void
DEFUN_VOID (obj_coff_dim)
if (def_symbol_in_progress == NULL)
{
- obj_coff_ln ();
+ obj_coff_ln (0);
return;
} /* if it looks like a stabs style line */
}
else if (strcmp (S_GET_NAME (def_symbol_in_progress), symbol_name))
{
- def_symbol_in_progress->sy_forward = symbol_find_or_make (symbol_name);
-
- /* If the segment is undefined when the forward
- reference is solved, then copy the segment id
- from the forward symbol. */
+ def_symbol_in_progress->sy_value.X_op = O_symbol;
+ def_symbol_in_progress->sy_value.X_add_symbol =
+ symbol_find_or_make (symbol_name);
+ def_symbol_in_progress->sy_value.X_op_symbol = NULL;
+ def_symbol_in_progress->sy_value.X_add_number = 0;
+
+ /* If the segment is undefined when the forward reference is
+ resolved, then copy the segment id from the forward
+ symbol. */
SF_SET_GET_SEGMENT (def_symbol_in_progress);
/* FIXME: gcc can generate address expressions
symbolS *last_functionP = NULL;
symbolS *last_tagP;
-
static unsigned int
DEFUN_VOID (yank_symbols)
{
symbolS *symbolP;
unsigned int symbol_number = 0;
+ unsigned int last_file_symno = 0;
for (symbolP = symbol_rootP;
symbolP;
/* L* and C_EFCN symbols never merge. */
if (!SF_GET_LOCAL (symbolP)
&& S_GET_STORAGE_CLASS (symbolP) != C_LABEL
+ && symbolP->sy_value.X_op == O_constant
&& (real_symbolP = symbol_find_base (S_GET_NAME (symbolP), DO_NOT_STRIP))
&& real_symbolP != symbolP)
{
S_SET_SEGMENT (symbolP, SEG_E0);
} /* push data into text */
- S_SET_VALUE (symbolP,
- S_GET_VALUE (symbolP) + symbolP->sy_frag->fr_address);
+ resolve_symbol_value (symbolP);
if (!S_IS_DEFINED (symbolP) && !SF_GET_LOCAL (symbolP))
{
sizeof (symbolP->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_ary.x_dimen));
#endif
}
- /* The C_FCN doesn't need any additional information.
- I don't even know if this is needed for sdb. But the
- standard assembler generates it, so...
- */
+ /* The C_FCN doesn't need any additional information. I
+ don't even know if this is needed for sdb. But the
+ standard assembler generates it, so... */
if (S_GET_STORAGE_CLASS (symbolP) == C_EFCN)
{
if (last_functionP == (symbolS *) 0)
{
if (S_GET_VALUE (symbolP))
{
- S_SET_VALUE ((symbolS *) S_GET_VALUE (symbolP), symbol_number);
- S_SET_VALUE (symbolP, 0);
+ S_SET_VALUE (symbolP, last_file_symno);
+ last_file_symno = symbol_number;
} /* no one points at the first .file symbol */
} /* if debug or tag or eos or file */
{
unsigned int i;
- unsigned int ptr = 0;
-
-
symbolS *symbolP;
/* Initialize the stack used to keep track of the matching .bb .be */
block_stack = stack_init (512, sizeof (symbolS *));
- /* JF deal with forward references first... */
- for (symbolP = symbol_rootP;
- symbolP;
- symbolP = symbol_next (symbolP))
- {
-
- if (symbolP->sy_forward)
- {
- S_SET_VALUE (symbolP, (S_GET_VALUE (symbolP)
- + S_GET_VALUE (symbolP->sy_forward)
- + symbolP->sy_forward->sy_frag->fr_address));
-
- if (SF_GET_GET_SEGMENT (symbolP))
- {
- S_SET_SEGMENT (symbolP, S_GET_SEGMENT (symbolP->sy_forward));
- } /* forward segment also */
-
- symbolP->sy_forward = 0;
- } /* if it has a forward reference */
- } /* walk the symbol chain */
-
/* The symbol list should be ordered according to the following sequence
* order :
symbolS *symbolP;
/* Gotta do md_ byte-ordering stuff for string_byte_count first - KWK */
- md_number_to_chars (where, string_byte_count, sizeof (string_byte_count));
- where += sizeof (string_byte_count);
+ md_number_to_chars (where, string_byte_count, 4);
+ where += 4;
for (symbolP = symbol_rootP;
symbolP;
symbolP = symbol_next (symbolP))
{
subseg_new (i, exp);
return;
-
}
}
/* No section, add one */
strncpy (segment_info[i].scnhdr.s_name, name, 8);
+ segment_info[i].scnhdr.s_flags = STYP_REG;
subseg_new (i, exp);
}
static void
obj_coff_data ()
{
- change_to_section (".data", 5, get_absolute_expression ());
+ if (flagseen['R'])
+ change_to_section (".text", 5, get_absolute_expression () + 1000);
+ else
+ change_to_section (".data", 5, get_absolute_expression ());
}
static void
break;
default:
+#ifdef TC_A29K
+ /* This really should be handled in the linker, but
+ backward compatibility forbids. */
+ add_number += S_GET_VALUE (add_symbolP);
+#else
add_number += S_GET_VALUE (add_symbolP) +
segment_info[S_GET_SEGMENT (add_symbolP)].scnhdr.s_paddr;
+#endif
break;
case SEG_UNKNOWN:
if (pcrel)
{
+#ifndef TC_M88K
+ /* This adjustment is not correct on the m88k, for which the
+ linker does all the computation. */
add_number -= md_pcrel_from (fixP);
+#endif
if (add_symbolP == 0)
{
fixP->fx_addsy = &abs_symbol;
if (!fixP->fx_bit_fixP)
{
+#ifndef TC_M88K
+ /* The m88k uses the offset field of the reloc to get around
+ this problem. */
if ((size == 1 &&
(add_number & ~0xFF) && ((add_number & ~0xFF) != (-1 & ~0xFF))) ||
(size == 2 &&
as_bad ("Value of %d too large for field of %d bytes at 0x%x",
add_number, size, fragP->fr_address + where);
} /* generic error checking */
+#endif
#ifdef WARN_SIGNED_OVERFLOW_WORD
/* Warn if a .word value is too large when treated as
a signed number. We already know it is not too