This is the mail archive of the binutils@sourceware.cygnus.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

m68k-coff ld --embedded-relocs


Here is the patch for m68k-coff mentioned earlier which creates a table
of relocations in data sections for use at runtime.  Unlike the MIPS code,
which packs the data tightly, this tries to keep as much information
as anyone might need.  It has been in use on Palm OS for some time,
and an earlier version has been in use on uClinux for about 18 months.

I am not currently copyright-assigned (though will be soon), but I wanted
to make this patch available for discussion and presently inclusion.
I think it can be extended to handle the situations brought up today
quite easily.

It suffers from the crashing problem Michael identified in the MIPS code,
but that is easily rectified.

> The problem with using a section index is that it implies that you
> need a section table.  Think about converting a program to S-records.
> Whatever table you use must be recorded in the program image somehow.

Interesting :-).  I would propose using the final field in the little
records (see the comment below) that is currently just zero.  We could
set up an encoding something like

	symsection	final field
	.code		0
	.data		1
	.bss		2

This is simple and compact, and not dependent on the section index.
Then formats with a section table would use the symsection field,
and others could use this numeric field.  User-defined sections could
perhaps have a convention that sections with numeric names "N" have
the corresponding numeric value in the final field.  Conventions like
this would preserve information without needing a section table.

But beyond this I think it all gets completely system-specific.  It
might be nice to have a tightly packed format for specific systems,
but it's impossible to anticipate what oddball adhoc-ery they might
want.  Instead, this patch just keeps all the information around for
people to frob it later.

But possibly it doesn't matter much: after all, it's taken a long time
for even a second port after the MIPS one to want something like this
--embedded-relocs...  :-)

    John


2000-06-08  John Marshall  <john_w_marshall@palm.com>

(bfd)
	* coff-m68k.c (bfd_m68k_coff_create_embedded_relocs, 
	coff_m68k_bfd_print_private_bfd_data): New functions.
	* bfd-in.h: Declare bfd_m68k_coff_create_embedded_relocs.
	* bfd-in2.h: Rebuild.
(ld)
	* m68kcoff.em: New file.
	* m68kcoff.sh (TEMPLATE_NAME): Use m68kcoff template.
	* Makefile.am (em68kcoff.c): Depend upon m68kcoff.em rather than
	generic.em.
	* Makefile.in: Rebuild.

diff -urN orig/binutils-000608/bfd/bfd-in.h binutils-000608/bfd/bfd-in.h
--- orig/binutils-000608/bfd/bfd-in.h	Fri Apr 28 18:45:48 2000
+++ binutils-000608/bfd/bfd-in.h	Thu Jun  8 09:12:17 2000
@@ -748,4 +748,8 @@
 extern boolean bfd_elf32_arm_get_bfd_for_interworking
   PARAMS ((bfd *, struct bfd_link_info *));
 
+/* M68K embedded data relocations support.  Called from linker.  */
+extern bfd_byte *bfd_m68k_coff_create_embedded_relocs
+  PARAMS ((bfd *, struct sec *, bfd_byte *));
+
 /* And more from the source.  */
diff -urN orig/binutils-000608/bfd/bfd-in2.h binutils-000608/bfd/bfd-in2.h
--- orig/binutils-000608/bfd/bfd-in2.h	Fri Apr 28 18:45:48 2000
+++ binutils-000608/bfd/bfd-in2.h	Thu Jun  8 11:05:55 2000
@@ -748,6 +748,10 @@
 extern boolean bfd_elf32_arm_get_bfd_for_interworking
   PARAMS ((bfd *, struct bfd_link_info *));
 
+/* M68K embedded data relocations support.  Called from linker.  */
+extern bfd_byte *bfd_m68k_coff_create_embedded_relocs
+  PARAMS ((bfd *, struct sec *, bfd_byte *));
+
 /* And more from the source.  */
 void 
 bfd_init PARAMS ((void));
diff -urN orig/binutils-000608/bfd/coff-m68k.c binutils-000608/bfd/coff-m68k.c
--- orig/binutils-000608/bfd/coff-m68k.c	Mon Jul 19 07:55:15 1999
+++ binutils-000608/bfd/coff-m68k.c	Thu Jun  8 13:39:06 2000
@@ -203,6 +203,257 @@
 
 #define coff_bfd_reloc_type_lookup m68k_reloc_type_lookup
 
+
+/* A `.reloc' section contains data section relocations so that an embedded
+   target can relocate its data section at runtime.  Entries in this section
+   are 12 byte structs as follows:
+     int16 type		relocation type (currently only 1 is used)
+     int16 section	data section index containing the relocation
+     int32 offset	address within that section to be relocated
+     int16 symsection	section index of the symbol to be added
+     int16 zero		padding written as zero
+   The symbol offset can be found at the corresponding location to be
+   modified in the data section.  */
+
+/* Write any relocations in the data section SEC in the input bfd ABFD to
+   EMREL, which is a pointer into ABFD's `.reloc' section.  Return EMREL
+   stepped past any records which were written, or NULL on error.  */
+bfd_byte *
+bfd_m68k_coff_create_embedded_relocs (abfd, sec, emrel)
+     bfd *abfd;
+     asection *sec;
+     bfd_byte *emrel;
+{
+  struct internal_reloc *rel, *relend;
+
+  char *esyms = obj_coff_external_syms (abfd);
+  bfd_size_type symesz = bfd_coff_symesz (abfd);
+
+  rel = _bfd_coff_read_internal_relocs (abfd, sec, true, NULL, false, NULL);
+  relend = rel + sec->reloc_count;
+  for (; rel < relend; rel++)
+    {
+      asection *symsec;
+      unsigned int embedded_type = 0;
+
+      if (rel->r_symndx == -1)
+	symsec = bfd_abs_section_ptr;
+      else
+	{
+	  struct coff_link_hash_entry *h;
+	  h = obj_coff_sym_hashes (abfd)[rel->r_symndx];
+	  if (h == NULL)
+	    {
+	      struct internal_syment isym;
+	      bfd_coff_swap_sym_in (abfd, esyms + symesz*rel->r_symndx, &isym);
+	      symsec = coff_section_from_bfd_index (abfd, isym.n_scnum);
+	    }
+	  else if (h->root.type == bfd_link_hash_defined
+		   || h->root.type == bfd_link_hash_defweak)
+	    symsec = h->root.u.def.section;
+	  else
+	    symsec = NULL;
+	}
+
+      /* We can't use the internal type because that is an enum whose values
+         could change with new versions of BFD.  We don't want to use the
+	 external coff types because that would introduce a dependency on a
+	 non-exported part of BFD.  So we invent another numbering -- we'll
+	 likely only need just this one anyway.  */
+      switch (rel->r_type)
+	{
+	case R_RELLONG:
+	  embedded_type = 1;
+	  break;
+
+	default:
+	  bfd_set_error (bfd_error_bad_value);
+	  return NULL;
+	}
+
+      if (symsec && embedded_type)
+	{
+	  bfd_put_16 (abfd, embedded_type, emrel);
+	  bfd_put_16 (abfd, sec->output_section->index, emrel+2);
+	  bfd_put_32 (abfd, rel->r_vaddr - sec->vma + sec->output_offset,
+		      emrel+4);
+	  bfd_put_16 (abfd, symsec->output_section->index, emrel+8);
+	  bfd_put_16 (abfd, 0, emrel+10);
+	  emrel += 12;
+	}
+    }
+
+  return emrel;
+}
+
+
+/* Print the contents of ABFD's `.reloc' section to the file PTR.  */
+static boolean
+coff_m68k_bfd_print_private_bfd_data (abfd, ptr)
+     bfd *abfd;
+     PTR ptr;
+{
+  FILE *f = (FILE *) ptr;
+  asection *relocs_sec, *held_relsec;
+  bfd_byte *relocs, *rel, *relsec_contents;
+  bfd_size_type relocs_size, relsec_size;
+
+  relocs_sec = bfd_get_section_by_name (abfd, ".reloc");
+  if (relocs_sec == NULL)
+    return true;
+
+  fprintf (f, "\nEMBEDDED RELOCATION RECORDS:");
+
+  relocs_size = bfd_section_size (abfd, relocs_sec);
+  if (relocs_size == 0)
+    {
+      fprintf (f, " (none)\n\n");
+      return true;
+    }
+  else
+    fprintf (f, "\n");
+  
+  relocs = (bfd_byte *) bfd_malloc ((size_t) relocs_size);
+  bfd_get_section_contents (abfd, relocs_sec, (PTR) relocs, 0, relocs_size);
+
+  /* Get column headers lined up reasonably.  */
+  {
+    static int width;
+    if (width == 0)
+      {
+	char buf[30];
+	sprintf_vma (buf, (bfd_vma) -1);
+	width = strlen (buf) - 7;
+      }
+    fprintf (f, "SECTION+OFFSET    %*s TYPE %*s VALUE \n", width, "", 12, "");
+  }
+
+  held_relsec = NULL;
+  relsec_contents = NULL;
+  relsec_size = 0;
+
+  for (rel = relocs; rel < relocs + relocs_size; rel += 12)
+    {
+      asection *sec, *relsec, *symsec;
+      unsigned int embedded_type;
+      int relsecndx, symsecndx;
+      bfd_vma reloffset;
+      bfd_reloc_code_real_type type;
+      reloc_howto_type *howto;
+      CONST char *relsecname, *symsecname;
+      char relbuffer[32], symbuffer[32];
+      bfd_vma value = 0;
+
+      embedded_type = bfd_get_16 (abfd, rel);
+      relsecndx     = bfd_get_16 (abfd, rel+2);
+      reloffset     = bfd_get_32 (abfd, rel+4);
+      symsecndx     = bfd_get_16 (abfd, rel+8);
+
+      /* Decode the embedded relocation type.  See also the corresponding
+         encoding table in bfd_m68k_coff_create_embedded_relocs().  */
+      switch (embedded_type)
+	{
+	case 1:
+	  type = BFD_RELOC_32;
+	  break;
+
+	default:
+	  type = BFD_RELOC_UNUSED;  /* Something definitely unknown.  */
+	  break;
+	}
+
+      relsec = symsec = NULL;
+      for (sec = abfd->sections; sec; sec = sec->next)
+	{
+	  if (sec->index == relsecndx)
+	    relsec = sec;
+	  if (sec->index == symsecndx)
+	    symsec = sec;
+	}
+
+      sprintf (relbuffer, "[%d?]", relsecndx);
+      relsecname = (relsec)? bfd_section_name (abfd, relsec) : relbuffer;
+
+      sprintf (symbuffer, "[%d?]", symsecndx);
+      symsecname = (symsec)? bfd_section_name (abfd, symsec) : symbuffer;
+
+      fprintf (f, "%s+0x", relsecname);
+      fprintf_vma (f, reloffset);
+      fprintf (f, "%*s", 9 - strlen (relsecname), "");
+
+      howto = (relsec)? bfd_reloc_type_lookup (abfd, type) : NULL;
+      if (howto == NULL)
+	{
+	  char buf[32];
+	  sprintf (buf, "[0x%x]", (unsigned int) type);
+	  fprintf (f, "%-18.18s%s+?? (%s unknown)\n", buf, symsecname,
+		   (relsec)? "type" : "relocation section");
+	  continue;
+	}
+
+      fprintf (f, "%-18.18s", howto->name);
+
+      if (relsec == NULL)
+	{
+	  fprintf (f, "%s+?? (relocation section unknown)\n", symsecname);
+	  continue;
+	}
+
+      if (held_relsec != relsec)
+	{
+	  free (relsec_contents);
+	  held_relsec = relsec;
+	  relsec_size = bfd_section_size (abfd, relsec);
+	  relsec_contents = (bfd_byte *) bfd_malloc ((size_t) relsec_size);
+	  bfd_get_section_contents (abfd, relsec, (PTR) relsec_contents,
+				    0, relsec_size);
+	}
+
+      if (reloffset > relsec_size - bfd_get_reloc_size (howto))
+	{
+	  fprintf (f, "%s+?? (offset out of range)\n", symsecname);
+	  continue;
+	}
+
+      switch (bfd_get_reloc_size (howto))
+	{
+	default:
+	case 0:
+	  abort ();
+	case 1:
+	  value = bfd_get_8 (abfd, &relsec_contents[reloffset]);
+	  break;
+	case 2:
+	  value = bfd_get_16 (abfd, &relsec_contents[reloffset]);
+	  break;
+	case 4:
+	  value = bfd_get_32 (abfd, &relsec_contents[reloffset]);
+	  break;
+	case 8:
+#ifdef BFD64
+	  value = bfd_get_64 (abfd, &relsec_contents[reloffset]);
+#else
+	  abort ();
+#endif
+	  break;
+	}
+
+      value &= howto->dst_mask;
+      value >>= howto->bitpos;
+      value <<= howto->rightshift;
+
+      fprintf (f, "%s+0x", symsecname);
+      fprintf_vma (f, value - bfd_section_vma (abfd, symsec));
+      fprintf (f, "\n");
+    }
+
+  free (relocs);
+  free (relsec_contents);
+
+  return true;
+}
+
+
 #ifndef COFF_COMMON_ADDEND
 #ifndef coff_rtype_to_howto
 
@@ -423,6 +674,8 @@
 #define coff_bfd_is_local_label_name m68k_coff_is_local_label_name
 
 #define coff_relocate_section _bfd_coff_generic_relocate_section
+
+#define coff_bfd_print_private_bfd_data coff_m68k_bfd_print_private_bfd_data
 
 #include "coffcode.h"
 
diff -urN orig/binutils-000608/ld/Makefile.am binutils-000608/ld/Makefile.am
--- orig/binutils-000608/ld/Makefile.am	Tue Apr  4 22:36:43 2000
+++ binutils-000608/ld/Makefile.am	Thu Jun  8 09:29:54 2000
@@ -541,7 +541,7 @@
   $(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/m68kaux.sc ${GEN_DEPENDS}
 	${GENSCRIPTS} m68kaux "$(tdir_m68kaux)"
 em68kcoff.c: $(srcdir)/emulparams/m68kcoff.sh \
-  $(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/m68kcoff.sc ${GEN_DEPENDS}
+  $(srcdir)/emultempl/m68kcoff.em $(srcdir)/scripttempl/m68kcoff.sc ${GEN_DEPENDS}
 	${GENSCRIPTS} m68kcoff "$(tdir_m68kcoff)"
 em68kelf.c: $(srcdir)/emulparams/m68kelf.sh \
   $(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
diff -urN orig/binutils-000608/ld/Makefile.in binutils-000608/ld/Makefile.in
--- orig/binutils-000608/ld/Makefile.in	Tue Apr  4 22:36:43 2000
+++ binutils-000608/ld/Makefile.in	Thu Jun  8 09:48:28 2000
@@ -1240,7 +1240,7 @@
   $(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/m68kaux.sc ${GEN_DEPENDS}
 	${GENSCRIPTS} m68kaux "$(tdir_m68kaux)"
 em68kcoff.c: $(srcdir)/emulparams/m68kcoff.sh \
-  $(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/m68kcoff.sc ${GEN_DEPENDS}
+  $(srcdir)/emultempl/m68kcoff.em $(srcdir)/scripttempl/m68kcoff.sc ${GEN_DEPENDS}
 	${GENSCRIPTS} m68kcoff "$(tdir_m68kcoff)"
 em68kelf.c: $(srcdir)/emulparams/m68kelf.sh \
   $(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
diff -urN orig/binutils-000608/ld/emulparams/m68kcoff.sh binutils-000608/ld/emulparams/m68kcoff.sh
--- orig/binutils-000608/ld/emulparams/m68kcoff.sh	Mon May  3 00:29:07 1999
+++ binutils-000608/ld/emulparams/m68kcoff.sh	Thu Jun  8 09:31:33 2000
@@ -3,3 +3,4 @@
 TEXT_START_ADDR=0x1000000
 TARGET_PAGE_SIZE=0x1000000
 ARCH=m68k
+TEMPLATE_NAME=m68kcoff
diff -urN orig/binutils-000608/ld/emultempl/m68kcoff.em binutils-000608/ld/emultempl/m68kcoff.em
--- orig/binutils-000608/ld/emultempl/m68kcoff.em	Wed Dec 31 16:00:00 1969
+++ binutils-000608/ld/emultempl/m68kcoff.em	Thu Jun  8 13:27:33 2000
@@ -0,0 +1,212 @@
+# This shell script emits a C file. -*- C -*-
+# It does some substitutions.
+cat >e${EMULATION_NAME}.c <<EOF
+/* This file is is generated by a shell script.  DO NOT EDIT! */
+
+/* Handle embedded relocs for m68k coff.
+   Copyright 1994, 1998, 1999, 2000 Free Software Foundation, Inc.
+   Written by John Marshall <jmarshall@acm.org> based on generic.em,
+   with much inspiration from mipsecoff.em, which was
+   Written by Ian Lance Taylor <ian@cygnus.com> based on generic.em.
+
+This file is part of GLD, the Gnu Linker.
+
+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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#define TARGET_IS_${EMULATION_NAME}
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "bfdlink.h"
+#include "libbfd.h"
+
+#include "ld.h"
+#include "ldmain.h"
+#include "ldemul.h"
+#include "ldfile.h"
+#include "ldmisc.h"
+
+static void gld${EMULATION_NAME}_before_parse PARAMS ((void));
+static void gld${EMULATION_NAME}_after_open PARAMS ((void));
+static void gld${EMULATION_NAME}_after_allocation PARAMS ((void));
+static char *gld${EMULATION_NAME}_get_script PARAMS ((int *isfile));
+
+static void
+gld${EMULATION_NAME}_before_parse()
+{
+#ifndef TARGET_			/* I.e., if not generic.  */
+  ldfile_set_output_arch ("`echo ${ARCH}`");
+#endif /* not TARGET_ */
+}
+
+/* This function is run after all the input files have been opened.
+   We create a .reloc section for each input file with any relocations
+   needed in any data section.  The BFD backend will fill in these sections
+   with magic numbers which can be used to relocate the data section at run
+   time.  */
+
+static void
+gld${EMULATION_NAME}_after_open ()
+{
+  bfd *abfd;
+
+  if (! command_line.embedded_relocs
+      || link_info.relocateable)
+    return;
+
+  for (abfd = link_info.input_bfds; abfd != NULL; abfd = abfd->link_next)
+    {
+      asection *sec;
+      unsigned total_data_relocs = 0;
+
+      /* Note that we assume that the reloc_count field has already
+         been set up.  We could call bfd_get_reloc_upper_bound, but
+         that returns the size of a memory buffer rather than a reloc
+         count.  We do not want to call bfd_canonicalize_reloc,
+         because although it would always work it would force us to
+         read in the relocs into BFD canonical form, which would waste
+         a significant amount of time and memory.  */
+
+      for (sec = abfd->sections; sec; sec = sec->next)
+	if (sec->flags & SEC_DATA)
+	  total_data_relocs += sec->reloc_count;
+
+      if (total_data_relocs > 0)
+	{
+	  asection *relsec;
+
+	  relsec = bfd_make_section (abfd, ".reloc");
+	  if (relsec == NULL
+	      || ! bfd_set_section_flags (abfd, relsec,
+					  (SEC_HAS_CONTENTS | SEC_IN_MEMORY))
+	      || ! bfd_set_section_size (abfd, relsec, total_data_relocs * 12)
+	      || (relsec->contents = (bfd_byte *)
+			bfd_zalloc (abfd, total_data_relocs * 12)) == NULL)
+	    einfo ("%F%B: can not create .reloc section: %E\n");
+	}
+    }
+}
+
+/* This function is called after the section sizes and offsets have
+   been set.  If we are generating embedded relocs, it calls a special
+   BFD backend routine to do the work.  */
+
+static void
+gld${EMULATION_NAME}_after_allocation ()
+{
+  bfd *abfd;
+
+  if (! command_line.embedded_relocs
+      || link_info.relocateable)
+    return;
+
+  for (abfd = link_info.input_bfds; abfd != NULL; abfd = abfd->link_next)
+    {
+      asection *relsec = bfd_get_section_by_name (abfd, ".reloc");
+      if (relsec)
+	{
+	  asection *sec;
+	  bfd_byte *emrel = (bfd_byte *) relsec->contents;
+
+	  for (sec = abfd->sections; sec && emrel; sec = sec->next)
+	    if ((sec->flags & SEC_DATA) && sec->reloc_count > 0)
+	      emrel = bfd_m68k_coff_create_embedded_relocs (abfd, sec, emrel);
+
+	  if (! emrel)
+	    einfo ("%F%B: cannot create embedded relocations: %E\n", abfd);
+	}
+    }
+}
+
+static char *
+gld${EMULATION_NAME}_get_script(isfile)
+     int *isfile;
+EOF
+
+if test -n "$COMPILE_IN"
+then
+# Scripts compiled in.
+
+# sed commands to quote an ld script as a C string.
+sc="-f stringify.sed"
+
+cat >>e${EMULATION_NAME}.c <<EOF
+{			     
+  *isfile = 0;
+
+  if (link_info.relocateable == true && config.build_constructors == true)
+    return
+EOF
+sed $sc ldscripts/${EMULATION_NAME}.xu                     >> e${EMULATION_NAME}.c
+echo '  ; else if (link_info.relocateable == true) return' >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xr                     >> 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
+
+else
+# Scripts read from the filesystem.
+
+cat >>e${EMULATION_NAME}.c <<EOF
+{			     
+  *isfile = 1;
+
+  if (link_info.relocateable == true && config.build_constructors == true)
+    return "ldscripts/${EMULATION_NAME}.xu";
+  else if (link_info.relocateable == true)
+    return "ldscripts/${EMULATION_NAME}.xr";
+  else if (!config.text_read_only)
+    return "ldscripts/${EMULATION_NAME}.xbn";
+  else if (!config.magic_demand_paged)
+    return "ldscripts/${EMULATION_NAME}.xn";
+  else
+    return "ldscripts/${EMULATION_NAME}.x";
+}
+EOF
+
+fi
+
+cat >>e${EMULATION_NAME}.c <<EOF
+
+struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = 
+{
+  gld${EMULATION_NAME}_before_parse,
+  syslib_default,
+  hll_default,
+  after_parse_default,
+  gld${EMULATION_NAME}_after_open,
+  gld${EMULATION_NAME}_after_allocation,
+  set_output_arch_default,
+  ldemul_default_target,
+  before_allocation_default,
+  gld${EMULATION_NAME}_get_script,
+  "${EMULATION_NAME}",
+  "${OUTPUT_FORMAT}",
+  NULL,	/* finish */
+  NULL,	/* create output section statements */
+  NULL,	/* open dynamic archive */
+  NULL,	/* place orphan */
+  NULL,	/* set symbols */
+  NULL,	/* parse args */
+  NULL,	/* unrecognized file */
+  NULL,	/* list options */
+  NULL,	/* recognized file */
+  NULL 	/* find_potential_libraries */
+};
+EOF

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]