#include "../bfd/libbfd.h"
#include "../bfd/libcoff.h"
+/* The NOP_OPCODE is for the alignment fill value. Fill with nop so
+ that we can stick sections together without causing trouble. */
+#ifndef NOP_OPCODE
+#define NOP_OPCODE 0x00
+#endif
#define MIN(a,b) ((a) < (b)? (a) : (b))
/* This vector is used to turn an internal segment into a section #
void EXFUN (bfd_as_write_hook, (struct internal_filehdr *,
bfd * abfd));
-static void EXFUN (fixup_segment, (fixS * fixP,
+static void EXFUN (fixup_segment, (segment_info_type *segP,
segT this_segment_type));
*file_cursor += external_reloc_size;
free (external_reloc_vec);
}
-#ifndef ZERO_BASED_SEGMENTS
- /* Supposedly setting segment addresses non-zero causes problems
- for some platforms, although it shouldn't. If you define
- ZERO_BASED_SEGMENTS, all the segments will be based at 0.
- Please don't make this the default, since some systems (e.g.,
- SVR3.2) require the segments to be non-zero based. Ian Taylor
- <ian@cygnus.com>. */
addr += segment_info[idx].scnhdr.s_size;
-#endif
}
}
{
unsigned int i;
+#ifdef ZERO_BASED_SEGMENTS
+ unsigned int paddr = 0;
+#endif
for (i = SEG_E0; i < SEG_UNKNOWN; i++)
{
if (s->s_name[0])
{
fragS *frag = segment_info[i].frchainP->frch_root;
- char *buffer = malloc (s->s_size);
- if (s->s_size != 0)
- s->s_scnptr = *file_cursor;
+ char *buffer;
+
+ if (s->s_size != 0 && i != SEG_E2)
+ {
+ buffer = malloc (s->s_size);
+ s->s_scnptr = *file_cursor;
+#ifdef ZERO_BASED_SEGMENTS
+ s->s_paddr = paddr;
+ s->s_vaddr = paddr;
+#endif
+ }
else
- s->s_scnptr = 0;
+ {
+ buffer = NULL;
+ s->s_scnptr = 0;
+ }
s->s_flags = STYP_REG;
if (strcmp (s->s_name, ".text") == 0)
s->s_flags |= STYP_BSS | STYP_NOLOAD;
else if (strcmp (s->s_name, ".lit") == 0)
s->s_flags = STYP_LIT | STYP_TEXT;
-
+ else if (strcmp (s->s_name, ".init") == 0)
+ s->s_flags |= STYP_TEXT;
+ else if (strcmp (s->s_name, ".fini") == 0)
+ s->s_flags |= STYP_TEXT;
while (frag)
{
frag = frag->fr_next;
}
-
- bfd_write (buffer, s->s_size, 1, abfd);
- free (buffer);
-
- *file_cursor += s->s_size;
-
+ if (s->s_size != 0 && i != SEG_E2)
+ {
+ bfd_write (buffer, s->s_size, 1, abfd);
+ free (buffer);
+ *file_cursor += s->s_size;
+ }
+#ifdef ZERO_BASED_SEGMENTS
+ paddr += s->s_size;
+#endif
}
}
-
}
case C_FCN:
S_SET_SEGMENT (def_symbol_in_progress, SEG_E0);
- if (def_symbol_in_progress->sy_symbol.ost_entry._n._n_nptr[1][1] == 'b'
- && def_symbol_in_progress->sy_symbol.ost_entry._n._n_nptr[1][2] == 'f')
+ if (strcmp (def_symbol_in_progress->sy_symbol.ost_entry._n._n_nptr,
+ ".bf") == 0)
{ /* .bf */
if (function_lineoff < 0)
{
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. */
+ /* 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.
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
- || (symbolP = symbol_find_base (S_GET_NAME (def_symbol_in_progress), DO_NOT_STRIP)) == NULL)
+ || def_symbol_in_progress->sy_forward != NULL
+ || (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);
reference is solved, then copy the segment id
from the forward symbol. */
SF_SET_GET_SEGMENT (def_symbol_in_progress);
+
+ /* FIXME: gcc can generate address expressions
+ here in unusual cases (search for "obscure"
+ in sdbout.c). We just ignore the offset
+ here, thus generating incorrect debugging
+ information. We ignore the rest of the
+ line just below. */
}
- /* Otherwise, it is the name of a non debug symbol and its value will be calculated later. */
+ /* Otherwise, it is the name of a non debug symbol and
+ its value will be calculated later. */
*input_line_pointer = name_end;
+
+ /* FIXME: this is to avoid an error message in the
+ FIXME case mentioned just above. */
+ while (! is_end_of_line[*input_line_pointer])
+ ++input_line_pointer;
}
else
{
&zero_address_frag);
tag_insert (S_GET_NAME (symbolP), symbolP);
- symbol_table_insert (symbolP);
} /* not found */
return (symbolP);
/* L* and C_EFCN symbols never merge. */
if (!SF_GET_LOCAL (symbolP)
+ && S_GET_STORAGE_CLASS (symbolP) != C_LABEL
&& (real_symbolP = symbol_find_base (S_GET_NAME (symbolP), DO_NOT_STRIP))
&& real_symbolP != symbolP)
{
frag */
subseg_new (frchain_ptr->frch_seg, frchain_ptr->frch_subseg);
+#ifndef SUB_SEGMENT_ALIGN
#define SUB_SEGMENT_ALIGN 1
- frag_align (SUB_SEGMENT_ALIGN, 0);
+#endif
+ frag_align (SUB_SEGMENT_ALIGN, NOP_OPCODE);
frag_wane (frag_now);
frag_now->fr_fix = 0;
know (frag_now->fr_next == NULL);
filehdr.f_nscns++;
}
-#ifndef ZERO_BASED_SEGMENTS
- /* See the comment at the previous ZERO_BASED_SEGMENTS check. */
+ /* Supposedly setting segment addresses non-zero
+ causes problems for some platforms, although it
+ shouldn't. If you define ZERO_BASED_SEGMENTS, all
+ the segments will be based at 0. Please don't make
+ this the default, since some systems (e.g., SVR3.2)
+ require the segments to be non-zero based. Ian
+ Taylor <ian@cygnus.com>. */
+
if (i == SEG_E2)
{
/* This is a special case, we leave the size alone, which
will have been made up from all and any lcomms seen. */
+#ifndef ZERO_BASED_SEGMENTS
addr += segment_info[i].scnhdr.s_size;
+#endif
}
else
{
+#ifndef ZERO_BASED_SEGMENTS
addr += size_section (abfd, i);
- }
+#else
+ size_section (abfd, i);
#endif
+ }
}
for (i = SEG_E0; i < SEG_UNKNOWN; i++)
{
fixup_mdeps (segment_info[i].frchainP->frch_root);
- fixup_segment (segment_info[i].fix_root, i);
+ fixup_segment (&segment_info[i], i);
}
#endif
len = section_name_end - section_name;
input_line_pointer++;
SKIP_WHITESPACE ();
- if (c == ',')
+
+ /* Some 386 assemblers stick a quoted string at the end of
+ a .section; we just ignore it. */
+ if (c == ',' && *input_line_pointer != '"')
{
exp = get_absolute_expression ();
}
- else if (*input_line_pointer == ',')
+ else if (*input_line_pointer == ','
+ && input_line_pointer[1] != '"')
{
-
input_line_pointer++;
exp = get_absolute_expression ();
}
else
{
exp = 0;
+ while (! is_end_of_line[*input_line_pointer])
+ ++input_line_pointer;
}
change_to_section (section_name, len, exp);
*section_name_end = c;
-
}
#if 1
static void
DEFUN (fixup_segment, (fixP, this_segment_type),
- register fixS * fixP AND
+ segment_info_type * segP AND
segT this_segment_type)
{
+ register fixS * fixP;
register symbolS *add_symbolP;
register symbolS *sub_symbolP;
register long add_number;
register segT add_symbol_segment = SEG_ABSOLUTE;
- for (; fixP; fixP = fixP->fx_next)
+ for (fixP = segP->fix_root; fixP; fixP = fixP->fx_next)
{
fragP = fixP->fx_frag;
know (fragP);
add_number += S_GET_VALUE (add_symbolP);
add_number -= md_pcrel_from (fixP);
+#ifdef TC_I386
+ /* On the 386 we must adjust by the segment
+ vaddr as well. Ian Taylor. */
+ add_number -= segP->scnhdr.s_vaddr;
+#endif
pcrel = 0; /* Lie. Don't want further pcrel processing. */
fixP->fx_addsy = NULL; /* No relocations please. */
}
#endif /* TC_I960 */
#ifdef TC_I386
/* 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>. */
+ 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>. */
add_number += S_GET_VALUE (add_symbolP);
#endif
break;
{
fixP->fx_addsy = &abs_symbol;
} /* if there's an add_symbol */
+#ifdef TC_I386
+ /* On the 386 we must adjust by the segment vaddr
+ as well. Ian Taylor. */
+ add_number -= segP->scnhdr.s_vaddr;
+#endif
} /* if pcrel */
if (!fixP->fx_bit_fixP)
along with GAS; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+#if 0
#define MASK_CHAR (0xFF) /* If your chars aren't 8 bits, you will
change this a bit. But then, GNU isn't
spozed to run on your machine anyway.
(RMS is so shortsighted sometimes.)
*/
+#else
+#define MASK_CHAR ((int)(unsigned char)-1)
+#endif
#define MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT (16)
/* This is the largest known floating point */
/* do 4361 style flonums. */
-/* Routines that read assembler source text to build spagetti in memory. */
-/* Another group of these functions is in the as-expr.c module */
+/* Routines that read assembler source text to build spagetti in memory.
+ Another group of these functions is in the expr.c module. */
#include <ctype.h>
#include "obstack.h"
#include "listing.h"
-char *input_line_pointer; /*->next char of source file to parse. */
+/* The NOP_OPCODE is for the alignment fill value.
+ * fill it a nop instruction so that the disassembler does not choke
+ * on it
+ */
+#ifndef NOP_OPCODE
+#define NOP_OPCODE 0x00
+#endif
+
+char *input_line_pointer; /*->next char of source file to parse. */
#if BITS_PER_CHAR != 8
/* The following table is indexed by[(char)] and will break if
die horribly;
#endif
- const char /* used by is_... macros. our ctype[] */
- lex_type[256] =
- {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* @ABCDEFGHIJKLMNO */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* PQRSTUVWXYZ[\]^_ */
- 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, /* _!"#$%&'()*+,-./ */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 0123456789:;<=>? */
- 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* @ABCDEFGHIJKLMNO */
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 3, /* PQRSTUVWXYZ[\]^_ */
- 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* `abcdefghijklmno */
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, /* pqrstuvwxyz{|}~. */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
- };
-
-
- /*
+/* used by is_... macros. our ctype[] */
+const char lex_type[256] =
+{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* @ABCDEFGHIJKLMNO */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* PQRSTUVWXYZ[\]^_ */
+ 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, /* _!"#$%&'()*+,-./ */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 0123456789:;<=>? */
+ 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* @ABCDEFGHIJKLMNO */
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 3, /* PQRSTUVWXYZ[\]^_ */
+ 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* `abcdefghijklmno */
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, /* pqrstuvwxyz{|}~. */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+
+/*
* In: a character.
* Out: 1 if this character ends a line.
*/
#define _ (0)
- char is_end_of_line[256] =
- {
+char is_end_of_line[256] =
+{
#ifdef CR_EOL
- _, _, _, _, _, _, _, _, _, _, 99, _, _, 99, _, _, /* @abcdefghijklmno */
+ _, _, _, _, _, _, _, _, _, _, 99, _, _, 99, _, _, /* @abcdefghijklmno */
#else
- _, _, _, _, _, _, _, _, _, _, 99, _, _, _, _, _, /* @abcdefghijklmno */
+ _, _, _, _, _, _, _, _, _, _, 99, _, _, _, _, _, /* @abcdefghijklmno */
#endif
- _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
- _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
- _, _, _, _, _, _, _, _, _, _, _, 99, _, _, _, _, /* 0123456789:;<=>? */
- _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
- _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
- _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
- _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
- _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
- _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
- _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
- _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
- _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ /* */
- };
+ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
+ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
+ _, _, _, _, _, _, _, _, _, _, _, 99, _, _, _, _, /* 0123456789:;<=>? */
+ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
+ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
+ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
+ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
+ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
+ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
+ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
+ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
+ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
+};
#undef _
- /* Functions private to this file. */
+/* Functions private to this file. */
+
+static char *buffer; /* 1st char of each buffer of lines is here. */
+static char *buffer_limit; /*->1 + last char in buffer. */
- static char *buffer; /* 1st char of each buffer of lines is here. */
- static char *buffer_limit; /*->1 + last char in buffer. */
+static char *bignum_low; /* Lowest char of bignum. */
+static char *bignum_limit; /* 1st illegal address of bignum. */
+static char *bignum_high; /* Highest char of bignum. */
+/* May point to (bignum_start-1). */
+/* Never >= bignum_limit. */
- static char *bignum_low; /* Lowest char of bignum. */
- static char *bignum_limit; /* 1st illegal address of bignum. */
- static char *bignum_high; /* Highest char of bignum. */
- /* May point to (bignum_start-1). */
- /* Never >= bignum_limit. */
- static char *old_buffer = 0; /* JF a hack */
- static char *old_input;
- static char *old_limit;
+static char *old_buffer = 0; /* JF a hack */
+static char *old_input;
+static char *old_limit;
- /* Variables for handling include file directory list. */
+/* Variables for handling include file directory list. */
- char **include_dirs; /* List of pointers to directories to
- search for .include's */
- int include_dir_count; /* How many are in the list */
- int include_dir_maxlen = 1;/* Length of longest in list */
+char **include_dirs; /* List of pointers to directories to
+ search for .include's */
+int include_dir_count; /* How many are in the list */
+int include_dir_maxlen = 1;/* Length of longest in list */
#ifndef WORKING_DOT_WORD
- struct broken_word *broken_words;
- int new_broken_words = 0;
+struct broken_word *broken_words;
+int new_broken_words = 0;
#endif
-#ifdef __STDC__
-
- static char *demand_copy_string (int *lenP);
- int is_it_end_of_statement (void);
- unsigned int next_char_of_string (void);
- static segT get_known_segmented_expression (expressionS * expP);
- static void grow_bignum (void);
- static void pobegin (void);
- void stringer (int append_zero);
-
-#else /* __STDC__ */
-
- static char *demand_copy_string ();
- int is_it_end_of_statement ();
- unsigned int next_char_of_string ();
- static segT get_known_segmented_expression ();
- static void grow_bignum ();
- static void pobegin ();
- void stringer ();
-
-#endif /* __STDC__ */
+static char *demand_copy_string PARAMS ((int *lenP));
+int is_it_end_of_statement PARAMS ((void));
+unsigned int next_char_of_string PARAMS ((void));
+static segT get_known_segmented_expression PARAMS ((expressionS * expP));
+static void grow_bignum PARAMS ((void));
+static void pobegin PARAMS ((void));
+void stringer PARAMS ((int append_zero));
- extern int listing;
+extern int listing;
\f
- void
- read_begin ()
+void
+read_begin ()
{
- char *p;
+ const char *p;
pobegin ();
obj_read_begin_hook ();
\f
/* set up pseudo-op tables */
-struct hash_control *
- po_hash = NULL; /* use before set up: NULL->address error */
+struct hash_control *po_hash = NULL; /* use before set up: NULL->address error */
#ifdef DONTDEF
void s_gdbline (), s_gdblinetab ();
void s_gdbbeg (), s_gdbblock (), s_gdbend (), s_gdbsym ();
#endif
-static const pseudo_typeS
- potable[] =
+static const pseudo_typeS potable[] =
{
{"abort", s_abort, 0},
{"align", s_align_ptwo, 0},
input_line_pointer++;
temp_fill = get_absolute_expression ();
}
+ else if (now_seg != SEG_DATA && now_seg != SEG_BSS)
+ temp_fill = NOP_OPCODE;
else
- {
- temp_fill = 0;
- }
+ temp_fill = 0;
/* Only make a frag if we HAVE to. . . */
if (temp && !need_pass_2)
frag_align (temp, (int) temp_fill);
input_line_pointer++;
temp_fill = get_absolute_expression ();
}
+ else if (now_seg != SEG_DATA && now_seg != SEG_BSS)
+ temp_fill = NOP_OPCODE;
else
temp_fill = 0;
/* Only make a frag if we HAVE to. . . */