Proposed changes for pdp11 --*magic options
Stephen Casner
casner@acm.org
Tue Feb 25 00:14:00 GMT 2020
I solicit your feedback regarding a few design choices I've made as
part of implementing two proposed changes related to the ld magic
number options. These changes affect only the pdp11 emulation and
they are implemented all within an expansion of the customization
files for the pdp11 emulation except for two one-line changes in the
common code as explained below.
And, to allay any concerns about the number of emails I've sent to
this list recently, I don't have any work planned beyond this.
First, to be consistent with the behavior of ld both in Unix v6 at the
beginning of Unix on the PDP11 and in 2.11 BSD at its end, the default
format for the pdp11-aout target should be --omagic, not --nmagic.
That format does not page-align the .data section and generates magic
number 0407 which indicates to the runtime system that the .text
section should not be read-only. I've changed the default only for
the pdp11 emulation.
Second, I would like to add option --imagic to generate output with
magic number 0411 (defined as IMAGIC in Unix v6 ld.c) that puts both
the .text and .data sections starting at address 0 for loading into
the separate instruction and data spaces of larger PDP11 models. The
Unix v6 ld selected this format with option -i, but that option
already has another meaning in binutils ld. In 2.11 BSD the option -z
was added as a synonym for -i, so within the pdp11 emulation I also
implemented that option as a synonym for --imagic.
The expansion of the pdp11 customization consists of adding a pdp11.em
file containing _before_parse() to adjust the default config settings
consistent with --omagic. It also contains functions _add_options(),
_list_options() and _handle_option() to implement the additional
options including printing pdp11-specific help for all of the --*magic
options. I also needed a new _get_script() function that compiles in
a sixth linker script where the .data section starts at address 0.
Since genscripts does not produce such a script, when compiling in the
scripts I reuse the script that aligns the data to a page boundary but
edit it to set address 0 instead.
Related to this, I observe that the code in the adjust_*_magic()
functions in bfd/aoutx.h and bfd/pdp11.c that sets the VMA for data is
not effective because the alignment directive in the linker script
overrides it.
I also added a pdp11.sc file instead of using aout.sc so I could
remove some sections that are extraneous for the pdp11 emulation.
The design choices that I want to check with you are as follows:
- I have used the existing boolean ld_config_type::separate_code to
indicate when --imagic is seen in the option parsing. To me its
meaning seemed consistent with the new way I'm using it, but I
could add another boolean if that would be preferred.
- Rather than define another flag bit in bfd_target::object_flags,
I'm copying the state of the separate_code boolean into a local
variable in bfd/pdp11.c at _final_link() time for reference later
in adjust_sizes_and_vmas() as the sections are written.
- Since the --imagic format intentionally causes the .text and .data
sections to occupy the same memory addresses, I had to set
command_line.check_section_addresses = 0. Would that cause any
other problems?
- In my generated epdp11.c, the function name prefix is gldpdp11
rather than gld_pdp11 since that is how the code was written in
the emulation from which I borrowed code. But I also saw the
underscore included in a different emulation. Is one of these
considered correct?
The two one-line changes that I needed to make in common code are as
follows:
- I needed to add i_magic to enum aout_magic in bfd/libaout.h.
- In ld/lexsup.c, I needed to set config.text_read_only to TRUE in
case 'n'. This is the same as the default value of that boolean
as initialized in ldmain.c so I assume my change won't affect any
non-pdp11 emulation. I need this change so that my change of the
default value for pdp11 will work. That boolean is initialized to
FALSE or TRUE in case 'N' and case OPTION_NO_OMAGIC.
The diff is attached.
-- Steve
-------------- next part --------------
diff --git a/bfd/libaout.h b/bfd/libaout.h
index 81ef4cffd5..04efd9b08e 100644
--- a/bfd/libaout.h
+++ b/bfd/libaout.h
@@ -359,7 +359,8 @@ enum aout_magic {
undecided_magic = 0,
z_magic,
o_magic,
- n_magic
+ n_magic,
+ i_magic
};
struct aoutdata
diff --git a/bfd/pdp11.c b/bfd/pdp11.c
index 50d006f085..7ee9f94193 100644
--- a/bfd/pdp11.c
+++ b/bfd/pdp11.c
@@ -90,7 +90,8 @@ struct pdp11_external_exec
#define A_MAGIC2 NMAGIC
#define NMAGIC 0410 /* Pure executable. */
#define ZMAGIC 0413 /* Demand-paged executable. */
-#define A_MAGIC3 0411 /* Separated I&D. */
+#define IMAGIC 0411 /* Separated I&D. */
+#define A_MAGIC3 IMAGIC
#define A_MAGIC4 0405 /* Overlay. */
#define A_MAGIC5 0430 /* Auto-overlay (nonseparate). */
#define A_MAGIC6 0431 /* Auto-overlay (separate). */
@@ -242,6 +243,10 @@ struct aout_final_link_info
struct external_nlist *output_syms;
};
+/* Copy of the link_info.separate_code boolean to select the output format with
+ separate instruction and data spaces selected by --imagic */
+static bfd_boolean separate_i_d = FALSE;
+
reloc_howto_type howto_table_pdp11[] =
{
/* type rs size bsz pcrel bitpos ovrf sf name part_inpl readmask setmask pcdone */
@@ -988,6 +993,47 @@ adjust_n_magic (bfd *abfd, struct internal_exec *execp)
N_SET_MAGIC (execp, NMAGIC);
}
+static void
+adjust_i_magic (bfd *abfd, struct internal_exec *execp)
+{
+ file_ptr pos = adata (abfd).exec_bytes_size;
+ bfd_vma vma = 0;
+ int pad;
+ asection *text = obj_textsec (abfd);
+ asection *data = obj_datasec (abfd);
+ asection *bss = obj_bsssec (abfd);
+
+ /* Text. */
+ text->filepos = pos;
+ if (!text->user_set_vma)
+ text->vma = vma;
+ else
+ vma = text->vma;
+ pos += execp->a_text;
+
+ /* Data. */
+ data->filepos = pos;
+ if (!data->user_set_vma)
+ data->vma = 0;
+ vma = data->vma;
+
+ /* Since BSS follows data immediately, see if it needs alignment. */
+ vma += data->size;
+ pad = align_power (vma, bss->alignment_power) - vma;
+ execp->a_data = data->size + pad;
+ pos += execp->a_data;
+
+ /* BSS. */
+ if (!bss->user_set_vma)
+ bss->vma = vma;
+ else
+ vma = bss->vma;
+
+ /* Fix up exec header. */
+ execp->a_bss = bss->size;
+ N_SET_MAGIC (execp, IMAGIC);
+}
+
bfd_boolean
NAME (aout, adjust_sizes_and_vmas) (bfd *abfd)
{
@@ -1018,7 +1064,9 @@ NAME (aout, adjust_sizes_and_vmas) (bfd *abfd)
I understand it better now, but I haven't time to do the cleanup this
minute. */
- if (abfd->flags & WP_TEXT)
+ if (separate_i_d)
+ adata (abfd).magic = i_magic;
+ else if (abfd->flags & WP_TEXT)
adata (abfd).magic = n_magic;
else
adata (abfd).magic = o_magic;
@@ -1031,6 +1079,7 @@ NAME (aout, adjust_sizes_and_vmas) (bfd *abfd)
{
case n_magic: str = "NMAGIC"; break;
case o_magic: str = "OMAGIC"; break;
+ case i_magic: str = "IMAGIC"; break;
case z_magic: str = "ZMAGIC"; break;
default: abort ();
}
@@ -1056,6 +1105,9 @@ NAME (aout, adjust_sizes_and_vmas) (bfd *abfd)
case n_magic:
adjust_n_magic (abfd, execp);
break;
+ case i_magic:
+ adjust_i_magic (abfd, execp);
+ break;
default:
abort ();
}
@@ -3624,6 +3676,7 @@ NAME (aout, final_link) (bfd *abfd,
if (bfd_link_pic (info))
abfd->flags |= DYNAMIC;
+ separate_i_d = info->separate_code;
aout_info.info = info;
aout_info.output_bfd = abfd;
aout_info.contents = NULL;
diff --git a/ld/emulparams/pdp11.sh b/ld/emulparams/pdp11.sh
index 9b6bbbbd25..3f3326d121 100644
--- a/ld/emulparams/pdp11.sh
+++ b/ld/emulparams/pdp11.sh
@@ -1,5 +1,6 @@
-SCRIPT_NAME=aout
+SCRIPT_NAME=pdp11
OUTPUT_FORMAT="a.out-pdp11"
TEXT_START_ADDR=0
TARGET_PAGE_SIZE=8192
+EXTRA_EM_FILE=pdp11
ARCH=pdp11
diff --git a/ld/emultempl/pdp11.em b/ld/emultempl/pdp11.em
new file mode 100644
index 0000000000..ac1f9805dc
--- /dev/null
+++ b/ld/emultempl/pdp11.em
@@ -0,0 +1,130 @@
+# This shell script emits a C file. -*- C -*-
+# Copyright (C) 2006-2020 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.
+
+LDEMUL_BEFORE_PARSE=gldpdp11_before_parse
+
+fragment <<EOF
+
+/* --- \begin{pdp11.em} */
+#include "getopt.h"
+
+static void
+${LDEMUL_BEFORE_PARSE} (void)
+{
+ ldfile_set_output_arch ("`echo ${ARCH}`", bfd_arch_unknown);
+ /* for PDP11 Unix compatibility, default to --omagic */
+ config.magic_demand_paged = FALSE;
+ config.text_read_only = FALSE;
+}
+
+/* PDP11 specific options. */
+#define OPTION_IMAGIC 301
+
+static void
+gld${EMULATION_NAME}_add_options
+ (int ns ATTRIBUTE_UNUSED,
+ char **shortopts,
+ int nl,
+ struct option **longopts,
+ int nrl ATTRIBUTE_UNUSED,
+ struct option **really_longopts ATTRIBUTE_UNUSED)
+{
+ static const char xtra_short[] = "z";
+ static const struct option xtra_long[] =
+ {
+ {"imagic", no_argument, NULL, OPTION_IMAGIC},
+ {NULL, no_argument, NULL, 0}
+ };
+
+ *shortopts = (char *) xrealloc (*shortopts, ns + sizeof (xtra_short));
+ memcpy (*shortopts + ns, &xtra_short, sizeof (xtra_short));
+ *longopts
+ = xrealloc (*longopts, nl * sizeof (struct option) + sizeof (xtra_long));
+ memcpy (*longopts + nl, &xtra_long, sizeof (xtra_long));
+}
+
+static void
+gld${EMULATION_NAME}_list_options (FILE *file)
+{
+ fprintf (file, _(" -N, --omagic Do not make text readonly, do not page align data (default)\n"));
+ fprintf (file, _(" -n, --nmagic Make text readonly, align data to next page\n"));
+ fprintf (file, _(" -z, --imagic Make text readonly, separate instruction and data spaces\n"));
+ fprintf (file, _(" --no-omagic Equivalent to --nmagic\n"));
+}
+
+static bfd_boolean
+gld${EMULATION_NAME}_handle_option (int optc)
+{
+ switch (optc)
+ {
+ default:
+ return FALSE;
+
+ case 'z':
+ case OPTION_IMAGIC:
+ link_info.separate_code = 1;
+ command_line.check_section_addresses = 0;
+ break;
+ }
+
+ return TRUE;
+}
+
+/* We need a special case to prepare an additional linker script for option
+ * --imagic where the .data section starts at address 0 rather than directly
+ * following the .text section or being aligned to the next page after the
+ * .text section. */
+static char *
+gld${EMULATION_NAME}_get_script (int *isfile)
+EOF
+# Scripts compiled in.
+# sed commands to quote an ld script as a C string.
+sc="-f stringify.sed"
+
+fragment <<EOF
+{
+ *isfile = 0;
+
+ if (bfd_link_relocatable (&link_info) && config.build_constructors)
+ return
+EOF
+sed $sc ldscripts/${EMULATION_NAME}.xu >> e${EMULATION_NAME}.c
+echo ' ; else if (bfd_link_relocatable (&link_info)) return' >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xr >> e${EMULATION_NAME}.c
+echo ' ; else if (link_info.separate_code) return' >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xn | \
+ sed -e "s/ALIGN($TARGET_PAGE_SIZE)/0/" >> e${EMULATION_NAME}.c
+echo ' ; else if (!config.text_read_only) return' >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xbn >> e${EMULATION_NAME}.c
+echo ' ; else if (!config.magic_demand_paged) return' >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xn >> e${EMULATION_NAME}.c
+echo ' ; else return' >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.x >> e${EMULATION_NAME}.c
+echo '; }' >> e${EMULATION_NAME}.c
+
+fragment <<EOF
+/* --- \end{pdp11.em} */
+
+EOF
+
+LDEMUL_ADD_OPTIONS=gld"$EMULATION_NAME"_add_options
+LDEMUL_HANDLE_OPTION=gld"$EMULATION_NAME"_handle_option
+LDEMUL_LIST_OPTIONS=gld"$EMULATION_NAME"_list_options
+LDEMUL_GET_SCRIPT=gld"$EMULATION_NAME"_get_script
diff --git a/ld/lexsup.c b/ld/lexsup.c
index 3d15cc491d..d14e822b57 100644
--- a/ld/lexsup.c
+++ b/ld/lexsup.c
@@ -928,6 +928,7 @@ parse_args (unsigned argc, char **argv)
Use --call-shared or -Bdynamic for this. */
break;
case 'n':
+ config.text_read_only = TRUE;
config.magic_demand_paged = FALSE;
input_flags.dynamic = FALSE;
break;
diff --git a/ld/scripttempl/pdp11.sc b/ld/scripttempl/pdp11.sc
new file mode 100644
index 0000000000..995e5826d0
--- /dev/null
+++ b/ld/scripttempl/pdp11.sc
@@ -0,0 +1,56 @@
+# Copyright (C) 2014-2020 Free Software Foundation, Inc.
+#
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved.
+#
+test -z "${BIG_OUTPUT_FORMAT}" && BIG_OUTPUT_FORMAT=${OUTPUT_FORMAT}
+test -z "${LITTLE_OUTPUT_FORMAT}" && LITTLE_OUTPUT_FORMAT=${OUTPUT_FORMAT}
+test -z "${ALIGNMENT}" && ALIGNMENT="2"
+
+cat <<EOF
+/* Copyright (C) 2014-2020 Free Software Foundation, Inc.
+
+ Copying and distribution of this script, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. */
+
+OUTPUT_FORMAT("${OUTPUT_FORMAT}", "${BIG_OUTPUT_FORMAT}",
+ "${LITTLE_OUTPUT_FORMAT}")
+OUTPUT_ARCH(${ARCH})
+
+${RELOCATING+${LIB_SEARCH_DIRS}}
+${STACKZERO+${RELOCATING+${STACKZERO}}}
+${SHLIB_PATH+${RELOCATING+${SHLIB_PATH}}}
+${RELOCATING+${EXECUTABLE_SYMBOLS}}
+${RELOCATING+PROVIDE (__stack = 0);}
+SECTIONS
+{
+ ${RELOCATING+. = ${TEXT_START_ADDR};}
+ .text :
+ {
+ CREATE_OBJECT_SYMBOLS
+ *(.text)
+ ${RELOCATING+_etext = .;}
+ ${RELOCATING+__etext = .;}
+ ${PAD_TEXT+${RELOCATING+. = ${DATA_ALIGNMENT};}}
+ }
+ ${RELOCATING+. = ${DATA_ALIGNMENT};}
+ .data :
+ {
+ *(.data)
+ ${CONSTRUCTING+CONSTRUCTORS}
+ ${RELOCATING+_edata = .;}
+ ${RELOCATING+__edata = .;}
+ }
+ .bss :
+ {
+ ${RELOCATING+ __bss_start = .};
+ *(.bss)
+ *(COMMON)
+ ${RELOCATING+. = ALIGN(${ALIGNMENT});}
+ ${RELOCATING+_end = . };
+ ${RELOCATING+__end = . };
+ }
+}
+EOF
More information about the Binutils
mailing list