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