1993-05-28 03:42:23 +08:00
|
|
|
/* ELF object file format
|
1997-01-04 06:13:05 +08:00
|
|
|
Copyright (C) 1992, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
|
1993-05-28 03:42:23 +08:00
|
|
|
|
|
|
|
This file is part of GAS, the GNU Assembler.
|
|
|
|
|
|
|
|
GAS is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as
|
|
|
|
published by the Free Software Foundation; either version 2,
|
|
|
|
or (at your option) any later version.
|
|
|
|
|
|
|
|
GAS is distributed in the hope that it will be useful, but
|
|
|
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
|
|
|
|
the GNU General Public License for more details.
|
|
|
|
|
1996-01-30 06:11:12 +08:00
|
|
|
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, 59 Temple Place - Suite 330, Boston, MA
|
|
|
|
02111-1307, USA. */
|
1993-05-28 03:42:23 +08:00
|
|
|
|
1995-05-11 07:08:40 +08:00
|
|
|
#define OBJ_HEADER "obj-elf.h"
|
1993-05-28 03:42:23 +08:00
|
|
|
#include "as.h"
|
1993-07-08 00:40:30 +08:00
|
|
|
#include "subsegs.h"
|
1993-05-28 03:42:23 +08:00
|
|
|
#include "obstack.h"
|
|
|
|
|
1995-05-11 07:08:40 +08:00
|
|
|
#ifndef ECOFF_DEBUGGING
|
|
|
|
#define ECOFF_DEBUGGING 0
|
1996-01-13 04:35:38 +08:00
|
|
|
#else
|
|
|
|
#define NEED_ECOFF_DEBUG
|
1995-05-11 07:08:40 +08:00
|
|
|
#endif
|
|
|
|
|
1996-01-13 04:35:38 +08:00
|
|
|
#ifdef NEED_ECOFF_DEBUG
|
1993-11-24 15:42:03 +08:00
|
|
|
#include "ecoff.h"
|
|
|
|
#endif
|
|
|
|
|
1994-01-16 01:31:05 +08:00
|
|
|
#ifdef TC_MIPS
|
|
|
|
#include "elf/mips.h"
|
|
|
|
#endif
|
|
|
|
|
1996-01-30 06:11:12 +08:00
|
|
|
#ifdef TC_PPC
|
|
|
|
#include "elf/ppc.h"
|
|
|
|
#endif
|
|
|
|
|
1996-01-13 04:35:38 +08:00
|
|
|
#ifdef NEED_ECOFF_DEBUG
|
1993-11-24 15:42:03 +08:00
|
|
|
static boolean elf_get_extr PARAMS ((asymbol *, EXTR *));
|
|
|
|
static void elf_set_index PARAMS ((asymbol *, bfd_size_type));
|
|
|
|
#endif
|
|
|
|
|
1993-09-14 05:32:07 +08:00
|
|
|
static void obj_elf_line PARAMS ((int));
|
|
|
|
void obj_elf_version PARAMS ((int));
|
|
|
|
static void obj_elf_size PARAMS ((int));
|
|
|
|
static void obj_elf_type PARAMS ((int));
|
|
|
|
static void obj_elf_ident PARAMS ((int));
|
|
|
|
static void obj_elf_weak PARAMS ((int));
|
|
|
|
static void obj_elf_local PARAMS ((int));
|
|
|
|
static void obj_elf_common PARAMS ((int));
|
1997-03-10 12:53:55 +08:00
|
|
|
static void obj_elf_symver PARAMS ((int));
|
1993-09-17 02:26:36 +08:00
|
|
|
static void obj_elf_data PARAMS ((int));
|
|
|
|
static void obj_elf_text PARAMS ((int));
|
1993-05-28 03:42:23 +08:00
|
|
|
|
1995-05-11 07:08:40 +08:00
|
|
|
static const pseudo_typeS elf_pseudo_table[] =
|
1993-07-08 00:40:30 +08:00
|
|
|
{
|
1993-08-20 13:29:24 +08:00
|
|
|
{"comm", obj_elf_common, 0},
|
1993-07-08 00:40:30 +08:00
|
|
|
{"ident", obj_elf_ident, 0},
|
1993-08-20 13:29:24 +08:00
|
|
|
{"local", obj_elf_local, 0},
|
1993-07-20 03:49:34 +08:00
|
|
|
{"previous", obj_elf_previous, 0},
|
1993-07-08 00:40:30 +08:00
|
|
|
{"section", obj_elf_section, 0},
|
1996-01-13 04:35:38 +08:00
|
|
|
{"section.s", obj_elf_section, 0},
|
|
|
|
{"sect", obj_elf_section, 0},
|
|
|
|
{"sect.s", obj_elf_section, 0},
|
1993-07-08 00:40:30 +08:00
|
|
|
{"size", obj_elf_size, 0},
|
|
|
|
{"type", obj_elf_type, 0},
|
|
|
|
{"version", obj_elf_version, 0},
|
1993-08-19 05:09:23 +08:00
|
|
|
{"weak", obj_elf_weak, 0},
|
1993-07-08 00:40:30 +08:00
|
|
|
|
1997-03-10 12:53:55 +08:00
|
|
|
/* These are used for stabs-in-elf configurations. */
|
1993-07-08 00:40:30 +08:00
|
|
|
{"line", obj_elf_line, 0},
|
|
|
|
|
1997-03-10 12:53:55 +08:00
|
|
|
/* This is a GNU extension to handle symbol versions. */
|
|
|
|
{"symver", obj_elf_symver, 0},
|
|
|
|
|
1993-07-20 03:49:34 +08:00
|
|
|
/* These are used for dwarf. */
|
|
|
|
{"2byte", cons, 2},
|
|
|
|
{"4byte", cons, 4},
|
1993-08-19 05:09:23 +08:00
|
|
|
{"8byte", cons, 8},
|
1993-07-20 03:49:34 +08:00
|
|
|
|
1993-09-17 02:26:36 +08:00
|
|
|
/* We need to trap the section changing calls to handle .previous. */
|
|
|
|
{"data", obj_elf_data, 0},
|
|
|
|
{"text", obj_elf_text, 0},
|
|
|
|
|
1995-05-11 07:08:40 +08:00
|
|
|
/* End sentinel. */
|
|
|
|
{NULL},
|
|
|
|
};
|
|
|
|
|
|
|
|
static const pseudo_typeS ecoff_debug_pseudo_table[] =
|
|
|
|
{
|
1996-01-13 04:35:38 +08:00
|
|
|
#ifdef NEED_ECOFF_DEBUG
|
1993-11-24 15:42:03 +08:00
|
|
|
/* COFF style debugging information for ECOFF. .ln is not used; .loc
|
|
|
|
is used instead. */
|
|
|
|
{ "def", ecoff_directive_def, 0 },
|
|
|
|
{ "dim", ecoff_directive_dim, 0 },
|
|
|
|
{ "endef", ecoff_directive_endef, 0 },
|
|
|
|
{ "file", ecoff_directive_file, 0 },
|
|
|
|
{ "scl", ecoff_directive_scl, 0 },
|
|
|
|
{ "tag", ecoff_directive_tag, 0 },
|
|
|
|
{ "val", ecoff_directive_val, 0 },
|
|
|
|
|
|
|
|
/* COFF debugging requires pseudo-ops .size and .type, but ELF
|
|
|
|
already has meanings for those. We use .esize and .etype
|
|
|
|
instead. These are only generated by gcc anyhow. */
|
|
|
|
{ "esize", ecoff_directive_size, 0 },
|
|
|
|
{ "etype", ecoff_directive_type, 0 },
|
|
|
|
|
|
|
|
/* ECOFF specific debugging information. */
|
|
|
|
{ "begin", ecoff_directive_begin, 0 },
|
|
|
|
{ "bend", ecoff_directive_bend, 0 },
|
|
|
|
{ "end", ecoff_directive_end, 0 },
|
|
|
|
{ "ent", ecoff_directive_ent, 0 },
|
|
|
|
{ "fmask", ecoff_directive_fmask, 0 },
|
|
|
|
{ "frame", ecoff_directive_frame, 0 },
|
|
|
|
{ "loc", ecoff_directive_loc, 0 },
|
|
|
|
{ "mask", ecoff_directive_mask, 0 },
|
|
|
|
|
1996-01-13 04:35:38 +08:00
|
|
|
/* Other ECOFF directives. */
|
|
|
|
{ "extern", ecoff_directive_extern, 0 },
|
|
|
|
|
1993-11-24 15:42:03 +08:00
|
|
|
/* These are used on Irix. I don't know how to implement them. */
|
|
|
|
{ "alias", s_ignore, 0 },
|
|
|
|
{ "bgnb", s_ignore, 0 },
|
|
|
|
{ "endb", s_ignore, 0 },
|
|
|
|
{ "lab", s_ignore, 0 },
|
|
|
|
{ "noalias", s_ignore, 0 },
|
|
|
|
{ "verstamp", s_ignore, 0 },
|
|
|
|
{ "vreg", s_ignore, 0 },
|
1996-01-13 04:35:38 +08:00
|
|
|
#endif
|
1993-11-24 15:42:03 +08:00
|
|
|
|
1993-07-08 00:40:30 +08:00
|
|
|
{NULL} /* end sentinel */
|
1993-05-28 03:42:23 +08:00
|
|
|
};
|
|
|
|
|
1993-08-19 05:09:23 +08:00
|
|
|
#undef NO_RELOC
|
1993-07-08 00:40:30 +08:00
|
|
|
#include "aout/aout64.h"
|
|
|
|
|
1996-10-07 23:25:58 +08:00
|
|
|
/* This is called when the assembler starts. */
|
|
|
|
|
|
|
|
void
|
|
|
|
elf_begin ()
|
|
|
|
{
|
|
|
|
/* Add symbols for the known sections to the symbol table. */
|
|
|
|
symbol_table_insert (section_symbol (bfd_get_section_by_name (stdoutput,
|
|
|
|
".text")));
|
|
|
|
symbol_table_insert (section_symbol (bfd_get_section_by_name (stdoutput,
|
|
|
|
".data")));
|
|
|
|
symbol_table_insert (section_symbol (bfd_get_section_by_name (stdoutput,
|
|
|
|
".bss")));
|
|
|
|
}
|
|
|
|
|
1995-05-11 07:08:40 +08:00
|
|
|
void
|
|
|
|
elf_pop_insert ()
|
|
|
|
{
|
|
|
|
pop_insert (elf_pseudo_table);
|
|
|
|
if (ECOFF_DEBUGGING)
|
|
|
|
pop_insert (ecoff_debug_pseudo_table);
|
|
|
|
}
|
|
|
|
|
|
|
|
static bfd_vma
|
|
|
|
elf_s_get_size (sym)
|
|
|
|
symbolS *sym;
|
|
|
|
{
|
|
|
|
return S_GET_SIZE (sym);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
elf_s_set_size (sym, sz)
|
|
|
|
symbolS *sym;
|
|
|
|
bfd_vma sz;
|
|
|
|
{
|
|
|
|
S_SET_SIZE (sym, sz);
|
|
|
|
}
|
|
|
|
|
|
|
|
static bfd_vma
|
|
|
|
elf_s_get_align (sym)
|
|
|
|
symbolS *sym;
|
|
|
|
{
|
|
|
|
return S_GET_ALIGN (sym);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
elf_s_set_align (sym, align)
|
|
|
|
symbolS *sym;
|
|
|
|
bfd_vma align;
|
|
|
|
{
|
|
|
|
S_SET_ALIGN (sym, align);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
elf_copy_symbol_attributes (dest, src)
|
|
|
|
symbolS *dest, *src;
|
|
|
|
{
|
|
|
|
OBJ_COPY_SYMBOL_ATTRIBUTES (dest, src);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
elf_sec_sym_ok_for_reloc (sec)
|
|
|
|
asection *sec;
|
|
|
|
{
|
|
|
|
return obj_sec_sym_ok_for_reloc (sec);
|
|
|
|
}
|
|
|
|
|
1993-07-08 00:40:30 +08:00
|
|
|
void
|
|
|
|
elf_file_symbol (s)
|
|
|
|
char *s;
|
|
|
|
{
|
|
|
|
symbolS *sym;
|
|
|
|
|
|
|
|
sym = symbol_new (s, absolute_section, (valueT) 0, (struct frag *) 0);
|
|
|
|
sym->sy_frag = &zero_address_frag;
|
|
|
|
sym->bsym->flags |= BSF_FILE;
|
|
|
|
|
|
|
|
if (symbol_rootP != sym)
|
|
|
|
{
|
|
|
|
symbol_remove (sym, &symbol_rootP, &symbol_lastP);
|
|
|
|
symbol_insert (sym, symbol_rootP, &symbol_rootP, &symbol_lastP);
|
|
|
|
#ifdef DEBUG
|
|
|
|
verify_symbol_chain (symbol_rootP, symbol_lastP);
|
|
|
|
#endif
|
|
|
|
}
|
1997-01-04 06:13:05 +08:00
|
|
|
|
|
|
|
#ifdef NEED_ECOFF_DEBUG
|
|
|
|
ecoff_new_file (s);
|
|
|
|
#endif
|
1993-07-08 00:40:30 +08:00
|
|
|
}
|
|
|
|
|
1993-08-20 13:29:24 +08:00
|
|
|
static void
|
1993-09-14 05:32:07 +08:00
|
|
|
obj_elf_common (ignore)
|
|
|
|
int ignore;
|
1993-08-20 13:29:24 +08:00
|
|
|
{
|
|
|
|
char *name;
|
|
|
|
char c;
|
|
|
|
char *p;
|
|
|
|
int temp, size;
|
|
|
|
symbolS *symbolP;
|
1993-10-27 05:01:15 +08:00
|
|
|
int have_align;
|
1993-08-20 13:29:24 +08:00
|
|
|
|
|
|
|
name = input_line_pointer;
|
|
|
|
c = get_symbol_end ();
|
|
|
|
/* just after name is now '\0' */
|
|
|
|
p = input_line_pointer;
|
|
|
|
*p = c;
|
|
|
|
SKIP_WHITESPACE ();
|
|
|
|
if (*input_line_pointer != ',')
|
|
|
|
{
|
|
|
|
as_bad ("Expected comma after symbol-name");
|
|
|
|
ignore_rest_of_line ();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
input_line_pointer++; /* skip ',' */
|
|
|
|
if ((temp = get_absolute_expression ()) < 0)
|
|
|
|
{
|
|
|
|
as_bad (".COMMon length (%d.) <0! Ignored.", temp);
|
|
|
|
ignore_rest_of_line ();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
size = temp;
|
|
|
|
*p = 0;
|
|
|
|
symbolP = symbol_find_or_make (name);
|
|
|
|
*p = c;
|
|
|
|
if (S_IS_DEFINED (symbolP))
|
|
|
|
{
|
|
|
|
as_bad ("Ignoring attempt to re-define symbol");
|
|
|
|
ignore_rest_of_line ();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (S_GET_VALUE (symbolP) != 0)
|
|
|
|
{
|
|
|
|
if (S_GET_VALUE (symbolP) != size)
|
|
|
|
{
|
|
|
|
as_warn ("Length of .comm \"%s\" is already %ld. Not changed to %d.",
|
|
|
|
S_GET_NAME (symbolP), (long) S_GET_VALUE (symbolP), size);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
know (symbolP->sy_frag == &zero_address_frag);
|
|
|
|
if (*input_line_pointer != ',')
|
1993-10-27 05:01:15 +08:00
|
|
|
have_align = 0;
|
|
|
|
else
|
1993-08-20 13:29:24 +08:00
|
|
|
{
|
1993-10-27 05:01:15 +08:00
|
|
|
have_align = 1;
|
|
|
|
input_line_pointer++;
|
|
|
|
SKIP_WHITESPACE ();
|
1993-08-20 13:29:24 +08:00
|
|
|
}
|
1993-10-27 05:01:15 +08:00
|
|
|
if (! have_align || *input_line_pointer != '"')
|
1993-08-20 13:29:24 +08:00
|
|
|
{
|
1993-10-27 05:01:15 +08:00
|
|
|
if (! have_align)
|
|
|
|
temp = 0;
|
|
|
|
else
|
1993-08-20 13:29:24 +08:00
|
|
|
{
|
1993-10-27 05:01:15 +08:00
|
|
|
temp = get_absolute_expression ();
|
|
|
|
if (temp < 0)
|
|
|
|
{
|
|
|
|
temp = 0;
|
|
|
|
as_warn ("Common alignment negative; 0 assumed");
|
|
|
|
}
|
1993-08-20 13:29:24 +08:00
|
|
|
}
|
|
|
|
if (symbolP->local)
|
|
|
|
{
|
|
|
|
segT old_sec;
|
|
|
|
int old_subsec;
|
1993-09-14 05:32:07 +08:00
|
|
|
char *pfrag;
|
1993-08-20 13:29:24 +08:00
|
|
|
int align;
|
|
|
|
|
1993-09-11 00:01:07 +08:00
|
|
|
/* allocate_bss: */
|
1993-08-20 13:29:24 +08:00
|
|
|
old_sec = now_seg;
|
|
|
|
old_subsec = now_subseg;
|
1996-01-13 04:35:38 +08:00
|
|
|
if (temp)
|
|
|
|
{
|
|
|
|
/* convert to a power of 2 alignment */
|
|
|
|
for (align = 0; (temp & 1) == 0; temp >>= 1, ++align);
|
|
|
|
if (temp != 1)
|
|
|
|
{
|
|
|
|
as_bad ("Common alignment not a power of 2");
|
|
|
|
ignore_rest_of_line ();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
align = 0;
|
1993-08-20 13:29:24 +08:00
|
|
|
record_alignment (bss_section, align);
|
|
|
|
subseg_set (bss_section, 0);
|
|
|
|
if (align)
|
1997-03-10 12:53:55 +08:00
|
|
|
frag_align (align, 0, 0);
|
1993-08-20 13:29:24 +08:00
|
|
|
if (S_GET_SEGMENT (symbolP) == bss_section)
|
|
|
|
symbolP->sy_frag->fr_symbol = 0;
|
|
|
|
symbolP->sy_frag = frag_now;
|
1993-09-14 05:32:07 +08:00
|
|
|
pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, size,
|
|
|
|
(char *) 0);
|
|
|
|
*pfrag = 0;
|
1996-01-13 04:35:38 +08:00
|
|
|
S_SET_SIZE (symbolP, size);
|
1993-08-20 13:29:24 +08:00
|
|
|
S_SET_SEGMENT (symbolP, bss_section);
|
|
|
|
S_CLEAR_EXTERNAL (symbolP);
|
|
|
|
subseg_set (old_sec, old_subsec);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
allocate_common:
|
1993-09-14 05:32:07 +08:00
|
|
|
S_SET_VALUE (symbolP, (valueT) size);
|
1995-05-11 07:08:40 +08:00
|
|
|
S_SET_ALIGN (symbolP, temp);
|
1993-08-20 13:29:24 +08:00
|
|
|
S_SET_EXTERNAL (symbolP);
|
|
|
|
/* should be common, but this is how gas does it for now */
|
1995-05-11 07:08:40 +08:00
|
|
|
S_SET_SEGMENT (symbolP, bfd_und_section_ptr);
|
1993-08-20 13:29:24 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
input_line_pointer++;
|
|
|
|
/* @@ Some use the dot, some don't. Can we get some consistency?? */
|
|
|
|
if (*input_line_pointer == '.')
|
|
|
|
input_line_pointer++;
|
|
|
|
/* @@ Some say data, some say bss. */
|
|
|
|
if (strncmp (input_line_pointer, "bss\"", 4)
|
|
|
|
&& strncmp (input_line_pointer, "data\"", 5))
|
|
|
|
{
|
|
|
|
while (*--input_line_pointer != '"')
|
|
|
|
;
|
|
|
|
input_line_pointer--;
|
|
|
|
goto bad_common_segment;
|
|
|
|
}
|
|
|
|
while (*input_line_pointer++ != '"')
|
|
|
|
;
|
|
|
|
goto allocate_common;
|
|
|
|
}
|
1997-03-10 12:53:55 +08:00
|
|
|
|
|
|
|
symbolP->bsym->flags |= BSF_OBJECT;
|
|
|
|
|
1993-08-20 13:29:24 +08:00
|
|
|
demand_empty_rest_of_line ();
|
|
|
|
return;
|
|
|
|
|
|
|
|
{
|
|
|
|
bad_common_segment:
|
|
|
|
p = input_line_pointer;
|
|
|
|
while (*p && *p != '\n')
|
|
|
|
p++;
|
|
|
|
c = *p;
|
|
|
|
*p = '\0';
|
|
|
|
as_bad ("bad .common segment %s", input_line_pointer + 1);
|
|
|
|
*p = c;
|
|
|
|
input_line_pointer = p;
|
|
|
|
ignore_rest_of_line ();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1996-10-14 23:40:15 +08:00
|
|
|
static void
|
1993-09-14 05:32:07 +08:00
|
|
|
obj_elf_local (ignore)
|
|
|
|
int ignore;
|
1993-08-20 13:29:24 +08:00
|
|
|
{
|
|
|
|
char *name;
|
|
|
|
int c;
|
|
|
|
symbolS *symbolP;
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
name = input_line_pointer;
|
|
|
|
c = get_symbol_end ();
|
|
|
|
symbolP = symbol_find_or_make (name);
|
|
|
|
*input_line_pointer = c;
|
|
|
|
SKIP_WHITESPACE ();
|
|
|
|
S_CLEAR_EXTERNAL (symbolP);
|
|
|
|
symbolP->local = 1;
|
|
|
|
if (c == ',')
|
|
|
|
{
|
|
|
|
input_line_pointer++;
|
|
|
|
SKIP_WHITESPACE ();
|
|
|
|
if (*input_line_pointer == '\n')
|
|
|
|
c = '\n';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while (c == ',');
|
|
|
|
demand_empty_rest_of_line ();
|
|
|
|
}
|
|
|
|
|
1996-10-14 23:40:15 +08:00
|
|
|
static void
|
1993-09-14 05:32:07 +08:00
|
|
|
obj_elf_weak (ignore)
|
|
|
|
int ignore;
|
1993-08-19 05:09:23 +08:00
|
|
|
{
|
|
|
|
char *name;
|
|
|
|
int c;
|
|
|
|
symbolS *symbolP;
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
name = input_line_pointer;
|
|
|
|
c = get_symbol_end ();
|
|
|
|
symbolP = symbol_find_or_make (name);
|
|
|
|
*input_line_pointer = c;
|
|
|
|
SKIP_WHITESPACE ();
|
|
|
|
S_SET_WEAK (symbolP);
|
|
|
|
symbolP->local = 1;
|
|
|
|
if (c == ',')
|
|
|
|
{
|
|
|
|
input_line_pointer++;
|
|
|
|
SKIP_WHITESPACE ();
|
|
|
|
if (*input_line_pointer == '\n')
|
|
|
|
c = '\n';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while (c == ',');
|
|
|
|
demand_empty_rest_of_line ();
|
|
|
|
}
|
|
|
|
|
1993-07-20 03:49:34 +08:00
|
|
|
static segT previous_section;
|
|
|
|
static int previous_subsection;
|
|
|
|
|
1993-10-27 05:01:15 +08:00
|
|
|
/* Handle the .section pseudo-op. This code supports two different
|
1996-10-14 23:40:15 +08:00
|
|
|
syntaxes.
|
1993-10-27 05:01:15 +08:00
|
|
|
|
|
|
|
The first is found on Solaris, and looks like
|
|
|
|
.section ".sec1",#alloc,#execinstr,#write
|
|
|
|
Here the names after '#' are the SHF_* flags to turn on for the
|
|
|
|
section. I'm not sure how it determines the SHT_* type (BFD
|
|
|
|
doesn't really give us control over the type, anyhow).
|
|
|
|
|
|
|
|
The second format is found on UnixWare, and probably most SVR4
|
|
|
|
machines, and looks like
|
|
|
|
.section .sec1,"a",@progbits
|
|
|
|
The quoted string may contain any combination of a, w, x, and
|
|
|
|
represents the SHF_* flags to turn on for the section. The string
|
|
|
|
beginning with '@' can be progbits or nobits. There should be
|
|
|
|
other possibilities, but I don't know what they are. In any case,
|
|
|
|
BFD doesn't really let us set the section type. */
|
|
|
|
|
1994-01-16 01:31:05 +08:00
|
|
|
/* Certain named sections have particular defined types, listed on p.
|
|
|
|
4-19 of the ABI. */
|
|
|
|
struct special_section
|
|
|
|
{
|
|
|
|
const char *name;
|
|
|
|
int type;
|
|
|
|
int attributes;
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct special_section special_sections[] =
|
|
|
|
{
|
|
|
|
{ ".bss", SHT_NOBITS, SHF_ALLOC + SHF_WRITE },
|
|
|
|
{ ".comment", SHT_PROGBITS, 0 },
|
|
|
|
{ ".data", SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
|
|
|
|
{ ".data1", SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
|
|
|
|
{ ".debug", SHT_PROGBITS, 0 },
|
|
|
|
{ ".fini", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR },
|
|
|
|
{ ".init", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR },
|
|
|
|
{ ".line", SHT_PROGBITS, 0 },
|
|
|
|
{ ".note", SHT_NOTE, 0 },
|
|
|
|
{ ".rodata", SHT_PROGBITS, SHF_ALLOC },
|
|
|
|
{ ".rodata1", SHT_PROGBITS, SHF_ALLOC },
|
|
|
|
{ ".text", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR },
|
|
|
|
|
|
|
|
#ifdef ELF_TC_SPECIAL_SECTIONS
|
|
|
|
ELF_TC_SPECIAL_SECTIONS
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
/* The following section names are special, but they can not
|
|
|
|
reasonably appear in assembler code. Some of the attributes are
|
|
|
|
processor dependent. */
|
|
|
|
{ ".dynamic", SHT_DYNAMIC, SHF_ALLOC /* + SHF_WRITE */ },
|
|
|
|
{ ".dynstr", SHT_STRTAB, SHF_ALLOC },
|
|
|
|
{ ".dynsym", SHT_DYNSYM, SHF_ALLOC },
|
|
|
|
{ ".got", SHT_PROGBITS, 0 },
|
|
|
|
{ ".hash", SHT_HASH, SHF_ALLOC },
|
|
|
|
{ ".interp", SHT_PROGBITS, /* SHF_ALLOC */ },
|
|
|
|
{ ".plt", SHT_PROGBITS, 0 },
|
|
|
|
{ ".shstrtab",SHT_STRTAB, 0 },
|
|
|
|
{ ".strtab", SHT_STRTAB, /* SHF_ALLOC */ },
|
|
|
|
{ ".symtab", SHT_SYMTAB, /* SHF_ALLOC */ },
|
|
|
|
#endif
|
|
|
|
|
|
|
|
{ NULL, 0, 0 }
|
|
|
|
};
|
|
|
|
|
1993-08-05 07:10:43 +08:00
|
|
|
void
|
1993-05-28 03:42:23 +08:00
|
|
|
obj_elf_section (xxx)
|
|
|
|
int xxx;
|
|
|
|
{
|
|
|
|
char *string;
|
1993-09-17 02:26:36 +08:00
|
|
|
int new_sec;
|
1993-10-27 05:01:15 +08:00
|
|
|
segT sec;
|
1994-01-16 01:31:05 +08:00
|
|
|
int type, attr;
|
|
|
|
int i;
|
1993-10-27 05:01:15 +08:00
|
|
|
flagword flags;
|
1996-10-07 23:25:58 +08:00
|
|
|
symbolS *secsym;
|
1993-05-28 03:42:23 +08:00
|
|
|
|
1995-05-11 07:08:40 +08:00
|
|
|
#ifdef md_flush_pending_output
|
|
|
|
md_flush_pending_output ();
|
|
|
|
#endif
|
|
|
|
|
1996-01-13 04:35:38 +08:00
|
|
|
if (flag_mri)
|
|
|
|
{
|
1996-03-01 03:04:49 +08:00
|
|
|
char mri_type;
|
1996-01-13 04:35:38 +08:00
|
|
|
|
|
|
|
previous_section = now_seg;
|
|
|
|
previous_subsection = now_subseg;
|
|
|
|
|
1996-03-01 03:04:49 +08:00
|
|
|
s_mri_sect (&mri_type);
|
1996-01-13 04:35:38 +08:00
|
|
|
|
|
|
|
#ifdef md_elf_section_change_hook
|
|
|
|
md_elf_section_change_hook ();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
1993-08-19 05:09:23 +08:00
|
|
|
/* Get name of section. */
|
1993-10-27 05:01:15 +08:00
|
|
|
SKIP_WHITESPACE ();
|
1993-07-20 03:49:34 +08:00
|
|
|
if (*input_line_pointer == '"')
|
1993-10-27 05:01:15 +08:00
|
|
|
{
|
|
|
|
string = demand_copy_C_string (&xxx);
|
|
|
|
if (string == NULL)
|
|
|
|
{
|
|
|
|
ignore_rest_of_line ();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
1993-07-20 03:49:34 +08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
char *p = input_line_pointer;
|
|
|
|
char c;
|
|
|
|
while (0 == strchr ("\n\t,; ", *p))
|
|
|
|
p++;
|
1993-10-27 05:01:15 +08:00
|
|
|
if (p == input_line_pointer)
|
|
|
|
{
|
|
|
|
as_warn ("Missing section name");
|
|
|
|
ignore_rest_of_line ();
|
|
|
|
return;
|
|
|
|
}
|
1993-07-20 03:49:34 +08:00
|
|
|
c = *p;
|
|
|
|
*p = 0;
|
1993-09-14 05:32:07 +08:00
|
|
|
string = xmalloc ((unsigned long) (p - input_line_pointer + 1));
|
1993-07-20 03:49:34 +08:00
|
|
|
strcpy (string, input_line_pointer);
|
|
|
|
*p = c;
|
|
|
|
input_line_pointer = p;
|
|
|
|
}
|
1993-10-27 05:01:15 +08:00
|
|
|
|
|
|
|
/* Switch to the section, creating it if necessary. */
|
|
|
|
previous_section = now_seg;
|
|
|
|
previous_subsection = now_subseg;
|
|
|
|
|
|
|
|
new_sec = bfd_get_section_by_name (stdoutput, string) == NULL;
|
|
|
|
sec = subseg_new (string, 0);
|
|
|
|
|
|
|
|
/* If this section already existed, we don't bother to change the
|
|
|
|
flag values. */
|
|
|
|
if (! new_sec)
|
|
|
|
{
|
|
|
|
while (! is_end_of_line[(unsigned char) *input_line_pointer])
|
|
|
|
++input_line_pointer;
|
|
|
|
++input_line_pointer;
|
1995-05-11 07:08:40 +08:00
|
|
|
|
|
|
|
#ifdef md_elf_section_change_hook
|
|
|
|
md_elf_section_change_hook ();
|
|
|
|
#endif
|
|
|
|
|
1993-10-27 05:01:15 +08:00
|
|
|
return;
|
|
|
|
}
|
1993-08-19 05:09:23 +08:00
|
|
|
|
1993-05-28 03:42:23 +08:00
|
|
|
SKIP_WHITESPACE ();
|
1994-01-16 01:31:05 +08:00
|
|
|
|
|
|
|
type = SHT_NULL;
|
|
|
|
attr = 0;
|
|
|
|
|
|
|
|
if (*input_line_pointer == ',')
|
1993-10-27 05:01:15 +08:00
|
|
|
{
|
|
|
|
/* Skip the comma. */
|
|
|
|
++input_line_pointer;
|
1993-08-19 05:09:23 +08:00
|
|
|
|
1993-10-27 05:01:15 +08:00
|
|
|
SKIP_WHITESPACE ();
|
1993-08-19 05:09:23 +08:00
|
|
|
if (*input_line_pointer == '"')
|
|
|
|
{
|
1993-10-27 05:01:15 +08:00
|
|
|
/* Pick up a string with a combination of a, w, x. */
|
|
|
|
++input_line_pointer;
|
|
|
|
while (*input_line_pointer != '"')
|
|
|
|
{
|
|
|
|
switch (*input_line_pointer)
|
|
|
|
{
|
|
|
|
case 'a':
|
1994-01-16 01:31:05 +08:00
|
|
|
attr |= SHF_ALLOC;
|
1993-10-27 05:01:15 +08:00
|
|
|
break;
|
|
|
|
case 'w':
|
1994-01-16 01:31:05 +08:00
|
|
|
attr |= SHF_WRITE;
|
1993-10-27 05:01:15 +08:00
|
|
|
break;
|
|
|
|
case 'x':
|
1994-01-16 01:31:05 +08:00
|
|
|
attr |= SHF_EXECINSTR;
|
1993-10-27 05:01:15 +08:00
|
|
|
break;
|
|
|
|
default:
|
1996-01-13 04:35:38 +08:00
|
|
|
{
|
|
|
|
char *bad_msg = "Bad .section directive: want a,w,x in string";
|
|
|
|
#ifdef md_elf_section_letter
|
|
|
|
int md_attr = md_elf_section_letter (*input_line_pointer, &bad_msg);
|
|
|
|
if (md_attr)
|
|
|
|
attr |= md_attr;
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
as_warn (bad_msg);
|
|
|
|
ignore_rest_of_line ();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
1993-10-27 05:01:15 +08:00
|
|
|
}
|
|
|
|
++input_line_pointer;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Skip the closing quote. */
|
|
|
|
++input_line_pointer;
|
|
|
|
|
1993-08-19 05:09:23 +08:00
|
|
|
SKIP_WHITESPACE ();
|
1993-10-27 05:01:15 +08:00
|
|
|
if (*input_line_pointer == ',')
|
|
|
|
{
|
|
|
|
++input_line_pointer;
|
|
|
|
SKIP_WHITESPACE ();
|
|
|
|
if (*input_line_pointer == '@')
|
|
|
|
{
|
|
|
|
++input_line_pointer;
|
|
|
|
if (strncmp (input_line_pointer, "progbits",
|
|
|
|
sizeof "progbits" - 1) == 0)
|
|
|
|
{
|
1994-01-16 01:31:05 +08:00
|
|
|
type = SHT_PROGBITS;
|
1993-10-27 05:01:15 +08:00
|
|
|
input_line_pointer += sizeof "progbits" - 1;
|
|
|
|
}
|
|
|
|
else if (strncmp (input_line_pointer, "nobits",
|
|
|
|
sizeof "nobits" - 1) == 0)
|
|
|
|
{
|
1994-01-16 01:31:05 +08:00
|
|
|
type = SHT_NOBITS;
|
1993-10-27 05:01:15 +08:00
|
|
|
input_line_pointer += sizeof "nobits" - 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
1996-01-13 04:35:38 +08:00
|
|
|
#ifdef md_elf_section_type
|
|
|
|
int md_type = md_elf_section_type (&input_line_pointer);
|
|
|
|
if (md_type)
|
|
|
|
type = md_type;
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
as_warn ("Unrecognized section type");
|
|
|
|
ignore_rest_of_line ();
|
|
|
|
}
|
1993-10-27 05:01:15 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1993-08-19 05:09:23 +08:00
|
|
|
}
|
1993-10-27 05:01:15 +08:00
|
|
|
else
|
1993-05-28 03:42:23 +08:00
|
|
|
{
|
1993-10-27 05:01:15 +08:00
|
|
|
do
|
|
|
|
{
|
|
|
|
SKIP_WHITESPACE ();
|
|
|
|
if (*input_line_pointer != '#')
|
|
|
|
{
|
|
|
|
as_warn ("Bad .section directive");
|
|
|
|
ignore_rest_of_line ();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
++input_line_pointer;
|
|
|
|
if (strncmp (input_line_pointer, "write",
|
|
|
|
sizeof "write" - 1) == 0)
|
|
|
|
{
|
1994-01-16 01:31:05 +08:00
|
|
|
attr |= SHF_WRITE;
|
1993-10-27 05:01:15 +08:00
|
|
|
input_line_pointer += sizeof "write" - 1;
|
|
|
|
}
|
|
|
|
else if (strncmp (input_line_pointer, "alloc",
|
|
|
|
sizeof "alloc" - 1) == 0)
|
|
|
|
{
|
1994-01-16 01:31:05 +08:00
|
|
|
attr |= SHF_ALLOC;
|
1993-10-27 05:01:15 +08:00
|
|
|
input_line_pointer += sizeof "alloc" - 1;
|
|
|
|
}
|
|
|
|
else if (strncmp (input_line_pointer, "execinstr",
|
|
|
|
sizeof "execinstr" - 1) == 0)
|
|
|
|
{
|
1994-01-16 01:31:05 +08:00
|
|
|
attr |= SHF_EXECINSTR;
|
1993-10-27 05:01:15 +08:00
|
|
|
input_line_pointer += sizeof "execinstr" - 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
1996-01-13 04:35:38 +08:00
|
|
|
#ifdef md_elf_section_word
|
|
|
|
int md_attr = md_elf_section_word (&input_line_pointer);
|
|
|
|
if (md_attr)
|
|
|
|
attr |= md_attr;
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
as_warn ("Unrecognized section attribute");
|
|
|
|
ignore_rest_of_line ();
|
|
|
|
return;
|
|
|
|
}
|
1993-10-27 05:01:15 +08:00
|
|
|
}
|
|
|
|
SKIP_WHITESPACE ();
|
|
|
|
}
|
|
|
|
while (*input_line_pointer++ == ',');
|
|
|
|
--input_line_pointer;
|
1993-05-28 03:42:23 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1994-01-16 01:31:05 +08:00
|
|
|
/* See if this is one of the special sections. */
|
|
|
|
for (i = 0; special_sections[i].name != NULL; i++)
|
|
|
|
{
|
|
|
|
if (string[1] == special_sections[i].name[1]
|
|
|
|
&& strcmp (string, special_sections[i].name) == 0)
|
|
|
|
{
|
|
|
|
if (type == SHT_NULL)
|
|
|
|
type = special_sections[i].type;
|
|
|
|
else if (type != special_sections[i].type)
|
|
|
|
as_warn ("Setting incorrect section type for %s", string);
|
|
|
|
|
|
|
|
if ((attr &~ special_sections[i].attributes) != 0)
|
1997-03-10 12:53:55 +08:00
|
|
|
{
|
|
|
|
/* As a GNU extension, we permit a .note section to be
|
|
|
|
allocatable. If the linker sees an allocateable
|
|
|
|
.note section, it will create a PT_NOTE segment in
|
|
|
|
the output file. */
|
|
|
|
if (strcmp (string, ".note") != 0
|
|
|
|
|| attr != SHF_ALLOC)
|
|
|
|
as_warn ("Setting incorrect section attributes for %s",
|
|
|
|
string);
|
|
|
|
}
|
1994-01-16 01:31:05 +08:00
|
|
|
attr |= special_sections[i].attributes;
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
flags = (SEC_RELOC
|
|
|
|
| ((attr & SHF_WRITE) ? 0 : SEC_READONLY)
|
1996-10-07 23:25:58 +08:00
|
|
|
| ((attr & SHF_ALLOC) ? SEC_ALLOC : 0)
|
|
|
|
| (((attr & SHF_ALLOC) && type != SHT_NOBITS) ? SEC_LOAD : 0)
|
1994-01-16 01:31:05 +08:00
|
|
|
| ((attr & SHF_EXECINSTR) ? SEC_CODE : 0));
|
1996-10-07 23:25:58 +08:00
|
|
|
if (special_sections[i].name == NULL)
|
1994-01-16 01:31:05 +08:00
|
|
|
{
|
1996-10-07 23:25:58 +08:00
|
|
|
if (type == SHT_PROGBITS)
|
|
|
|
flags |= SEC_ALLOC | SEC_LOAD;
|
|
|
|
else if (type == SHT_NOBITS)
|
|
|
|
{
|
|
|
|
flags |= SEC_ALLOC;
|
|
|
|
flags &=~ SEC_LOAD;
|
|
|
|
}
|
1996-01-13 04:35:38 +08:00
|
|
|
|
|
|
|
#ifdef md_elf_section_flags
|
1996-10-07 23:25:58 +08:00
|
|
|
flags = md_elf_section_flags (flags, attr, type);
|
1996-01-13 04:35:38 +08:00
|
|
|
#endif
|
1996-10-07 23:25:58 +08:00
|
|
|
}
|
1994-01-16 01:31:05 +08:00
|
|
|
|
1993-10-27 05:01:15 +08:00
|
|
|
bfd_set_section_flags (stdoutput, sec, flags);
|
1993-09-17 02:26:36 +08:00
|
|
|
|
1996-10-07 23:25:58 +08:00
|
|
|
/* Add a symbol for this section to the symbol table. */
|
|
|
|
secsym = symbol_find (string);
|
|
|
|
if (secsym != NULL)
|
|
|
|
secsym->bsym = sec->symbol;
|
|
|
|
else
|
|
|
|
symbol_table_insert (section_symbol (sec));
|
|
|
|
|
1995-05-11 07:08:40 +08:00
|
|
|
#ifdef md_elf_section_change_hook
|
|
|
|
md_elf_section_change_hook ();
|
|
|
|
#endif
|
|
|
|
|
1993-10-27 05:01:15 +08:00
|
|
|
demand_empty_rest_of_line ();
|
1993-09-17 02:26:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Change to the .data section. */
|
|
|
|
|
|
|
|
static void
|
|
|
|
obj_elf_data (i)
|
|
|
|
int i;
|
|
|
|
{
|
1997-03-14 00:21:34 +08:00
|
|
|
#ifdef md_flush_pending_output
|
|
|
|
md_flush_pending_output ();
|
|
|
|
#endif
|
|
|
|
|
1993-09-17 02:26:36 +08:00
|
|
|
previous_section = now_seg;
|
|
|
|
previous_subsection = now_subseg;
|
|
|
|
s_data (i);
|
1997-03-14 00:21:34 +08:00
|
|
|
|
|
|
|
#ifdef md_elf_section_change_hook
|
|
|
|
md_elf_section_change_hook ();
|
|
|
|
#endif
|
1993-09-17 02:26:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Change to the .text section. */
|
|
|
|
|
|
|
|
static void
|
|
|
|
obj_elf_text (i)
|
|
|
|
int i;
|
|
|
|
{
|
1997-03-14 00:21:34 +08:00
|
|
|
#ifdef md_flush_pending_output
|
|
|
|
md_flush_pending_output ();
|
|
|
|
#endif
|
|
|
|
|
1993-09-17 02:26:36 +08:00
|
|
|
previous_section = now_seg;
|
|
|
|
previous_subsection = now_subseg;
|
|
|
|
s_text (i);
|
1997-03-14 00:21:34 +08:00
|
|
|
|
|
|
|
#ifdef md_elf_section_change_hook
|
|
|
|
md_elf_section_change_hook ();
|
|
|
|
#endif
|
1993-05-28 03:42:23 +08:00
|
|
|
}
|
|
|
|
|
1993-08-05 07:10:43 +08:00
|
|
|
void
|
1993-09-14 05:32:07 +08:00
|
|
|
obj_elf_previous (ignore)
|
|
|
|
int ignore;
|
1993-07-20 03:49:34 +08:00
|
|
|
{
|
|
|
|
if (previous_section == 0)
|
|
|
|
{
|
|
|
|
as_bad (".previous without corresponding .section; ignored");
|
|
|
|
return;
|
|
|
|
}
|
1997-03-14 00:21:34 +08:00
|
|
|
|
|
|
|
#ifdef md_flush_pending_output
|
|
|
|
md_flush_pending_output ();
|
|
|
|
#endif
|
|
|
|
|
1993-07-20 03:49:34 +08:00
|
|
|
subseg_set (previous_section, previous_subsection);
|
|
|
|
previous_section = 0;
|
1997-03-14 00:21:34 +08:00
|
|
|
|
|
|
|
#ifdef md_elf_section_change_hook
|
|
|
|
md_elf_section_change_hook ();
|
|
|
|
#endif
|
1993-07-20 03:49:34 +08:00
|
|
|
}
|
|
|
|
|
1993-07-08 00:40:30 +08:00
|
|
|
static void
|
1993-09-14 05:32:07 +08:00
|
|
|
obj_elf_line (ignore)
|
|
|
|
int ignore;
|
1993-07-08 00:40:30 +08:00
|
|
|
{
|
|
|
|
/* Assume delimiter is part of expression. BSD4.2 as fails with
|
|
|
|
delightful bug, so we are not being incompatible here. */
|
|
|
|
new_logical_line ((char *) NULL, (int) (get_absolute_expression ()));
|
|
|
|
demand_empty_rest_of_line ();
|
|
|
|
}
|
1993-05-28 03:42:23 +08:00
|
|
|
|
1997-03-10 12:53:55 +08:00
|
|
|
/* This handle the .symver pseudo-op, which is used to specify a
|
|
|
|
symbol version. The syntax is ``.symver NAME,SYMVERNAME''.
|
|
|
|
SYMVERNAME may contain ELF_VER_CHR ('@') characters. This
|
|
|
|
pseudo-op causes the assembler to emit a symbol named SYMVERNAME
|
|
|
|
with the same value as the symbol NAME. */
|
|
|
|
|
|
|
|
static void
|
|
|
|
obj_elf_symver (ignore)
|
|
|
|
int ignore;
|
|
|
|
{
|
|
|
|
char *name;
|
|
|
|
char c;
|
|
|
|
symbolS *sym;
|
|
|
|
|
|
|
|
name = input_line_pointer;
|
|
|
|
c = get_symbol_end ();
|
|
|
|
|
|
|
|
sym = symbol_find_or_make (name);
|
|
|
|
|
|
|
|
*input_line_pointer = c;
|
1997-03-14 00:21:34 +08:00
|
|
|
|
|
|
|
if (sym->sy_obj.versioned_name != NULL)
|
|
|
|
{
|
|
|
|
as_bad ("multiple .symver directives for symbol `%s'",
|
|
|
|
S_GET_NAME (sym));
|
|
|
|
ignore_rest_of_line ();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
1997-03-10 12:53:55 +08:00
|
|
|
SKIP_WHITESPACE ();
|
|
|
|
if (*input_line_pointer != ',')
|
|
|
|
{
|
|
|
|
as_bad ("expected comma after name in .symver");
|
|
|
|
ignore_rest_of_line ();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
++input_line_pointer;
|
|
|
|
name = input_line_pointer;
|
|
|
|
while (1)
|
|
|
|
{
|
|
|
|
c = get_symbol_end ();
|
|
|
|
if (c != ELF_VER_CHR)
|
|
|
|
break;
|
|
|
|
*input_line_pointer++ = c;
|
|
|
|
}
|
|
|
|
|
|
|
|
sym->sy_obj.versioned_name = xstrdup (name);
|
|
|
|
|
|
|
|
*input_line_pointer = c;
|
|
|
|
|
1997-03-14 00:21:34 +08:00
|
|
|
if (strchr (sym->sy_obj.versioned_name, ELF_VER_CHR) == NULL)
|
|
|
|
{
|
|
|
|
as_bad ("missing version name in `%s' for symbol `%s'",
|
|
|
|
sym->sy_obj.versioned_name, S_GET_NAME (sym));
|
|
|
|
ignore_rest_of_line ();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
1997-03-10 12:53:55 +08:00
|
|
|
demand_empty_rest_of_line ();
|
|
|
|
}
|
|
|
|
|
1996-10-14 23:40:15 +08:00
|
|
|
void
|
1993-07-08 00:40:30 +08:00
|
|
|
obj_read_begin_hook ()
|
1993-05-28 03:42:23 +08:00
|
|
|
{
|
1996-01-13 04:35:38 +08:00
|
|
|
#ifdef NEED_ECOFF_DEBUG
|
1995-05-11 07:08:40 +08:00
|
|
|
if (ECOFF_DEBUGGING)
|
|
|
|
ecoff_read_begin_hook ();
|
1996-01-13 04:35:38 +08:00
|
|
|
#endif
|
1993-05-28 03:42:23 +08:00
|
|
|
}
|
|
|
|
|
1996-10-14 23:40:15 +08:00
|
|
|
void
|
1993-07-08 00:40:30 +08:00
|
|
|
obj_symbol_new_hook (symbolP)
|
|
|
|
symbolS *symbolP;
|
1993-05-28 03:42:23 +08:00
|
|
|
{
|
1997-03-10 12:53:55 +08:00
|
|
|
symbolP->sy_obj.size = NULL;
|
|
|
|
symbolP->sy_obj.versioned_name = NULL;
|
1993-05-28 03:42:23 +08:00
|
|
|
|
1996-01-13 04:35:38 +08:00
|
|
|
#ifdef NEED_ECOFF_DEBUG
|
1995-05-11 07:08:40 +08:00
|
|
|
if (ECOFF_DEBUGGING)
|
|
|
|
ecoff_symbol_new_hook (symbolP);
|
1996-01-13 04:35:38 +08:00
|
|
|
#endif
|
1993-05-28 03:42:23 +08:00
|
|
|
}
|
|
|
|
|
1996-10-14 23:40:15 +08:00
|
|
|
void
|
1993-09-14 05:32:07 +08:00
|
|
|
obj_elf_version (ignore)
|
|
|
|
int ignore;
|
1993-05-28 03:42:23 +08:00
|
|
|
{
|
1993-07-08 00:40:30 +08:00
|
|
|
char *name;
|
|
|
|
unsigned int c;
|
|
|
|
char ch;
|
|
|
|
char *p;
|
|
|
|
asection *seg = now_seg;
|
|
|
|
subsegT subseg = now_subseg;
|
|
|
|
Elf_Internal_Note i_note;
|
|
|
|
Elf_External_Note e_note;
|
|
|
|
asection *note_secp = (asection *) NULL;
|
|
|
|
int i, len;
|
|
|
|
|
|
|
|
SKIP_WHITESPACE ();
|
|
|
|
if (*input_line_pointer == '\"')
|
|
|
|
{
|
|
|
|
++input_line_pointer; /* -> 1st char of string. */
|
1993-05-28 03:42:23 +08:00
|
|
|
name = input_line_pointer;
|
|
|
|
|
1993-07-08 00:40:30 +08:00
|
|
|
while (is_a_char (c = next_char_of_string ()))
|
|
|
|
;
|
1993-05-28 03:42:23 +08:00
|
|
|
c = *input_line_pointer;
|
|
|
|
*input_line_pointer = '\0';
|
1993-07-08 00:40:30 +08:00
|
|
|
*(input_line_pointer - 1) = '\0';
|
1993-05-28 03:42:23 +08:00
|
|
|
*input_line_pointer = c;
|
|
|
|
|
Some more gcc lint, and:
* read.c (change_to_section): Removed. This is now done by
subseg_new.
(get_stab_string_offset): Rearranged somewhat. Create the section
using subseg_new. Store the string index in seg_info, rather than
in a static variable. Force the first string to be empty. Use
frag_more rather than FRAG_APPEND_1_CHAR.
(s_stab_generic): Rewrote.
* subsegs.h (segment_info_type): Added stabu union.
* subsegs.c (subseg_new): Initialize stab_string_size to 0.
* config/obj-aout.c: Don't include aout/stab_gnu.h.
(obj_aout_stab, obj_aout_desc): Removed.
(obj_pseudo_table): Removed desc and stabX entries.
* config/obj-bout.c: Same changes as config/obj-aout.c.
* config/obj-bout.h (S_SET_TYPE): Define.
(tc_bout_fix_to_chars): Declare.
* config/obj-coff.c (obj_coff_stab): Removed.
(obj_pseudo_table): Removed desc and stabX entries.
* config/obj-coff.h (SEPARATE_STAB_SECTIONS): Define.
* config/obj-coffbfd.c (current_stab_symbol): Removed.
* config/obj-coffbfd.h (obj_symbol_type): Removed n_strx, n_type,
n_other, n_desc and n_value fields.
(S_{S,G}ET_{OFFSET,OTHER,TYPE,DESC}): Removed.
(MAKE_STAB_SYMBOL): Removed.
* config/obj-ecoff.c (obj_ecoff_stab): Renamed to ecoff_stab.
Changed arguments and removed parsing code.
(obj_pseudo_table): Removed stabX entries.
* config/obj-ecoff.h (ecoff_stab): Declare.
(OBJ_PROCESS_STAB): Define.
* config/obj-elf.c: Don't include aout/stab_gnu.h.
(obj_elf_stab, obj_elf_xstab, obj_elf_desc,
elf_stab_symbol_string, elf_stab_symbol, obj_elf_stab_generic):
Removed.
(obj_pseudo_table): Removed desc, stabX and xstabs entries.
(obj_elf_version): Use subseg_new, not bfd_make_section. Don't
set SEC_LOAD for .note section.
(adjust_stab_sections): Get frag pointer from seg_info, rather
than looking through frags.
* config/obj-elf.h (S_{S,G}ET_{OTHER,TYPE,DESC}): Removed.
(SEPARATE_STAB_SECTIONS, INIT_STAB_SECTION, OBJ_PROCESS_STAB):
Define.
* config/obj-vms.c (obj_aout_stab): Removed.
(obj_pseudo_table): Removed stabX entries.
* config/obj-vms.h (S_SET_TYPE): Define.
1993-09-15 01:58:35 +08:00
|
|
|
/* create the .note section */
|
1993-05-28 03:42:23 +08:00
|
|
|
|
Some more gcc lint, and:
* read.c (change_to_section): Removed. This is now done by
subseg_new.
(get_stab_string_offset): Rearranged somewhat. Create the section
using subseg_new. Store the string index in seg_info, rather than
in a static variable. Force the first string to be empty. Use
frag_more rather than FRAG_APPEND_1_CHAR.
(s_stab_generic): Rewrote.
* subsegs.h (segment_info_type): Added stabu union.
* subsegs.c (subseg_new): Initialize stab_string_size to 0.
* config/obj-aout.c: Don't include aout/stab_gnu.h.
(obj_aout_stab, obj_aout_desc): Removed.
(obj_pseudo_table): Removed desc and stabX entries.
* config/obj-bout.c: Same changes as config/obj-aout.c.
* config/obj-bout.h (S_SET_TYPE): Define.
(tc_bout_fix_to_chars): Declare.
* config/obj-coff.c (obj_coff_stab): Removed.
(obj_pseudo_table): Removed desc and stabX entries.
* config/obj-coff.h (SEPARATE_STAB_SECTIONS): Define.
* config/obj-coffbfd.c (current_stab_symbol): Removed.
* config/obj-coffbfd.h (obj_symbol_type): Removed n_strx, n_type,
n_other, n_desc and n_value fields.
(S_{S,G}ET_{OFFSET,OTHER,TYPE,DESC}): Removed.
(MAKE_STAB_SYMBOL): Removed.
* config/obj-ecoff.c (obj_ecoff_stab): Renamed to ecoff_stab.
Changed arguments and removed parsing code.
(obj_pseudo_table): Removed stabX entries.
* config/obj-ecoff.h (ecoff_stab): Declare.
(OBJ_PROCESS_STAB): Define.
* config/obj-elf.c: Don't include aout/stab_gnu.h.
(obj_elf_stab, obj_elf_xstab, obj_elf_desc,
elf_stab_symbol_string, elf_stab_symbol, obj_elf_stab_generic):
Removed.
(obj_pseudo_table): Removed desc, stabX and xstabs entries.
(obj_elf_version): Use subseg_new, not bfd_make_section. Don't
set SEC_LOAD for .note section.
(adjust_stab_sections): Get frag pointer from seg_info, rather
than looking through frags.
* config/obj-elf.h (S_{S,G}ET_{OTHER,TYPE,DESC}): Removed.
(SEPARATE_STAB_SECTIONS, INIT_STAB_SECTION, OBJ_PROCESS_STAB):
Define.
* config/obj-vms.c (obj_aout_stab): Removed.
(obj_pseudo_table): Removed stabX entries.
* config/obj-vms.h (S_SET_TYPE): Define.
1993-09-15 01:58:35 +08:00
|
|
|
note_secp = subseg_new (".note", 0);
|
|
|
|
bfd_set_section_flags (stdoutput,
|
|
|
|
note_secp,
|
|
|
|
SEC_HAS_CONTENTS | SEC_READONLY);
|
1993-05-28 03:42:23 +08:00
|
|
|
|
|
|
|
/* process the version string */
|
|
|
|
|
1993-07-08 00:40:30 +08:00
|
|
|
len = strlen (name);
|
|
|
|
|
1993-08-05 07:10:43 +08:00
|
|
|
i_note.namesz = ((len + 1) + 3) & ~3; /* round this to word boundary */
|
|
|
|
i_note.descsz = 0; /* no description */
|
1993-07-08 00:40:30 +08:00
|
|
|
i_note.type = NT_VERSION;
|
|
|
|
p = frag_more (sizeof (e_note.namesz));
|
|
|
|
md_number_to_chars (p, (valueT) i_note.namesz, 4);
|
|
|
|
p = frag_more (sizeof (e_note.descsz));
|
|
|
|
md_number_to_chars (p, (valueT) i_note.descsz, 4);
|
|
|
|
p = frag_more (sizeof (e_note.type));
|
|
|
|
md_number_to_chars (p, (valueT) i_note.type, 4);
|
|
|
|
|
|
|
|
for (i = 0; i < len; i++)
|
|
|
|
{
|
|
|
|
ch = *(name + i);
|
|
|
|
{
|
|
|
|
FRAG_APPEND_1_CHAR (ch);
|
|
|
|
}
|
|
|
|
}
|
1997-03-10 12:53:55 +08:00
|
|
|
frag_align (2, 0, 0);
|
1993-05-28 03:42:23 +08:00
|
|
|
|
1993-09-14 05:32:07 +08:00
|
|
|
subseg_set (seg, subseg);
|
1993-05-28 03:42:23 +08:00
|
|
|
}
|
1993-07-08 00:40:30 +08:00
|
|
|
else
|
|
|
|
{
|
1993-08-05 07:10:43 +08:00
|
|
|
as_bad ("Expected quoted string");
|
1993-05-28 03:42:23 +08:00
|
|
|
}
|
1993-07-08 00:40:30 +08:00
|
|
|
demand_empty_rest_of_line ();
|
1993-05-28 03:42:23 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
1993-09-14 05:32:07 +08:00
|
|
|
obj_elf_size (ignore)
|
|
|
|
int ignore;
|
1993-05-28 03:42:23 +08:00
|
|
|
{
|
|
|
|
char *name = input_line_pointer;
|
|
|
|
char c = get_symbol_end ();
|
|
|
|
char *p;
|
|
|
|
expressionS exp;
|
|
|
|
symbolS *sym;
|
|
|
|
|
|
|
|
p = input_line_pointer;
|
|
|
|
*p = c;
|
|
|
|
SKIP_WHITESPACE ();
|
|
|
|
if (*input_line_pointer != ',')
|
|
|
|
{
|
|
|
|
*p = 0;
|
|
|
|
as_bad ("expected comma after name `%s' in .size directive", name);
|
|
|
|
*p = c;
|
|
|
|
ignore_rest_of_line ();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
input_line_pointer++;
|
* Extensive changes to permit symbols to contain any expression
type and to delay the computation of the expression until the
value is actually needed. This permits setting symbols to values
calculated based on object code size. Expressions were changed to
no longer be in a section, to stop the overloading of segment and
expression type that previously occurred.
* as.c (big_section, pass1_section, diff_section, absent_section):
Removed.
(expr_section): Added (used for dummy symbols which hold
intermediate expression values).
(perform_an_assembly_pass): Create expr_section, do not create the
sections now removed.
* as.h (segT): Removed SEG_ABSENT, SEG_PASS1, SEG_BIG, and
SEG_DIFFERENCE. Added SEG_EXPR.
(SEG_NORMAL): Corresponding changes.
* subsegs.c (seg_name, subsegs_begin): Changed accordingly.
* write.c (write_object_file): Ditto.
* config/obj-aout.c (seg_N_TYPE): Ditto.
* config/obj-bout.c (seg_N_TYPE): Ditto.
* config/obj-coff.c (seg_N_TYPE): Ditto.
* config/obj-coffbfd.c (seg_N_TYPE): Ditto.
* config/obj-vms.c (seg_N_TYPE): Ditto.
* expr.h (operatorT): Moved in from expr.c, added some values.
(expressionS): Added X_op field, removed X_seg field; renamed
X_subtract_symbol to X_op_symbol.
* expr.c: Extensive changes to assign expression types rather than
sections and to simplify the parsing.
* write.c (fix_new_internal): New static function.
(fix_new): Removed sub_symbol argument.
(fix_new_exp): New function, takes expression argument.
* write.h: Prototype changes for fix_new and fix_new_exp.
* cond.c (s_if): Changed accordingly.
* read.c (s_lsym, pseudo_set, emit_expr, parse_bitfield_cons,
parse_repeat_cons, get_segmented_expression,
get_known_segmented_expression, get_absolute_expression): Ditto.
* symbols.c (resolve_symbol_value, S_GET_VALUE, S_SET_VALUE):
Ditto.
* write.c (write_object_file): Ditto.
* config/obj-coff.c (obj_coff_def, obj_coff_val): Ditto.
* config/obj-coffbfd.c (obj_coff_def, obj_coff_val,
obj_coff_endef, yank_symbols): Ditto.
* config/obj-elf.c (obj_elf_stab_generic, obj_elf_size): Ditto.
* config/tc-a29k.c (md_assemble, parse_operand, machine_ip,
print_insn, md_operand): Ditto.
* config/tc-h8300.c (parse_exp, colonmod24, check_operand,
do_a_fix_imm, build_bytes): Ditto.
* config/tc-h8500.c (parse_exp, skip_colonthing, parse_reglist,
get_specific, check, insert, md_convert_frag): Ditto.
* config/tc-hppa.c (the_insn, fix_new_hppa, cons_fix_new_hppa,
md_assemble, pa_ip, getExpression, getAbsoluteExpression,
evaluateAbsolute, pa_build_unwind_subspace, pa_entry,
process_exit): Ditto.
* config/tc-hppa.h (STAB_FIXUP, is_DP_relative, is_PC_relative,
is_complex): Ditto.
* config/tc-i386.c (pe, md_assemble, i386_operand,
md_estimate_size_before_relax, md_create_long_jump): Ditto.
* config/tc-i860.c (md_assemble, getExpression, print_insn):
Ditto.
* config/tc-i960.c (parse_expr, subs, segs, md_convert_frag,
get_cdisp, mem_fmt, parse_ldconst, relax_cobr, s_sysproc,
i960_handle_align): Ditto.
* config/tc-m68k.c (struct m68k_exp, struct m68k_it, seg, op,
subs, add_fix, isvar, m68k_ip, md_assemble, md_convert_frag_1,
md_estimate_size_before_relax, md_create_long_jump, get_num):
Ditto.
* config/tc-m88k.c (md_assemble, get_imm16, get_pcr,
md_create_short_jump, md_create_long_jump): Ditto.
* config/tc-mips.c (md_assemble, append_insn, gp_reference,
macro_build, macro, my_getExpression): Ditto. Also removed
get_optional_absolute_expression; just use get_absolute_expression
instead.
* config/tc-ns32k.c (get_addr_mode, evaluate_expr, convert_iif,
fix_new_ns32k, fix_new_ns32k_exp, cons_fix_new_ns32k): Ditto.
* config/tc-ns32k.h (fix_new_ns32k prototype): Ditto.
* config/tc-sh.c (parse_exp, check, insert, md_convert_frag):
Ditto.
* config/tc-sparc.c (md_assemble, sparc_ip, getExpression,
print_insn): Ditto.
* config/tc-tahoe.c (struct top, md_estimate_size_before_relax,
tip_op, md_assemble): Ditto.
* config/tc-vax.c (seg_of_operand, md_assemble,
md_estimate_size_before_relax, md_create_long_jump): Ditto.
* config/tc-z8k.c (parse_exp, check_operand, newfix): Ditto.
1993-07-21 08:41:42 +08:00
|
|
|
expression (&exp);
|
|
|
|
if (exp.X_op == O_absent)
|
1993-05-28 03:42:23 +08:00
|
|
|
{
|
|
|
|
as_bad ("missing expression in .size directive");
|
* Extensive changes to permit symbols to contain any expression
type and to delay the computation of the expression until the
value is actually needed. This permits setting symbols to values
calculated based on object code size. Expressions were changed to
no longer be in a section, to stop the overloading of segment and
expression type that previously occurred.
* as.c (big_section, pass1_section, diff_section, absent_section):
Removed.
(expr_section): Added (used for dummy symbols which hold
intermediate expression values).
(perform_an_assembly_pass): Create expr_section, do not create the
sections now removed.
* as.h (segT): Removed SEG_ABSENT, SEG_PASS1, SEG_BIG, and
SEG_DIFFERENCE. Added SEG_EXPR.
(SEG_NORMAL): Corresponding changes.
* subsegs.c (seg_name, subsegs_begin): Changed accordingly.
* write.c (write_object_file): Ditto.
* config/obj-aout.c (seg_N_TYPE): Ditto.
* config/obj-bout.c (seg_N_TYPE): Ditto.
* config/obj-coff.c (seg_N_TYPE): Ditto.
* config/obj-coffbfd.c (seg_N_TYPE): Ditto.
* config/obj-vms.c (seg_N_TYPE): Ditto.
* expr.h (operatorT): Moved in from expr.c, added some values.
(expressionS): Added X_op field, removed X_seg field; renamed
X_subtract_symbol to X_op_symbol.
* expr.c: Extensive changes to assign expression types rather than
sections and to simplify the parsing.
* write.c (fix_new_internal): New static function.
(fix_new): Removed sub_symbol argument.
(fix_new_exp): New function, takes expression argument.
* write.h: Prototype changes for fix_new and fix_new_exp.
* cond.c (s_if): Changed accordingly.
* read.c (s_lsym, pseudo_set, emit_expr, parse_bitfield_cons,
parse_repeat_cons, get_segmented_expression,
get_known_segmented_expression, get_absolute_expression): Ditto.
* symbols.c (resolve_symbol_value, S_GET_VALUE, S_SET_VALUE):
Ditto.
* write.c (write_object_file): Ditto.
* config/obj-coff.c (obj_coff_def, obj_coff_val): Ditto.
* config/obj-coffbfd.c (obj_coff_def, obj_coff_val,
obj_coff_endef, yank_symbols): Ditto.
* config/obj-elf.c (obj_elf_stab_generic, obj_elf_size): Ditto.
* config/tc-a29k.c (md_assemble, parse_operand, machine_ip,
print_insn, md_operand): Ditto.
* config/tc-h8300.c (parse_exp, colonmod24, check_operand,
do_a_fix_imm, build_bytes): Ditto.
* config/tc-h8500.c (parse_exp, skip_colonthing, parse_reglist,
get_specific, check, insert, md_convert_frag): Ditto.
* config/tc-hppa.c (the_insn, fix_new_hppa, cons_fix_new_hppa,
md_assemble, pa_ip, getExpression, getAbsoluteExpression,
evaluateAbsolute, pa_build_unwind_subspace, pa_entry,
process_exit): Ditto.
* config/tc-hppa.h (STAB_FIXUP, is_DP_relative, is_PC_relative,
is_complex): Ditto.
* config/tc-i386.c (pe, md_assemble, i386_operand,
md_estimate_size_before_relax, md_create_long_jump): Ditto.
* config/tc-i860.c (md_assemble, getExpression, print_insn):
Ditto.
* config/tc-i960.c (parse_expr, subs, segs, md_convert_frag,
get_cdisp, mem_fmt, parse_ldconst, relax_cobr, s_sysproc,
i960_handle_align): Ditto.
* config/tc-m68k.c (struct m68k_exp, struct m68k_it, seg, op,
subs, add_fix, isvar, m68k_ip, md_assemble, md_convert_frag_1,
md_estimate_size_before_relax, md_create_long_jump, get_num):
Ditto.
* config/tc-m88k.c (md_assemble, get_imm16, get_pcr,
md_create_short_jump, md_create_long_jump): Ditto.
* config/tc-mips.c (md_assemble, append_insn, gp_reference,
macro_build, macro, my_getExpression): Ditto. Also removed
get_optional_absolute_expression; just use get_absolute_expression
instead.
* config/tc-ns32k.c (get_addr_mode, evaluate_expr, convert_iif,
fix_new_ns32k, fix_new_ns32k_exp, cons_fix_new_ns32k): Ditto.
* config/tc-ns32k.h (fix_new_ns32k prototype): Ditto.
* config/tc-sh.c (parse_exp, check, insert, md_convert_frag):
Ditto.
* config/tc-sparc.c (md_assemble, sparc_ip, getExpression,
print_insn): Ditto.
* config/tc-tahoe.c (struct top, md_estimate_size_before_relax,
tip_op, md_assemble): Ditto.
* config/tc-vax.c (seg_of_operand, md_assemble,
md_estimate_size_before_relax, md_create_long_jump): Ditto.
* config/tc-z8k.c (parse_exp, check_operand, newfix): Ditto.
1993-07-21 08:41:42 +08:00
|
|
|
exp.X_op = O_constant;
|
1993-05-28 03:42:23 +08:00
|
|
|
exp.X_add_number = 0;
|
|
|
|
}
|
|
|
|
*p = 0;
|
|
|
|
sym = symbol_find_or_make (name);
|
|
|
|
*p = c;
|
* Extensive changes to permit symbols to contain any expression
type and to delay the computation of the expression until the
value is actually needed. This permits setting symbols to values
calculated based on object code size. Expressions were changed to
no longer be in a section, to stop the overloading of segment and
expression type that previously occurred.
* as.c (big_section, pass1_section, diff_section, absent_section):
Removed.
(expr_section): Added (used for dummy symbols which hold
intermediate expression values).
(perform_an_assembly_pass): Create expr_section, do not create the
sections now removed.
* as.h (segT): Removed SEG_ABSENT, SEG_PASS1, SEG_BIG, and
SEG_DIFFERENCE. Added SEG_EXPR.
(SEG_NORMAL): Corresponding changes.
* subsegs.c (seg_name, subsegs_begin): Changed accordingly.
* write.c (write_object_file): Ditto.
* config/obj-aout.c (seg_N_TYPE): Ditto.
* config/obj-bout.c (seg_N_TYPE): Ditto.
* config/obj-coff.c (seg_N_TYPE): Ditto.
* config/obj-coffbfd.c (seg_N_TYPE): Ditto.
* config/obj-vms.c (seg_N_TYPE): Ditto.
* expr.h (operatorT): Moved in from expr.c, added some values.
(expressionS): Added X_op field, removed X_seg field; renamed
X_subtract_symbol to X_op_symbol.
* expr.c: Extensive changes to assign expression types rather than
sections and to simplify the parsing.
* write.c (fix_new_internal): New static function.
(fix_new): Removed sub_symbol argument.
(fix_new_exp): New function, takes expression argument.
* write.h: Prototype changes for fix_new and fix_new_exp.
* cond.c (s_if): Changed accordingly.
* read.c (s_lsym, pseudo_set, emit_expr, parse_bitfield_cons,
parse_repeat_cons, get_segmented_expression,
get_known_segmented_expression, get_absolute_expression): Ditto.
* symbols.c (resolve_symbol_value, S_GET_VALUE, S_SET_VALUE):
Ditto.
* write.c (write_object_file): Ditto.
* config/obj-coff.c (obj_coff_def, obj_coff_val): Ditto.
* config/obj-coffbfd.c (obj_coff_def, obj_coff_val,
obj_coff_endef, yank_symbols): Ditto.
* config/obj-elf.c (obj_elf_stab_generic, obj_elf_size): Ditto.
* config/tc-a29k.c (md_assemble, parse_operand, machine_ip,
print_insn, md_operand): Ditto.
* config/tc-h8300.c (parse_exp, colonmod24, check_operand,
do_a_fix_imm, build_bytes): Ditto.
* config/tc-h8500.c (parse_exp, skip_colonthing, parse_reglist,
get_specific, check, insert, md_convert_frag): Ditto.
* config/tc-hppa.c (the_insn, fix_new_hppa, cons_fix_new_hppa,
md_assemble, pa_ip, getExpression, getAbsoluteExpression,
evaluateAbsolute, pa_build_unwind_subspace, pa_entry,
process_exit): Ditto.
* config/tc-hppa.h (STAB_FIXUP, is_DP_relative, is_PC_relative,
is_complex): Ditto.
* config/tc-i386.c (pe, md_assemble, i386_operand,
md_estimate_size_before_relax, md_create_long_jump): Ditto.
* config/tc-i860.c (md_assemble, getExpression, print_insn):
Ditto.
* config/tc-i960.c (parse_expr, subs, segs, md_convert_frag,
get_cdisp, mem_fmt, parse_ldconst, relax_cobr, s_sysproc,
i960_handle_align): Ditto.
* config/tc-m68k.c (struct m68k_exp, struct m68k_it, seg, op,
subs, add_fix, isvar, m68k_ip, md_assemble, md_convert_frag_1,
md_estimate_size_before_relax, md_create_long_jump, get_num):
Ditto.
* config/tc-m88k.c (md_assemble, get_imm16, get_pcr,
md_create_short_jump, md_create_long_jump): Ditto.
* config/tc-mips.c (md_assemble, append_insn, gp_reference,
macro_build, macro, my_getExpression): Ditto. Also removed
get_optional_absolute_expression; just use get_absolute_expression
instead.
* config/tc-ns32k.c (get_addr_mode, evaluate_expr, convert_iif,
fix_new_ns32k, fix_new_ns32k_exp, cons_fix_new_ns32k): Ditto.
* config/tc-ns32k.h (fix_new_ns32k prototype): Ditto.
* config/tc-sh.c (parse_exp, check, insert, md_convert_frag):
Ditto.
* config/tc-sparc.c (md_assemble, sparc_ip, getExpression,
print_insn): Ditto.
* config/tc-tahoe.c (struct top, md_estimate_size_before_relax,
tip_op, md_assemble): Ditto.
* config/tc-vax.c (seg_of_operand, md_assemble,
md_estimate_size_before_relax, md_create_long_jump): Ditto.
* config/tc-z8k.c (parse_exp, check_operand, newfix): Ditto.
1993-07-21 08:41:42 +08:00
|
|
|
if (exp.X_op == O_constant)
|
1993-05-28 03:42:23 +08:00
|
|
|
S_SET_SIZE (sym, exp.X_add_number);
|
|
|
|
else
|
1993-07-08 00:40:30 +08:00
|
|
|
{
|
1997-03-10 12:53:55 +08:00
|
|
|
sym->sy_obj.size = (expressionS *) xmalloc (sizeof (expressionS));
|
|
|
|
*sym->sy_obj.size = exp;
|
1993-07-08 00:40:30 +08:00
|
|
|
}
|
1993-05-28 03:42:23 +08:00
|
|
|
demand_empty_rest_of_line ();
|
|
|
|
}
|
|
|
|
|
1995-05-11 07:08:40 +08:00
|
|
|
/* Handle the ELF .type pseudo-op. This sets the type of a symbol.
|
|
|
|
There are three syntaxes. The first (used on Solaris) is
|
|
|
|
.type SYM,#function
|
|
|
|
The second (used on UnixWare) is
|
|
|
|
.type SYM,@function
|
|
|
|
The third (reportedly to be used on Irix 6.0) is
|
|
|
|
.type SYM STT_FUNC
|
1996-01-30 06:11:12 +08:00
|
|
|
*/
|
1995-05-11 07:08:40 +08:00
|
|
|
|
1993-05-28 03:42:23 +08:00
|
|
|
static void
|
1993-09-14 05:32:07 +08:00
|
|
|
obj_elf_type (ignore)
|
|
|
|
int ignore;
|
1993-05-28 03:42:23 +08:00
|
|
|
{
|
1995-05-11 07:08:40 +08:00
|
|
|
char *name;
|
|
|
|
char c;
|
|
|
|
int type;
|
|
|
|
const char *typename;
|
1993-05-28 03:42:23 +08:00
|
|
|
symbolS *sym;
|
|
|
|
|
1995-05-11 07:08:40 +08:00
|
|
|
name = input_line_pointer;
|
|
|
|
c = get_symbol_end ();
|
|
|
|
sym = symbol_find_or_make (name);
|
|
|
|
*input_line_pointer = c;
|
|
|
|
|
1993-05-28 03:42:23 +08:00
|
|
|
SKIP_WHITESPACE ();
|
1995-05-11 07:08:40 +08:00
|
|
|
if (*input_line_pointer == ',')
|
|
|
|
++input_line_pointer;
|
|
|
|
|
1993-05-28 03:42:23 +08:00
|
|
|
SKIP_WHITESPACE ();
|
1995-05-11 07:08:40 +08:00
|
|
|
if (*input_line_pointer == '#' || *input_line_pointer == '@')
|
|
|
|
++input_line_pointer;
|
|
|
|
|
|
|
|
typename = input_line_pointer;
|
|
|
|
c = get_symbol_end ();
|
|
|
|
|
|
|
|
type = 0;
|
|
|
|
if (strcmp (typename, "function") == 0
|
|
|
|
|| strcmp (typename, "STT_FUNC") == 0)
|
|
|
|
type = BSF_FUNCTION;
|
|
|
|
else if (strcmp (typename, "object") == 0
|
|
|
|
|| strcmp (typename, "STT_OBJECT") == 0)
|
1996-01-30 06:11:12 +08:00
|
|
|
type = BSF_OBJECT;
|
1993-05-28 03:42:23 +08:00
|
|
|
else
|
1995-05-11 07:08:40 +08:00
|
|
|
as_bad ("ignoring unrecognized symbol type \"%s\"", typename);
|
|
|
|
|
|
|
|
*input_line_pointer = c;
|
|
|
|
|
1993-07-08 00:40:30 +08:00
|
|
|
sym->bsym->flags |= type;
|
1995-05-11 07:08:40 +08:00
|
|
|
|
|
|
|
demand_empty_rest_of_line ();
|
1993-05-28 03:42:23 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
1993-09-14 05:32:07 +08:00
|
|
|
obj_elf_ident (ignore)
|
|
|
|
int ignore;
|
1993-05-28 03:42:23 +08:00
|
|
|
{
|
1993-07-08 00:40:30 +08:00
|
|
|
static segT comment_section;
|
|
|
|
segT old_section = now_seg;
|
|
|
|
int old_subsection = now_subseg;
|
1993-05-28 03:42:23 +08:00
|
|
|
|
1993-07-08 00:40:30 +08:00
|
|
|
if (!comment_section)
|
|
|
|
{
|
|
|
|
char *p;
|
|
|
|
comment_section = subseg_new (".comment", 0);
|
1993-10-27 05:01:15 +08:00
|
|
|
bfd_set_section_flags (stdoutput, comment_section,
|
|
|
|
SEC_READONLY | SEC_HAS_CONTENTS);
|
1993-07-08 00:40:30 +08:00
|
|
|
p = frag_more (1);
|
|
|
|
*p = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
subseg_set (comment_section, 0);
|
|
|
|
stringer (1);
|
|
|
|
subseg_set (old_section, old_subsection);
|
|
|
|
}
|
|
|
|
|
1994-01-16 01:31:05 +08:00
|
|
|
#ifdef INIT_STAB_SECTION
|
|
|
|
|
1993-09-21 07:29:42 +08:00
|
|
|
/* The first entry in a .stabs section is special. */
|
|
|
|
|
|
|
|
void
|
|
|
|
obj_elf_init_stab_section (seg)
|
|
|
|
segT seg;
|
|
|
|
{
|
1993-10-27 05:01:15 +08:00
|
|
|
char *file;
|
1993-09-21 07:29:42 +08:00
|
|
|
char *p;
|
1993-11-24 15:42:03 +08:00
|
|
|
char *stabstr_name;
|
1993-09-21 07:29:42 +08:00
|
|
|
unsigned int stroff;
|
|
|
|
|
1993-10-27 05:01:15 +08:00
|
|
|
/* Force the section to align to a longword boundary. Without this,
|
|
|
|
UnixWare ar crashes. */
|
|
|
|
bfd_set_section_alignment (stdoutput, seg, 2);
|
|
|
|
|
1995-05-11 07:08:40 +08:00
|
|
|
/* Make space for this first symbol. */
|
1993-09-21 07:29:42 +08:00
|
|
|
p = frag_more (12);
|
1995-05-11 07:08:40 +08:00
|
|
|
/* Zero it out. */
|
|
|
|
memset (p, 0, 12);
|
1993-10-27 05:01:15 +08:00
|
|
|
as_where (&file, (unsigned int *) NULL);
|
1993-11-24 15:42:03 +08:00
|
|
|
stabstr_name = (char *) alloca (strlen (segment_name (seg)) + 4);
|
|
|
|
strcpy (stabstr_name, segment_name (seg));
|
|
|
|
strcat (stabstr_name, "str");
|
|
|
|
stroff = get_stab_string_offset (file, stabstr_name);
|
1993-09-21 07:29:42 +08:00
|
|
|
know (stroff == 1);
|
|
|
|
md_number_to_chars (p, stroff, 4);
|
|
|
|
seg_info (seg)->stabu.p = p;
|
|
|
|
}
|
|
|
|
|
1994-01-16 01:31:05 +08:00
|
|
|
#endif
|
|
|
|
|
1993-09-21 07:29:42 +08:00
|
|
|
/* Fill in the counts in the first entry in a .stabs section. */
|
|
|
|
|
1993-08-05 07:10:43 +08:00
|
|
|
static void
|
|
|
|
adjust_stab_sections (abfd, sec, xxx)
|
|
|
|
bfd *abfd;
|
|
|
|
asection *sec;
|
|
|
|
PTR xxx;
|
|
|
|
{
|
|
|
|
char *name;
|
|
|
|
asection *strsec;
|
Some more gcc lint, and:
* read.c (change_to_section): Removed. This is now done by
subseg_new.
(get_stab_string_offset): Rearranged somewhat. Create the section
using subseg_new. Store the string index in seg_info, rather than
in a static variable. Force the first string to be empty. Use
frag_more rather than FRAG_APPEND_1_CHAR.
(s_stab_generic): Rewrote.
* subsegs.h (segment_info_type): Added stabu union.
* subsegs.c (subseg_new): Initialize stab_string_size to 0.
* config/obj-aout.c: Don't include aout/stab_gnu.h.
(obj_aout_stab, obj_aout_desc): Removed.
(obj_pseudo_table): Removed desc and stabX entries.
* config/obj-bout.c: Same changes as config/obj-aout.c.
* config/obj-bout.h (S_SET_TYPE): Define.
(tc_bout_fix_to_chars): Declare.
* config/obj-coff.c (obj_coff_stab): Removed.
(obj_pseudo_table): Removed desc and stabX entries.
* config/obj-coff.h (SEPARATE_STAB_SECTIONS): Define.
* config/obj-coffbfd.c (current_stab_symbol): Removed.
* config/obj-coffbfd.h (obj_symbol_type): Removed n_strx, n_type,
n_other, n_desc and n_value fields.
(S_{S,G}ET_{OFFSET,OTHER,TYPE,DESC}): Removed.
(MAKE_STAB_SYMBOL): Removed.
* config/obj-ecoff.c (obj_ecoff_stab): Renamed to ecoff_stab.
Changed arguments and removed parsing code.
(obj_pseudo_table): Removed stabX entries.
* config/obj-ecoff.h (ecoff_stab): Declare.
(OBJ_PROCESS_STAB): Define.
* config/obj-elf.c: Don't include aout/stab_gnu.h.
(obj_elf_stab, obj_elf_xstab, obj_elf_desc,
elf_stab_symbol_string, elf_stab_symbol, obj_elf_stab_generic):
Removed.
(obj_pseudo_table): Removed desc, stabX and xstabs entries.
(obj_elf_version): Use subseg_new, not bfd_make_section. Don't
set SEC_LOAD for .note section.
(adjust_stab_sections): Get frag pointer from seg_info, rather
than looking through frags.
* config/obj-elf.h (S_{S,G}ET_{OTHER,TYPE,DESC}): Removed.
(SEPARATE_STAB_SECTIONS, INIT_STAB_SECTION, OBJ_PROCESS_STAB):
Define.
* config/obj-vms.c (obj_aout_stab): Removed.
(obj_pseudo_table): Removed stabX entries.
* config/obj-vms.h (S_SET_TYPE): Define.
1993-09-15 01:58:35 +08:00
|
|
|
char *p;
|
1993-08-05 07:10:43 +08:00
|
|
|
int strsz, nsyms;
|
|
|
|
|
|
|
|
if (strncmp (".stab", sec->name, 5))
|
|
|
|
return;
|
|
|
|
if (!strcmp ("str", sec->name + strlen (sec->name) - 3))
|
|
|
|
return;
|
|
|
|
|
|
|
|
name = (char *) alloca (strlen (sec->name) + 4);
|
|
|
|
strcpy (name, sec->name);
|
|
|
|
strcat (name, "str");
|
|
|
|
strsec = bfd_get_section_by_name (abfd, name);
|
|
|
|
if (strsec)
|
|
|
|
strsz = bfd_section_size (abfd, strsec);
|
|
|
|
else
|
|
|
|
strsz = 0;
|
|
|
|
nsyms = bfd_section_size (abfd, sec) / 12 - 1;
|
|
|
|
|
Some more gcc lint, and:
* read.c (change_to_section): Removed. This is now done by
subseg_new.
(get_stab_string_offset): Rearranged somewhat. Create the section
using subseg_new. Store the string index in seg_info, rather than
in a static variable. Force the first string to be empty. Use
frag_more rather than FRAG_APPEND_1_CHAR.
(s_stab_generic): Rewrote.
* subsegs.h (segment_info_type): Added stabu union.
* subsegs.c (subseg_new): Initialize stab_string_size to 0.
* config/obj-aout.c: Don't include aout/stab_gnu.h.
(obj_aout_stab, obj_aout_desc): Removed.
(obj_pseudo_table): Removed desc and stabX entries.
* config/obj-bout.c: Same changes as config/obj-aout.c.
* config/obj-bout.h (S_SET_TYPE): Define.
(tc_bout_fix_to_chars): Declare.
* config/obj-coff.c (obj_coff_stab): Removed.
(obj_pseudo_table): Removed desc and stabX entries.
* config/obj-coff.h (SEPARATE_STAB_SECTIONS): Define.
* config/obj-coffbfd.c (current_stab_symbol): Removed.
* config/obj-coffbfd.h (obj_symbol_type): Removed n_strx, n_type,
n_other, n_desc and n_value fields.
(S_{S,G}ET_{OFFSET,OTHER,TYPE,DESC}): Removed.
(MAKE_STAB_SYMBOL): Removed.
* config/obj-ecoff.c (obj_ecoff_stab): Renamed to ecoff_stab.
Changed arguments and removed parsing code.
(obj_pseudo_table): Removed stabX entries.
* config/obj-ecoff.h (ecoff_stab): Declare.
(OBJ_PROCESS_STAB): Define.
* config/obj-elf.c: Don't include aout/stab_gnu.h.
(obj_elf_stab, obj_elf_xstab, obj_elf_desc,
elf_stab_symbol_string, elf_stab_symbol, obj_elf_stab_generic):
Removed.
(obj_pseudo_table): Removed desc, stabX and xstabs entries.
(obj_elf_version): Use subseg_new, not bfd_make_section. Don't
set SEC_LOAD for .note section.
(adjust_stab_sections): Get frag pointer from seg_info, rather
than looking through frags.
* config/obj-elf.h (S_{S,G}ET_{OTHER,TYPE,DESC}): Removed.
(SEPARATE_STAB_SECTIONS, INIT_STAB_SECTION, OBJ_PROCESS_STAB):
Define.
* config/obj-vms.c (obj_aout_stab): Removed.
(obj_pseudo_table): Removed stabX entries.
* config/obj-vms.h (S_SET_TYPE): Define.
1993-09-15 01:58:35 +08:00
|
|
|
p = seg_info (sec)->stabu.p;
|
|
|
|
assert (p != 0);
|
1993-08-05 07:10:43 +08:00
|
|
|
|
1993-09-21 07:29:42 +08:00
|
|
|
bfd_h_put_16 (abfd, (bfd_vma) nsyms, (bfd_byte *) p + 6);
|
|
|
|
bfd_h_put_32 (abfd, (bfd_vma) strsz, (bfd_byte *) p + 8);
|
1993-08-05 07:10:43 +08:00
|
|
|
}
|
|
|
|
|
1996-01-13 04:35:38 +08:00
|
|
|
#ifdef NEED_ECOFF_DEBUG
|
1993-11-24 15:42:03 +08:00
|
|
|
|
|
|
|
/* This function is called by the ECOFF code. It is supposed to
|
|
|
|
record the external symbol information so that the backend can
|
|
|
|
write it out correctly. The ELF backend doesn't actually handle
|
|
|
|
this at the moment, so we do it ourselves. We save the information
|
|
|
|
in the symbol. */
|
|
|
|
|
|
|
|
void
|
1995-05-11 07:08:40 +08:00
|
|
|
elf_ecoff_set_ext (sym, ext)
|
1993-11-24 15:42:03 +08:00
|
|
|
symbolS *sym;
|
1995-05-11 07:08:40 +08:00
|
|
|
struct ecoff_extr *ext;
|
1993-11-24 15:42:03 +08:00
|
|
|
{
|
1995-05-11 07:08:40 +08:00
|
|
|
sym->bsym->udata.p = (PTR) ext;
|
1993-11-24 15:42:03 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* This function is called by bfd_ecoff_debug_externals. It is
|
|
|
|
supposed to *EXT to the external symbol information, and return
|
|
|
|
whether the symbol should be used at all. */
|
|
|
|
|
|
|
|
static boolean
|
|
|
|
elf_get_extr (sym, ext)
|
|
|
|
asymbol *sym;
|
|
|
|
EXTR *ext;
|
|
|
|
{
|
1995-05-11 07:08:40 +08:00
|
|
|
if (sym->udata.p == NULL)
|
1993-11-24 15:42:03 +08:00
|
|
|
return false;
|
1995-05-11 07:08:40 +08:00
|
|
|
*ext = *(EXTR *) sym->udata.p;
|
1993-11-24 15:42:03 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* This function is called by bfd_ecoff_debug_externals. It has
|
|
|
|
nothing to do for ELF. */
|
|
|
|
|
|
|
|
/*ARGSUSED*/
|
|
|
|
static void
|
|
|
|
elf_set_index (sym, indx)
|
|
|
|
asymbol *sym;
|
|
|
|
bfd_size_type indx;
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
1996-01-13 04:35:38 +08:00
|
|
|
#endif /* NEED_ECOFF_DEBUG */
|
1995-05-11 07:08:40 +08:00
|
|
|
|
|
|
|
void
|
|
|
|
elf_frob_symbol (symp, puntp)
|
|
|
|
symbolS *symp;
|
|
|
|
int *puntp;
|
|
|
|
{
|
1996-01-13 04:35:38 +08:00
|
|
|
#ifdef NEED_ECOFF_DEBUG
|
1995-05-11 07:08:40 +08:00
|
|
|
if (ECOFF_DEBUGGING)
|
|
|
|
ecoff_frob_symbol (symp);
|
1996-01-13 04:35:38 +08:00
|
|
|
#endif
|
1995-05-11 07:08:40 +08:00
|
|
|
|
1997-03-10 12:53:55 +08:00
|
|
|
if (symp->sy_obj.size != NULL)
|
1995-05-11 07:08:40 +08:00
|
|
|
{
|
1997-03-10 12:53:55 +08:00
|
|
|
switch (symp->sy_obj.size->X_op)
|
1995-05-11 07:08:40 +08:00
|
|
|
{
|
|
|
|
case O_subtract:
|
|
|
|
S_SET_SIZE (symp,
|
1997-03-10 12:53:55 +08:00
|
|
|
(S_GET_VALUE (symp->sy_obj.size->X_add_symbol)
|
|
|
|
+ symp->sy_obj.size->X_add_number
|
|
|
|
- S_GET_VALUE (symp->sy_obj.size->X_op_symbol)));
|
1995-05-11 07:08:40 +08:00
|
|
|
break;
|
|
|
|
case O_constant:
|
|
|
|
S_SET_SIZE (symp,
|
1997-03-10 12:53:55 +08:00
|
|
|
(S_GET_VALUE (symp->sy_obj.size->X_add_symbol)
|
|
|
|
+ symp->sy_obj.size->X_add_number));
|
1995-05-11 07:08:40 +08:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
as_bad (".size expression too complicated to fix up");
|
|
|
|
break;
|
|
|
|
}
|
1997-03-10 12:53:55 +08:00
|
|
|
free (symp->sy_obj.size);
|
|
|
|
symp->sy_obj.size = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (symp->sy_obj.versioned_name != NULL)
|
|
|
|
{
|
|
|
|
/* This symbol was given a new name with the .symver directive.
|
|
|
|
|
|
|
|
If this is an external reference, just rename the symbol to
|
|
|
|
include the version string. This will make the relocs be
|
|
|
|
against the correct versioned symbol.
|
|
|
|
|
|
|
|
If this is a definition, add an alias. FIXME: Using an alias
|
|
|
|
will permit the debugging information to refer to the right
|
|
|
|
symbol. However, it's not clear whether it is the best
|
|
|
|
approach. */
|
|
|
|
|
|
|
|
if (! S_IS_DEFINED (symp))
|
1997-03-14 00:21:34 +08:00
|
|
|
{
|
|
|
|
char *p;
|
|
|
|
|
|
|
|
/* Verify that the name isn't using the @@ syntax--this is
|
|
|
|
reserved for definitions of the default version to link
|
|
|
|
against. */
|
|
|
|
p = strchr (symp->sy_obj.versioned_name, ELF_VER_CHR);
|
|
|
|
know (p != NULL);
|
|
|
|
if (p[1] == ELF_VER_CHR)
|
|
|
|
{
|
|
|
|
as_bad ("invalid attempt to declare external version name as default in symbol `%s'",
|
|
|
|
symp->sy_obj.versioned_name);
|
|
|
|
*puntp = true;
|
|
|
|
}
|
|
|
|
S_SET_NAME (symp, symp->sy_obj.versioned_name);
|
|
|
|
}
|
1997-03-10 12:53:55 +08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
symbolS *symp2;
|
|
|
|
|
|
|
|
/* FIXME: Creating a new symbol here is risky. We're in the
|
|
|
|
final loop over the symbol table. We can get away with
|
|
|
|
it only because the symbol goes to the end of the list,
|
|
|
|
where the loop will still see it. It would probably be
|
|
|
|
better to do this in obj_frob_file_before_adjust. */
|
|
|
|
|
|
|
|
symp2 = symbol_find_or_make (symp->sy_obj.versioned_name);
|
|
|
|
|
|
|
|
/* Now we act as though we saw symp2 = sym. */
|
|
|
|
|
|
|
|
S_SET_SEGMENT (symp2, S_GET_SEGMENT (symp));
|
|
|
|
|
|
|
|
/* Subtracting out the frag address here is a hack because
|
|
|
|
we are in the middle of the final loop. */
|
|
|
|
S_SET_VALUE (symp2, S_GET_VALUE (symp) - symp->sy_frag->fr_address);
|
|
|
|
|
|
|
|
symp2->sy_frag = symp->sy_frag;
|
|
|
|
|
|
|
|
/* This will copy over the size information. */
|
|
|
|
copy_symbol_attributes (symp2, symp);
|
|
|
|
|
|
|
|
if (S_IS_WEAK (symp))
|
|
|
|
S_SET_WEAK (symp2);
|
|
|
|
|
|
|
|
if (S_IS_EXTERNAL (symp))
|
|
|
|
S_SET_EXTERNAL (symp2);
|
|
|
|
}
|
1995-05-11 07:08:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Double check weak symbols. */
|
|
|
|
if (symp->bsym->flags & BSF_WEAK)
|
|
|
|
{
|
|
|
|
if (S_IS_COMMON (symp))
|
|
|
|
as_bad ("Symbol `%s' can not be both weak and common",
|
|
|
|
S_GET_NAME (symp));
|
|
|
|
}
|
1996-02-16 03:54:38 +08:00
|
|
|
|
|
|
|
#ifdef TC_MIPS
|
|
|
|
/* The Irix 5 assembler appears to set the type of any common symbol
|
|
|
|
to STT_OBJECT. We try to be compatible, since the Irix 5 linker
|
|
|
|
apparently sometimes cares. FIXME: What about Irix 6? */
|
|
|
|
if (S_IS_COMMON (symp))
|
|
|
|
symp->bsym->flags |= BSF_OBJECT;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef TC_PPC
|
|
|
|
/* Frob the PowerPC, so that the symbol always has object type
|
|
|
|
if it is not some other type. VxWorks needs this. */
|
1996-02-16 05:47:33 +08:00
|
|
|
if ((symp->bsym->flags & (BSF_FUNCTION | BSF_FILE | BSF_SECTION_SYM)) == 0
|
|
|
|
&& S_IS_DEFINED (symp))
|
1996-02-16 03:54:38 +08:00
|
|
|
symp->bsym->flags |= BSF_OBJECT;
|
|
|
|
#endif
|
1995-05-11 07:08:40 +08:00
|
|
|
}
|
1993-11-24 15:42:03 +08:00
|
|
|
|
1996-10-14 23:40:15 +08:00
|
|
|
void
|
1993-07-08 00:40:30 +08:00
|
|
|
elf_frob_file ()
|
|
|
|
{
|
1993-08-05 07:10:43 +08:00
|
|
|
bfd_map_over_sections (stdoutput, adjust_stab_sections, (PTR) 0);
|
|
|
|
|
1993-07-08 00:40:30 +08:00
|
|
|
#ifdef elf_tc_final_processing
|
1993-09-04 06:36:26 +08:00
|
|
|
elf_tc_final_processing ();
|
1993-07-08 00:40:30 +08:00
|
|
|
#endif
|
1996-10-14 23:40:15 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* It is required that we let write_relocs have the opportunity to
|
|
|
|
optimize away fixups before output has begun, since it is possible
|
|
|
|
to eliminate all fixups for a section and thus we never should
|
|
|
|
have generated the relocation section. */
|
1993-07-08 00:40:30 +08:00
|
|
|
|
1996-10-14 23:40:15 +08:00
|
|
|
void
|
|
|
|
elf_frob_file_after_relocs ()
|
|
|
|
{
|
1996-01-13 04:35:38 +08:00
|
|
|
#ifdef NEED_ECOFF_DEBUG
|
1995-05-11 07:08:40 +08:00
|
|
|
if (ECOFF_DEBUGGING)
|
|
|
|
/* Generate the ECOFF debugging information. */
|
|
|
|
{
|
|
|
|
const struct ecoff_debug_swap *debug_swap;
|
|
|
|
struct ecoff_debug_info debug;
|
|
|
|
char *buf;
|
|
|
|
asection *sec;
|
1993-11-24 15:42:03 +08:00
|
|
|
|
1995-05-11 07:08:40 +08:00
|
|
|
debug_swap
|
|
|
|
= get_elf_backend_data (stdoutput)->elf_backend_ecoff_debug_swap;
|
|
|
|
know (debug_swap != (const struct ecoff_debug_swap *) NULL);
|
|
|
|
ecoff_build_debug (&debug.symbolic_header, &buf, debug_swap);
|
1993-11-24 15:42:03 +08:00
|
|
|
|
1995-05-11 07:08:40 +08:00
|
|
|
/* Set up the pointers in debug. */
|
1993-11-24 15:42:03 +08:00
|
|
|
#define SET(ptr, offset, type) \
|
|
|
|
debug.ptr = (type) (buf + debug.symbolic_header.offset)
|
|
|
|
|
1996-10-14 23:40:15 +08:00
|
|
|
SET (line, cbLineOffset, unsigned char *);
|
1995-05-11 07:08:40 +08:00
|
|
|
SET (external_dnr, cbDnOffset, PTR);
|
|
|
|
SET (external_pdr, cbPdOffset, PTR);
|
|
|
|
SET (external_sym, cbSymOffset, PTR);
|
|
|
|
SET (external_opt, cbOptOffset, PTR);
|
|
|
|
SET (external_aux, cbAuxOffset, union aux_ext *);
|
|
|
|
SET (ss, cbSsOffset, char *);
|
|
|
|
SET (external_fdr, cbFdOffset, PTR);
|
|
|
|
SET (external_rfd, cbRfdOffset, PTR);
|
|
|
|
/* ssext and external_ext are set up just below. */
|
1993-11-24 15:42:03 +08:00
|
|
|
|
1996-10-14 23:40:15 +08:00
|
|
|
#undef SET
|
1993-11-24 15:42:03 +08:00
|
|
|
|
1995-05-11 07:08:40 +08:00
|
|
|
/* Set up the external symbols. */
|
|
|
|
debug.ssext = debug.ssext_end = NULL;
|
|
|
|
debug.external_ext = debug.external_ext_end = NULL;
|
|
|
|
if (! bfd_ecoff_debug_externals (stdoutput, &debug, debug_swap, true,
|
|
|
|
elf_get_extr, elf_set_index))
|
|
|
|
as_fatal ("Failed to set up debugging information: %s",
|
|
|
|
bfd_errmsg (bfd_get_error ()));
|
|
|
|
|
|
|
|
sec = bfd_get_section_by_name (stdoutput, ".mdebug");
|
|
|
|
assert (sec != NULL);
|
|
|
|
|
|
|
|
know (stdoutput->output_has_begun == false);
|
|
|
|
|
|
|
|
/* We set the size of the section, call bfd_set_section_contents
|
|
|
|
to force the ELF backend to allocate a file position, and then
|
|
|
|
write out the data. FIXME: Is this really the best way to do
|
|
|
|
this? */
|
|
|
|
sec->_raw_size = bfd_ecoff_debug_size (stdoutput, &debug, debug_swap);
|
|
|
|
|
|
|
|
if (! bfd_set_section_contents (stdoutput, sec, (PTR) NULL,
|
|
|
|
(file_ptr) 0, (bfd_size_type) 0))
|
|
|
|
as_fatal ("Can't start writing .mdebug section: %s",
|
|
|
|
bfd_errmsg (bfd_get_error ()));
|
|
|
|
|
|
|
|
know (stdoutput->output_has_begun == true);
|
|
|
|
know (sec->filepos != 0);
|
|
|
|
|
|
|
|
if (! bfd_ecoff_write_debug (stdoutput, &debug, debug_swap,
|
|
|
|
sec->filepos))
|
|
|
|
as_fatal ("Could not write .mdebug section: %s",
|
|
|
|
bfd_errmsg (bfd_get_error ()));
|
|
|
|
}
|
1996-01-13 04:35:38 +08:00
|
|
|
#endif /* NEED_ECOFF_DEBUG */
|
1993-05-28 03:42:23 +08:00
|
|
|
}
|
1995-05-11 07:08:40 +08:00
|
|
|
|
1997-03-10 12:53:55 +08:00
|
|
|
#ifdef SCO_ELF
|
|
|
|
|
|
|
|
/* Heavily plagarized from obj_elf_version. The idea is to emit the
|
|
|
|
SCO specific identifier in the .notes section to satisfy the SCO
|
|
|
|
linker.
|
|
|
|
|
|
|
|
This looks more complicated than it really is. As opposed to the
|
|
|
|
"obvious" solution, this should handle the cross dev cases
|
|
|
|
correctly. (i.e, hosting on a 64 bit big endian processor, but
|
|
|
|
generating SCO Elf code) Efficiency isn't a concern, as there
|
|
|
|
should be exactly one of these sections per object module.
|
|
|
|
|
|
|
|
SCO OpenServer 5 identifies it's ELF modules with a standard ELF
|
|
|
|
.note section.
|
|
|
|
|
|
|
|
int_32 namesz = 4 ; Name size
|
|
|
|
int_32 descsz = 12 ; Descriptive information
|
|
|
|
int_32 type = 1 ;
|
|
|
|
char name[4] = "SCO" ; Originator name ALWAYS SCO + NULL
|
|
|
|
int_32 version = (major ver # << 16) | version of tools ;
|
|
|
|
int_32 source = (tool_id << 16 ) | 1 ;
|
|
|
|
int_32 info = 0 ; These are set by the SCO tools, but we
|
|
|
|
don't know enough about the source
|
|
|
|
environment to set them. SCO ld currently
|
|
|
|
ignores them, and recommends we set them
|
|
|
|
to zero. */
|
|
|
|
|
|
|
|
#define SCO_MAJOR_VERSION 0x1
|
|
|
|
#define SCO_MINOR_VERSION 0x1
|
|
|
|
|
|
|
|
void
|
|
|
|
sco_id ()
|
|
|
|
{
|
|
|
|
|
|
|
|
char *name;
|
|
|
|
unsigned int c;
|
|
|
|
char ch;
|
|
|
|
char *p;
|
|
|
|
asection *seg = now_seg;
|
|
|
|
subsegT subseg = now_subseg;
|
|
|
|
Elf_Internal_Note i_note;
|
|
|
|
Elf_External_Note e_note;
|
|
|
|
asection *note_secp = (asection *) NULL;
|
|
|
|
int i, len;
|
|
|
|
|
|
|
|
/* create the .note section */
|
|
|
|
|
|
|
|
note_secp = subseg_new (".note", 0);
|
|
|
|
bfd_set_section_flags (stdoutput,
|
|
|
|
note_secp,
|
|
|
|
SEC_HAS_CONTENTS | SEC_READONLY);
|
|
|
|
|
|
|
|
/* process the version string */
|
|
|
|
|
|
|
|
i_note.namesz = 4;
|
|
|
|
i_note.descsz = 12; /* 12 descriptive bytes */
|
|
|
|
i_note.type = NT_VERSION; /* Contains a version string */
|
|
|
|
|
|
|
|
p = frag_more (sizeof (i_note.namesz));
|
|
|
|
md_number_to_chars (p, (valueT) i_note.namesz, 4);
|
|
|
|
|
|
|
|
p = frag_more (sizeof (i_note.descsz));
|
|
|
|
md_number_to_chars (p, (valueT) i_note.descsz, 4);
|
|
|
|
|
|
|
|
p = frag_more (sizeof (i_note.type));
|
|
|
|
md_number_to_chars (p, (valueT) i_note.type, 4);
|
|
|
|
|
|
|
|
p = frag_more (4);
|
|
|
|
strcpy (p, "SCO");
|
|
|
|
|
|
|
|
/* Note: this is the version number of the ELF we're representing */
|
|
|
|
p = frag_more (4);
|
|
|
|
md_number_to_chars (p, (SCO_MAJOR_VERSION << 16) | (SCO_MINOR_VERSION), 4);
|
|
|
|
|
|
|
|
/* Here, we pick a magic number for ourselves (yes, I "registered"
|
|
|
|
it with SCO. The bottom bit shows that we are compat with the
|
|
|
|
SCO ABI. */
|
|
|
|
p = frag_more (4);
|
|
|
|
md_number_to_chars (p, 0x4c520000 | 0x0001, 4);
|
|
|
|
|
|
|
|
/* If we knew (or cared) what the source language options were, we'd
|
|
|
|
fill them in here. SCO has given us permission to ignore these
|
|
|
|
and just set them to zero. */
|
|
|
|
p = frag_more (4);
|
|
|
|
md_number_to_chars (p, 0x0000, 4);
|
|
|
|
|
|
|
|
frag_align (2, 0, 0);
|
|
|
|
|
|
|
|
/* We probably can't restore the current segment, for there likely
|
|
|
|
isn't one yet... */
|
|
|
|
if (seg && subseg)
|
|
|
|
subseg_set (seg, subseg);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* SCO_ELF */
|
|
|
|
|
1995-05-11 07:08:40 +08:00
|
|
|
const struct format_ops elf_format_ops =
|
|
|
|
{
|
|
|
|
bfd_target_elf_flavour,
|
|
|
|
0,
|
|
|
|
1,
|
|
|
|
elf_frob_symbol,
|
|
|
|
elf_frob_file,
|
1997-01-04 06:13:05 +08:00
|
|
|
elf_frob_file_after_relocs,
|
1995-05-11 07:08:40 +08:00
|
|
|
elf_s_get_size, elf_s_set_size,
|
|
|
|
elf_s_get_align, elf_s_set_align,
|
|
|
|
elf_copy_symbol_attributes,
|
1996-01-13 04:35:38 +08:00
|
|
|
#ifdef NEED_ECOFF_DEBUG
|
1995-05-11 07:08:40 +08:00
|
|
|
ecoff_generate_asm_lineno,
|
1996-01-13 04:35:38 +08:00
|
|
|
ecoff_stab,
|
1995-05-11 07:08:40 +08:00
|
|
|
#else
|
|
|
|
0,
|
|
|
|
0, /* process_stab */
|
1996-01-13 04:35:38 +08:00
|
|
|
#endif
|
1995-05-11 07:08:40 +08:00
|
|
|
elf_sec_sym_ok_for_reloc,
|
|
|
|
elf_pop_insert,
|
1996-01-13 04:35:38 +08:00
|
|
|
#ifdef NEED_ECOFF_DEBUG
|
1995-05-11 07:08:40 +08:00
|
|
|
elf_ecoff_set_ext,
|
1996-01-13 04:35:38 +08:00
|
|
|
#else
|
|
|
|
0,
|
|
|
|
#endif
|
1995-05-11 07:08:40 +08:00
|
|
|
obj_read_begin_hook,
|
|
|
|
obj_symbol_new_hook,
|
|
|
|
};
|