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, 675 Mass Ave, Cambridge, MA 02139, USA. */
+ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "as.h"
#include "obstack.h"
#include "subsegs.h"
+/* I think this is probably always correct. */
+#ifndef KEEP_RELOC_INFO
+#define KEEP_RELOC_INFO
+#endif
+
+
+/* structure used to keep the filenames which
+ are too long around so that we can stick them
+ into the string table */
+struct filename_list
+{
+ char *filename;
+ struct filename_list *next;
+};
+
+static struct filename_list *filename_list_head;
+static struct filename_list *filename_list_tail;
+
const char *s_get_name PARAMS ((symbolS * s));
static symbolS *def_symbol_in_progress;
SA_SET_SYM_LNNO (def_symbol_in_progress, coff_line_base);
demand_empty_rest_of_line ();
+
+#ifndef NO_LISTING
+ if (strcmp (".bf", S_GET_NAME (def_symbol_in_progress)) == 0)
+ {
+ extern int listing;
+
+ if (listing)
+ listing_source_line ((unsigned int) coff_line_base);
+ }
+#endif
}
static void
S_SET_STORAGE_CLASS (symp, C_EXT);
else if (SF_GET_LOCAL (symp))
*punt = 1;
+
+ if (SF_GET_FUNCTION (symp))
+ symp->bsym->flags |= BSF_FUNCTION;
+
/* more ... */
}
#include "frags.h"
/* This is needed because we include internal bfd things. */
#include <time.h>
-#include "bfd/libbfd.h"
-#include "bfd/libcoff.h"
+
+#include "libbfd.h"
+#include "libcoff.h"
/* The NOP_OPCODE is for the alignment fill value. Fill with nop so
that we can stick sections together without causing trouble. */
size += TC_COFF_SIZEMACHDEP (frag);
break;
#endif
+ case rs_space:
+ assert (frag->fr_symbol == 0);
case rs_fill:
case rs_org:
size += frag->fr_fix;
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 (&segment_info[idx], fix_ptr, &intr,
+ base);
#else
symbolS *dot;
- symbol_ptr = fix_ptr->fx_addsy;
+ symbolS *symbol_ptr = fix_ptr->fx_addsy;
intr.r_type = TC_COFF_FIX2RTYPE (fix_ptr);
intr.r_vaddr =
for (i = SEG_E0; i < SEG_UNKNOWN; i++)
{
unsigned int offset = 0;
-
struct internal_scnhdr *s = &(segment_info[i].scnhdr);
+ PROGRESS (1);
+
if (s->s_name[0])
{
fragS *frag = segment_info[i].frchainP->frch_root;
}
break;
+ case rs_space:
+ assert (frag->fr_symbol == 0);
case rs_fill:
case rs_align:
case rs_org:
bfd_coff_swap_scnhdr_out (abfd,
&(segment_info[i].scnhdr),
buffer);
+ if (size == 0)
+ as_bad ("bfd_coff_swap_scnhdr_out failed");
bfd_write (buffer, size, 1, abfd);
}
}
#ifndef NO_LISTING
{
extern int listing;
- if (listing && 0)
+ if (listing)
{
listing_source_line ((unsigned int) line_base);
}
/* This function runs through the symbol table and puts all the
externals onto another chain */
+/* The chain of globals. */
+symbolS *symbol_globalP;
+symbolS *symbol_global_lastP;
+
/* The chain of externals */
symbolS *symbol_externP;
symbolS *symbol_extern_lastP;
unsigned int symbol_number = 0;
unsigned int last_file_symno = 0;
+ struct filename_list *filename_list_scan = filename_list_head;
+
for (symbolP = symbol_rootP;
symbolP;
symbolP = symbolP ? symbol_next (symbolP) : symbol_rootP)
{
+ if (symbolP->sy_mri_common)
+ {
+ if (S_GET_STORAGE_CLASS (symbolP) == C_EXT)
+ as_bad ("%s: global symbols not supported in common sections",
+ S_GET_NAME (symbolP));
+ symbol_remove (symbolP, &symbol_rootP, &symbol_lastP);
+ continue;
+ }
+
if (!SF_GET_DEBUG (symbolP))
{
/* Debug symbols do not need all this rubbish */
}
else if (S_GET_STORAGE_CLASS (symbolP) == C_FILE)
{
+ /* If the filename was too long to fit in the
+ auxent, put it in the string table */
+ if (SA_GET_FILE_FNAME_ZEROS (symbolP) == 0)
+ {
+ SA_SET_FILE_FNAME_OFFSET (symbolP, string_byte_count);
+ string_byte_count += strlen (filename_list_scan->filename) + 1;
+ filename_list_scan = filename_list_scan->next;
+ }
if (S_GET_VALUE (symbolP))
{
S_SET_VALUE (symbolP, last_file_symno);
symbol_append (symbolP, symbol_extern_lastP, &symbol_externP, &symbol_extern_lastP);
symbolP = hold;
}
+ else if (! S_IS_DEBUG (symbolP)
+ && ! SF_GET_STATICS (symbolP)
+ && ! SF_GET_FUNCTION (symbolP)
+ && S_GET_STORAGE_CLASS (symbolP) == C_EXT)
+ {
+ symbolS *hold = symbol_previous (symbolP);
+
+ /* The O'Reilly COFF book says that defined global symbols
+ come at the end of the symbol table, just before
+ undefined global symbols. */
+
+ symbol_remove (symbolP, &symbol_rootP, &symbol_lastP);
+ symbol_clear_list_pointers (symbolP);
+ symbol_append (symbolP, symbol_global_lastP, &symbol_globalP,
+ &symbol_global_lastP);
+ symbolP = hold;
+ }
else
{
if (SF_GET_STRING (symbolP))
static unsigned int
-glue_symbols ()
+glue_symbols (head, tail)
+ symbolS **head;
+ symbolS **tail;
{
unsigned int symbol_number = 0;
symbolS *symbolP;
- for (symbolP = symbol_externP; symbol_externP;)
+
+ for (symbolP = *head; *head != NULL;)
{
- symbolS *tmp = symbol_externP;
+ symbolS *tmp = *head;
/* append */
- symbol_remove (tmp, &symbol_externP, &symbol_extern_lastP);
+ symbol_remove (tmp, head, tail);
symbol_append (tmp, symbol_lastP, &symbol_rootP, &symbol_lastP);
/* and process */
tmp->sy_number = symbol_number;
symbol_number += 1 + S_GET_NUMBER_AUXILIARY (tmp);
} /* append the entire extern chain */
- return symbol_number;
+ return symbol_number;
}
static unsigned int
/* Take all the externals out and put them into another chain */
H_SET_SYMBOL_TABLE_SIZE (h, yank_symbols ());
/* Take the externals and glue them onto the end.*/
- H_SET_SYMBOL_TABLE_SIZE (h, H_GET_SYMBOL_COUNT (h) + glue_symbols ());
+ H_SET_SYMBOL_TABLE_SIZE (h,
+ (H_GET_SYMBOL_COUNT (h)
+ + glue_symbols (&symbol_globalP,
+ &symbol_global_lastP)
+ + glue_symbols (&symbol_externP,
+ &symbol_extern_lastP)));
H_SET_SYMBOL_TABLE_SIZE (h, tie_tags ());
+ know (symbol_globalP == NULL);
+ know (symbol_global_lastP == NULL);
know (symbol_externP == NULL);
know (symbol_extern_lastP == NULL);
}
char *where;
{
symbolS *symbolP;
+ struct filename_list *filename_list_scan = filename_list_head;
/* Gotta do md_ byte-ordering stuff for string_byte_count first - KWK */
md_number_to_chars (where, (valueT) string_byte_count, 4);
if (SF_GET_STRING (symbolP))
{
size = strlen (S_GET_NAME (symbolP)) + 1;
-
memcpy (where, S_GET_NAME (symbolP), size);
where += size;
-
+ }
+ if (S_GET_STORAGE_CLASS (symbolP) == C_FILE
+ && SA_GET_FILE_FNAME_ZEROS (symbolP) == 0)
+ {
+ size = strlen (filename_list_scan->filename) + 1;
+ memcpy (where, filename_list_scan->filename, size);
+ filename_list_scan = filename_list_scan ->next;
+ where += size;
}
}
}
H_SET_STRING_SIZE (&headers, string_byte_count);
-#if !defined(TC_H8300) && !defined(TC_Z8K)
+#ifdef tc_frob_file
+ tc_frob_file ();
+#endif
+
for (i = SEG_E0; i < SEG_UNKNOWN; i++)
{
fixup_mdeps (segment_info[i].frchainP->frch_root, &headers, i);
fixup_segment (&segment_info[i], i);
}
-#endif
/* Look for ".stab" segments and fill in their initial symbols
correctly. */
H_SET_FILE_MAGIC_NUMBER (&headers, COFF_MAGIC);
#ifndef OBJ_COFF_OMIT_TIMESTAMP
- H_SET_TIME_STAMP (&headers, (long)time((long*)0));
+ H_SET_TIME_STAMP (&headers, (long)time((time_t *)0));
#else
H_SET_TIME_STAMP (&headers, 0);
#endif
TC_COFF_SET_MACHINE (&headers);
#endif
+#ifndef COFF_FLAGS
+#define COFF_FLAGS 0
+#endif
+
#ifdef KEEP_RELOC_INFO
H_SET_FLAGS (&headers, ((H_GET_LINENO_SIZE(&headers) ? 0 : F_LNNO) |
COFF_FLAGS | coff_flags));
S_SET_STORAGE_CLASS (symbolP, C_FILE);
S_SET_NUMBER_AUXILIARY (symbolP, 1);
- SA_SET_FILE_FNAME (symbolP, filename);
+
+ if (strlen (filename) > FILNMLEN)
+ {
+ /* Filename is too long to fit into an auxent,
+ we stick it into the string table instead. We keep
+ a linked list of the filenames we find so we can emit
+ them later.*/
+ struct filename_list *f = xmalloc (sizeof (struct filename_list));
+
+ f->filename = filename;
+ f->next = 0;
+
+ SA_SET_FILE_FNAME_ZEROS (symbolP, 0);
+ SA_SET_FILE_FNAME_OFFSET (symbolP, 0);
+
+ if (filename_list_tail)
+ filename_list_tail->next = f;
+ else
+ filename_list_head = f;
+ filename_list_tail = f;
+ }
+ else
+ {
+ SA_SET_FILE_FNAME (symbolP, filename);
+ }
#ifndef NO_LISTING
{
extern int listing;
{
case rs_align:
case rs_org:
+#ifdef HANDLE_ALIGN
+ HANDLE_ALIGN (frags);
+#endif
frags->fr_type = rs_fill;
frags->fr_offset =
(frags->fr_next->fr_address - frags->fr_address - frags->fr_fix);
break;
case rs_machine_dependent:
- md_convert_frag (h, frags);
+ md_convert_frag (h, this_segment, frags);
frag_wane (frags);
break;
default:
}
#if 1
+
+#ifndef TC_FORCE_RELOCATION
+#define TC_FORCE_RELOCATION(fix) 0
+#endif
+
static void
fixup_segment (segP, this_segment_type)
segment_info_type * segP;
register fixS * fixP;
register symbolS *add_symbolP;
register symbolS *sub_symbolP;
- register long add_number;
+ long add_number;
register int size;
register char *place;
register long where;
register fragS *fragP;
register segT add_symbol_segment = absolute_section;
+ if (linkrelax)
+ return;
for (fixP = segP->fix_root; fixP; fixP = fixP->fx_next)
{
add_number = fixP->fx_offset;
pcrel = fixP->fx_pcrel;
+ if (add_symbolP != NULL
+ && add_symbolP->sy_mri_common)
+ {
+ know (add_symbolP->sy_value.X_op == O_symbol);
+ add_number += S_GET_VALUE (add_symbolP);
+ fixP->fx_offset = add_number;
+ add_symbolP = fixP->fx_addsy = add_symbolP->sy_value.X_add_symbol;
+ }
+
if (add_symbolP)
{
add_symbol_segment = S_GET_SEGMENT (add_symbolP);
#endif /* TC_I960 */
add_number += S_GET_VALUE (add_symbolP) -
S_GET_VALUE (sub_symbolP);
-
add_symbolP = NULL;
- fixP->fx_addsy = NULL;
- fixP->fx_subsy = NULL;
- fixP->fx_done = 1;
+
+ if (!TC_FORCE_RELOCATION (fixP))
+ {
+ fixP->fx_addsy = NULL;
+ fixP->fx_subsy = NULL;
+ fixP->fx_done = 1;
+#ifdef TC_M68K /* is this right? */
+ pcrel = 0;
+ fixP->fx_pcrel = 0;
+#endif
+ }
}
else
{
add_number -= segP->scnhdr.s_vaddr;
#endif
pcrel = 0; /* Lie. Don't want further pcrel processing. */
- fixP->fx_addsy = NULL;
- fixP->fx_done = 1;
+ if (!TC_FORCE_RELOCATION (fixP))
+ {
+ fixP->fx_addsy = NULL;
+ fixP->fx_done = 1;
+ }
}
else
{
reloc_callj (fixP); /* See comment about reloc_callj() above*/
#endif /* TC_I960 */
add_number += S_GET_VALUE (add_symbolP);
- fixP->fx_addsy = NULL;
- fixP->fx_done = 1;
add_symbolP = NULL;
+
+ if (!TC_FORCE_RELOCATION (fixP))
+ {
+ fixP->fx_addsy = NULL;
+ fixP->fx_done = 1;
+ }
break;
default:
-#ifdef TC_A29K
+
+#if defined(TC_A29K) || (defined(TE_PE) && defined(TC_I386))
/* This really should be handled in the linker, but
backward compatibility forbids. */
add_number += S_GET_VALUE (add_symbolP);
continue;
} /* COBR */
#endif /* TC_I960 */
-#if defined (TC_I386) || defined (TE_LYNX)
- /* 386 COFF uses a peculiar format in
- which the value of a common symbol is
- stored in the .text segment (I've
- checked this on SVR3.2 and SCO 3.2.2)
- Ian Taylor <ian@cygnus.com>. */
+#if (defined (TC_I386) || defined (TE_LYNX)) && !defined(TE_PE)
+ /* 386 COFF uses a peculiar format in which the
+ value of a common symbol is stored in the .text
+ segment (I've checked this on SVR3.2 and SCO
+ 3.2.2) Ian Taylor <ian@cygnus.com>. */
if (S_IS_COMMON (add_symbolP))
add_number += S_GET_VALUE (add_symbolP);
#endif
if (pcrel)
{
-#ifndef TC_M88K
+#if !defined(TC_M88K) && !(defined(TE_PE) && defined(TC_I386))
/* This adjustment is not correct on the m88k, for which the
linker does all the computation. */
add_number -= md_pcrel_from (fixP);
}
#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
- negative. This is to catch over-large switches
- generated by gcc on the 68k. */
+ /* Warn if a .word value is too large when treated as a
+ signed number. We already know it is not too negative.
+ This is to catch over-large switches generated by gcc on
+ the 68k. */
if (!flag_signed_overflow_ok
&& size == 2
&& add_number > 0x7fff)
(unsigned long) (fragP->fr_address + where));
#endif
} /* not a bit fix */
- /* once this fix has been applied, we don't have to output anything
- nothing more need be done -*/
+ /* Once this fix has been applied, we don't have to output
+ anything nothing more need be done. */
+#ifdef MD_APPLY_FIX3
+ md_apply_fix3 (fixP, &add_number, this_segment_type);
+#else
md_apply_fix (fixP, add_number);
+#endif
} /* For each fixS in this segment. */
} /* fixup_segment() */