binutils-gdb/ld/emultempl/e2kelf.em
2020-10-14 00:22:48 +03:00

570 lines
18 KiB
Plaintext

# This shell script emits a C file. -*- C -*-
# Copyright 2003, 2005, 2006, 2007, 2009 Free Software Foundation, Inc.
#
# This file is part of the GNU Binutils.
#
# This program 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 3 of the License, or
# (at your option) any later version.
#
# This program 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.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
# MA 02110-1301, USA.
#
# This file is sourced from elf32.em, and defines extra e2k-elf
# specific routines.
#
# Define some shell vars to insert bits of code into the standard elf
# parse_args and list_options functions.
#
fragment <<EOF
#include "elfxx-e2k.h"
static int e2k_ipd;
static int e2k_is_x86app;
static int e2k_is_4mpages;
/* Specifies that an architecture has been explicitly set via a command
line. */
static bfd_boolean arch_set_via_cmdline;
/* Whether the target should restrict itself to input files having an
architecture set via cmdline by means of '--restrict-to-arch ARCH' only (see
Bug #82047). Provided that this variable is TRUE, the former should be TRUE
as well, since --restrict-to-arch specifies output ARCH at the same
time. */
static bfd_boolean restrict_to_arch;
static bfd_boolean relaxed_e2k_machine_check;
static int link_mixed_eir;
static bfd_boolean output_new_e_machine = TRUE;
static bfd_boolean mark_objects;
static bfd_boolean inside_marked_objects;
/* A simulating mode which should make it possible to "link" any input object
file alone in a reproducible way. The goal is to get rid of relocations
which make it so difficult to compare output files produced by different
assemblers. */
static bfd_boolean simulate;
static bfd_boolean ignore_pure_eir_files;
/* Placeholders used to restore the corresponding values set
via cmdline. */
static enum bfd_architecture cmdline_output_architecture;
static unsigned long cmdline_output_machine;
EOF
# This code gets inserted into the generic elf32.sc linker script
# and allows us to define our own command line switches.
PARSE_AND_LIST_PROLOGUE='
#define OPTION_E2K_IPD 301
#define OPTION_E2K_X86APP 302
#define OPTION_E2K_4MPAGES 303
#define OPTION_RELAXED_E2K_MACHINE_CHECK 304
#define OPTION_LINK_MIXED_EIR 305
#define OPTION_OLD_E_MACHINE 306
#define OPTION_NEW_PM_SEMANTICS 307
#define OPTION_DSP_LINUX_MODE 308
#define OPTION_MARK_REGULAR_OBJECTS 309
#define OPTION_START_REGULAR_OBJECTS 310
#define OPTION_END_REGULAR_OBJECTS 311
#define OPTION_BINARY_EIR_OUTPUT 312
#define OPTION_RESTRICT_TO_ARCH 313
#define OPTION_SIMULATE 314
#define OPTION_IGNORE_PURE_EIR_FILES 315
'
PARSE_AND_LIST_LONGOPTS='
{ "e2k-ipd", required_argument, NULL, OPTION_E2K_IPD },
{ "e2k-x86app", no_argument, NULL, OPTION_E2K_X86APP },
{ "e2k-4mpages", no_argument, NULL, OPTION_E2K_4MPAGES },
{ "relaxed-e2k-machine-check", no_argument, NULL, OPTION_RELAXED_E2K_MACHINE_CHECK },
{ "link-mixed-eir", required_argument, NULL, OPTION_LINK_MIXED_EIR},
{ "old-e-machine", no_argument, NULL, OPTION_OLD_E_MACHINE},
{ "force-new-pm-semantics", no_argument, NULL, OPTION_NEW_PM_SEMANTICS},
{ "dsp-linux-mode", no_argument, NULL, OPTION_DSP_LINUX_MODE},
{ "mark-regular-objects", no_argument, NULL, OPTION_MARK_REGULAR_OBJECTS},
{ "start-regular-objects", no_argument, NULL, OPTION_START_REGULAR_OBJECTS},
{ "end-regular-objects", no_argument, NULL, OPTION_END_REGULAR_OBJECTS},
{ "binary-eir-output", no_argument, NULL, OPTION_BINARY_EIR_OUTPUT},
{ "restrict-to-arch", required_argument, NULL, OPTION_RESTRICT_TO_ARCH},
{ "simulate", no_argument, NULL, OPTION_SIMULATE},
{ "ignore-pure-eir-files", no_argument, NULL, OPTION_IGNORE_PURE_EIR_FILES},
'
PARSE_AND_LIST_OPTIONS='
fprintf (file, _(" --link-mixed-eir={1,2,3}\n"));
fprintf (file, _("\t\t\tLink mixed EIR\n"));
'
PARSE_AND_LIST_ARGS_CASES='
case OPTION_E2K_IPD:
{
const char *end;
e2k_ipd = (int) bfd_scan_vma (optarg, &end, 0);
if (*end
|| e2k_ipd < 0
|| e2k_ipd > 2)
einfo (_("%P%F: invalid argument '\''%s'\'' to option '\''%s'\''\n"), optarg, "--e2k-ipd");
e2k_ipd += 1;
}
break;
case OPTION_E2K_X86APP:
e2k_is_x86app = 1;
break;
case OPTION_E2K_4MPAGES:
e2k_is_4mpages = 1;
break;
case OPTION_DSP_LINUX_MODE:
e2k_dsp_linux_mode = TRUE;
break;
case OPTION_RESTRICT_TO_ARCH:
restrict_to_arch = TRUE;
/* Fall through. */
case '\'A\'':
/* This option has a very special meaning for E2k. It is not
absolutely necessary at present though. TODO: find out whether the
underlying code (especially "ldfile_set_output_arch ()") is needed at
all now that the output architecture is finally set in
_bfd_e2k_elf_merge_private_bfd_data (). Probably it is, because the
latter function makes use of OBFD->arch_info. */
{
char *arch_name = xmalloc (strlen (optarg) + 4);
sprintf (arch_name, "%s:%s", optarg, "'$MACHINE'");
ldfile_set_output_arch (arch_name, bfd_arch_e2k);
arch_set_via_cmdline = TRUE;
free (arch_name);
}
/* Save architecture and machine values obtained two lines above in
order to be able to restore them later in set_output_arch method. */
cmdline_output_architecture = ldfile_output_architecture;
cmdline_output_machine = ldfile_output_machine;
break;
case OPTION_RELAXED_E2K_MACHINE_CHECK:
relaxed_e2k_machine_check = TRUE;
break;
case OPTION_LINK_MIXED_EIR:
if ((optarg[0] != '\''1'\'' && optarg[0] != '\''2'\''
&& optarg[0] != '\''3'\'')
|| optarg[1] != '\''\0'\'')
einfo (_("%P%F: invalid value for '\''--link-mixed-eir'\'' option: '\''%s'\''\n"), optarg);
link_mixed_eir = optarg[0] - '\''0'\'';
break;
case OPTION_OLD_E_MACHINE:
output_new_e_machine = FALSE;
break;
case OPTION_NEW_PM_SEMANTICS:
break;
case OPTION_MARK_REGULAR_OBJECTS:
mark_objects = TRUE;
break;
case OPTION_START_REGULAR_OBJECTS:
inside_marked_objects = TRUE;
break;
case OPTION_END_REGULAR_OBJECTS:
inside_marked_objects = FALSE;
break;
case OPTION_BINARY_EIR_OUTPUT:
break;
case OPTION_SIMULATE:
simulate = 1;
break;
case OPTION_IGNORE_PURE_EIR_FILES:
ignore_pure_eir_files = TRUE;
break;
case 1:
/* Beware that this macro becomes part of emulation-specific "handle_
option ()" method. Returning TRUE for a filename below prevents
parse_args () in ld/lexsup.c from adding it as an input file. */
if (!mark_objects || inside_marked_objects)
return FALSE;
{
bfd_boolean ret = FALSE;
bfd *abfd = bfd_openr (optarg, "default");
if (abfd == NULL)
return FALSE;
/* My goal is to prevent relocatable objects not surrounded by
"--{start,end}-regular-objects" options from being included into
the final link. As you remember such a situation emerges if an object
is passed via "-Wl,f.o". This should apply neither to static nor to
shared libraries explicitly passed by their filenames (i.e. not via
-l option). Indeed, one may need to fetch some objects from the
former in case the mixed EIR contained in them has not been linked
into total EIR at "--link-mixed-eir=2" stage, while the latter never
take part in EIR linkage at all. It was Bug #81255 that made me
revisit the latter case. */
if (bfd_check_format (abfd, bfd_object)
&& (bfd_get_flavour (abfd) != bfd_target_elf_flavour
|| elf_elfheader (abfd)->e_type != ET_DYN))
ret = TRUE;
bfd_close (abfd);
return ret;
}
break;
'
fragment <<EOF
/* This is called before the hash table is allocated. */
static void
e2k_after_parse (void)
{
/* Inhibit '--export-dynamic' in '--link-mixed-eir=X' mode. These options turn
out to be passed together by LCC when it's invoked with '-fsanitize=address
-fwhole' (see Bug #82854). Now that '--export-dynamic' enforces creation of
dynamic sections, it would lead to appearance of a bogus '.dynamic' section
in the relocatable output at '--linux-mixed-eir=1' stage. If this
irrelevant '.dynamic' coming from an input file was eventually linked into
the executable at the final stage, its bogus entries would override the
ones created by LD during the final link, which would lead to a runtime
failure described in the above bug. */
if (link_mixed_eir >=1 && link_mixed_eir <= 3)
link_info.export_dynamic = FALSE;
/* LINK_MIXED_EIR should be available by the time we open each input
file. */
_bfd_e2k_elf_after_parse (link_mixed_eir);
gld${EMULATION_NAME}_after_parse ();
}
static bfd_boolean gld${EMULATION_NAME}_load_symbols
(lang_input_statement_type *);
static bfd_boolean
pure_eir_finder (bfd *abfd ATTRIBUTE_UNUSED,
asection *section,
void *ptr ATTRIBUTE_UNUSED)
{
return strcmp (section->name, ".pack_pure_eir") == 0;
}
static bfd_boolean
e2k_recognized_file (lang_input_statement_type *entry)
{
if (link_mixed_eir != 0 && (entry->the_bfd->flags & DYNAMIC) != 0)
return TRUE;
if (ignore_pure_eir_files
&& bfd_sections_find_if (entry->the_bfd, pure_eir_finder, NULL))
return TRUE;
/* Otherwise, the standard implementation from 'elf32.em' will do. */
return gld${EMULATION_NAME}_load_symbols (entry);
}
static bfd_boolean
e2k_allow_dynamic_entries_in_relocatable_link (void)
{
if (link_mixed_eir != 0)
return TRUE;
return FALSE;
}
/* This is called after the input files have been opened. TODO: some of the
parameters below could be probably set via
e2k_create_output_section_statements () which doesn't exist at
present . . . */
static void
e2k_after_open (void)
{
/* Hash table has been already allocated by the time I call this
function (see the end of 'open_output ()' in 'ldlang.c'. */
_bfd_e2k_elf_after_open (e2k_ipd, e2k_is_x86app, e2k_is_4mpages,
arch_set_via_cmdline, restrict_to_arch,
relaxed_e2k_machine_check, output_new_e_machine,
simulate);
gld${EMULATION_NAME}_after_open ();
}
static char * gld${EMULATION_NAME}_get_script (int *);
static char *
e2k_get_script (int *isfile)
{
if (link_mixed_eir == 2)
{
*isfile = 0;
return ("SECTIONS\n"
"{\n"
"\t.pack_pure_eir : { *(.pack_pure_eir) }\n"
"\t.pack_mixed_eir : { *(.pack_mixed_eir) }\n"
"\t/DISCARD/ : { *(*) }\n"
"}\n");
}
return gld${EMULATION_NAME}_get_script (isfile);
}
static void
e2k_set_output_arch (void)
{
EOF
if test -z "$KPDA"; then
if test "$MACHINE" = "64"; then
fragment <<EOF
int addend = 0;
EOF
elif test "$MACHINE" = "32"; then
fragment <<EOF
int addend = 1;
EOF
else
fragment <<EOF
int addend = 2;
EOF
fi
fi
fragment <<EOF
if (arch_set_via_cmdline)
{
/* Restore the values obtained from the commandline. They've
already been spoiled by . . . ??? */
ldfile_output_architecture = cmdline_output_architecture;
ldfile_output_machine = cmdline_output_machine;
}
/* Now make the output file machine number match the TARGET vector. Keep in
mind that currently we have a one to one correspondence between a target
vector and the corresponding ABI, which is encoded in the machine number.
E.g., ELF32 targets for E2K cannot be used to produce output for the 64-bit
ABI and so on.
This way, the 'OUTPUT_FORMAT ()' directive will SILENTLY (because currently
I don't need a public discussion) take precedence over ABI which a user
might have specified via the 'OUTPUT_ARCH(...:XX)' directive. */
EOF
if test -z "$KPDA"; then
fragment <<EOF
ldfile_output_machine = (ldfile_output_machine / 3) * 3 + addend;
EOF
fi
fragment <<EOF
set_output_arch_default ();
}
EOF
if test -n "$LDEMUL_PLACE_ORPHAN"; then
fragment <<EOF
static lang_output_section_statement_type *
insert_output_section_statement (const char *name)
{
lang_statement_list_type add;
lang_output_section_statement_type *os;
lang_list_init (&add);
os = lang_enter_output_section_statement (name, NULL, 0,
NULL, NULL, NULL, 0, 0);
lang_leave_output_section_statement (0, "*default*", NULL, NULL);
return os;
}
static lang_output_section_statement_type *
place_dsp_section (asection *s, const char *os_name)
{
lang_output_section_statement_type *os;
os = lang_output_section_find (os_name);
if (os == NULL)
{
os = insert_output_section_statement (os_name);
/* 2 ^ 17 == 128 Kb: align a DSP-specific output section in E2K space to
maximal possible alignment at DSP side. This is probably the only way
to ensure that the section and its symbols are aligned appropriately
from the point of view of DSP. */
os->section_alignment = 17;
}
lang_add_section (&os->children, s, NULL, os);
return os;
}
static const char *
dsp_output_section_name (const char *sec_name)
{
int is_text;
int sid;
const char *c;
static char os_name[32];
if (! (is_text = CONST_STRNEQ (sec_name, ".dsp_text"))
&& ! CONST_STRNEQ (sec_name, ".dsp_data")
&& ! CONST_STRNEQ (sec_name, ".dsp_rodata")
&& ! CONST_STRNEQ (sec_name, ".dsp_bss")
&& ! CONST_STRNEQ (sec_name, "DSP_COMMON"))
return NULL;
c = sec_name;
while (*c != '\0' && ! ISDIGIT (*c))
c++;
if (! ISDIGIT (*c) || !ISDIGIT (c[1]) || c[2] != '\0')
return NULL;
sid = 10 * (c[0] - '0') + (c[1] - '0');
if (sid >= 16)
return NULL;
sprintf (os_name, "%s%02d", is_text ? ".dsp_text" : ".dsp_data", sid);
return xstrdup (os_name);
}
static lang_output_section_statement_type *
${LDEMUL_PLACE_ORPHAN} (asection *s, const char *secname, int constraint)
{
struct _bfd_e2k_elf_link_hash_table *htab;
htab = _bfd_e2k_elf_hash_table (&link_info);
if (e2k_dsp_linux_mode && htab->have_dsp_output)
{
const char *os_name = dsp_output_section_name (s->name);
if (os_name)
return place_dsp_section (s, os_name);
}
return gld${EMULATION_NAME}_place_orphan (s, secname, constraint);
}
EOF
fi
if test -n "$LDEMUL_AFTER_ALLOCATION" ; then
fragment <<EOF
static void
define_dsp_symbol (const char *name, asection *section, bfd_vma value)
{
struct bfd_link_hash_entry *h;
h = bfd_link_hash_lookup (link_info.hash, name, TRUE,
TRUE, TRUE);
h->type = bfd_link_hash_defined;
h->u.def.value = value;
h->u.def.section = section;
}
static void
${LDEMUL_AFTER_ALLOCATION} (void)
{
unsigned int i;
struct _bfd_e2k_elf_link_hash_table *htab;
htab = _bfd_e2k_elf_hash_table (&link_info);
/* We don't need any segment map tuning when using a
hand-made linker script for producing an executable to
be loaded with BOOT. */
if (!e2k_dsp_linux_mode || !htab->have_dsp_output)
{
gld${EMULATION_NAME}_after_allocation ();
return;
}
/* The call of this function currently undoes all my attempts to assign VMA
addresses to DSP sections . . . */
gld${EMULATION_NAME}_after_allocation ();
for (i = 0; i < 16; i++)
{
static char os_name[64], sym_name[64];
lang_output_section_statement_type *os;
bfd_vma true_vma;
true_vma = (bfd_get_section_by_name (link_info.output_bfd, ".dsp_mem")->vma
+ 32 * 1024 * i);
sprintf (os_name, ".dsp_text%02d",i);
os = lang_output_section_find (os_name);
if (os && os->bfd_section)
{
os->bfd_section->vma = true_vma;
sprintf (sym_name, "__DSP%02d_CODE_BEGIN_VMA", i);
define_dsp_symbol (sym_name, os->bfd_section, 0);
sprintf (sym_name, "__DSP%02d_CODE_BEGIN_LMA", i);
define_dsp_symbol (sym_name, bfd_abs_section_ptr,
os->bfd_section->lma);
sprintf (sym_name, "__DSP%02d_CODE_END_LMA", i);
define_dsp_symbol (sym_name, bfd_abs_section_ptr,
(os->bfd_section->lma
+ os->bfd_section->size));
}
true_vma = (bfd_get_section_by_name (link_info.output_bfd, ".dsp_mem")->vma
+ (512 + 128 * i) * 1024);
sprintf (os_name, ".dsp_data%02d", i);
os = lang_output_section_find (os_name);
if (os && os->bfd_section)
{
os->bfd_section->vma = true_vma ;
sprintf (sym_name, "__DSP%02d_DATA_BEGIN_VMA", i);
define_dsp_symbol (sym_name, os->bfd_section, 0);
sprintf (sym_name, "__DSP%02d_DATA_BEGIN_LMA", i);
define_dsp_symbol (sym_name, bfd_abs_section_ptr,
os->bfd_section->lma);
sprintf (sym_name, "__DSP%02d_DATA_END_LMA", i);
define_dsp_symbol (sym_name, bfd_abs_section_ptr,
(os->bfd_section->lma + os->bfd_section->size));
}
}
}
EOF
fi
LDEMUL_GET_SCRIPT=e2k_get_script
LDEMUL_AFTER_PARSE=e2k_after_parse
LDEMUL_RECOGNIZED_FILE=e2k_recognized_file
LDEMUL_ALLOW_DYNAMIC_ENTRIES_IN_RELOCATABLE_LINK=\
e2k_allow_dynamic_entries_in_relocatable_link
LDEMUL_AFTER_OPEN=e2k_after_open
LDEMUL_SET_OUTPUT_ARCH=e2k_set_output_arch