public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* [patch] VxWorks x86 shared library support.
@ 2005-04-14 13:58 Paul Brook
  2005-04-15  7:09 ` Alan Modra
  0 siblings, 1 reply; 4+ messages in thread
From: Paul Brook @ 2005-04-14 13:58 UTC (permalink / raw)
  To: binutils

[-- Attachment #1: Type: text/plain, Size: 2906 bytes --]

The attached patch implements support for x86 VxWorks shared libraries.

VxWorks shared libraries are somewhat different to sysv shared libraries, so I 
needed to make a couple of changes to common code:
- The __GOTT_BASE__ and __GOTT_INDEX__ symbols are supplied by the OS loader, 
so we need to allow undefined references to these symbols.
- The OS loader requires both the normal dynamic relocations and a copy of the 
original static relocations for the PLT.

Both these changes will also be used by other (not yet submitted) VxWorks 
targets.

To actually generate working executables an additional option to create 
dynamic sections in executables is needed. This will follow shortly.

Tested on i586-wrs-vxworks and i686-pc-linux-gnu.
Ok?

Paul

2004-01-19  Paul Brook  <paul@codesourcery.com>

bfd/
	* config.bfd: Use bfd_elf32_i386_vxworks_vec for i?86-*-vxworks.
	* configure.in: Add bfd_elf32_i386_vxworks_vec.
	* configure: Regenerate.
	* elf-bfd.h (struct elf_backend_data): Add is_vxworks.
	(RELOC_FOR_GLOBAL_SYMBOL): Ignore VxWorks magic GOT symbols.
	* elf.c (assign_section_numbers): Add special handling for VxWorks
	.plt.unloaded section.
	* elflink.c (_bfd_elf_create_dynamic_sections): Mark VxWorks PLT
	symbols as functions.
	(elf_link_adjust_relocs): Convert SHN_UNDEF relocs for PLT stubs
	into section relative relocs.
	(elf_link_output_extsym): Ignore undefined VxWorks GOTT symbols.
	* elfxx-target.h (elf_backend_is_vxworks): Define.
	(elfNN_bed): Use it.
	* targets.c (bfd_elf32_i386_vxworks_vec): Declare.
	(_bfd_target_vector): Add bfd_elf32_i386_vxworks_vec.
	* elf32-i386.c: Add elf32-i386-vxworks target BFD.
	(PLTRESOLVE_RELOCS_SHLIB, PLTRESOLVE_RELOCS): Define.
	(PLT_NON_JUMP_SLOT_RELOCS): Define.
	(elf_i386_link_hash_table): Add srelplt2, hgot, hplt, is_vxworks and
	plt0_pad_byte fields.
	(elf_i386_link_hash_table_create): Zero them.
	(elf_i386_create_dynamic_sections): Create static relocation section.
	(allocate_dynrelocs): Allocate space for static PLT relocations.
	(elf_i386_size_dynamic_sections): Save shortcuts to PLT and GOT
	symbols.  Don't strip PLT sections if we have exported symbols from
	them.
	(elf_i386_finish_dynamic_symbol): Fill in VxWorks PLT static
	relocation section.  Don't mark _GLOBAL_OFFSET_TABLE_ as absolute on
	VxWorks.
	(elf_i386_finish_dynamic_sections): Allow different pad bytes.
	Add relocation for GOT location.  Fill in PLT static relocations.
	(elf_i386_vxworks_link_hash_table_create): New function.
gas/
	* config/tc-i386.h (ELF_TARGET_FORMAT): Define for TE_VXWORKS.
gas/testsuite/
	* gas/i386/i386.exp: Don't run divide test on vxworks.
ld/
	* Makefile.am: Add eelf_i386_vxworks.
	* Makefile.in: Regenerate.
	* configure.tgt: Make i?86-*-vxworks use targ_emul=elf_i386_vxworks.
	* emulparams/elf_i386_vxworks.sh: New file.
	* emulparams/vxworks.sh: New file.
	* scripttempl/elf.sc: Add DATA_END_SYMBOLS and ETEXT_NAME.

[-- Attachment #2: patch.vxworks_i386 --]
[-- Type: text/x-diff, Size: 29391 bytes --]

Index: bfd/config.bfd
===================================================================
RCS file: /var/cvsroot/src-cvs/src/bfd/config.bfd,v
retrieving revision 1.183
diff -u -p -r1.183 config.bfd
--- bfd/config.bfd	23 Mar 2005 15:35:43 -0000	1.183
+++ bfd/config.bfd	12 Apr 2005 15:00:30 -0000
@@ -601,7 +601,7 @@ case "${targ}" in
     targ_defvec=i386aout_vec
     ;;
   i[3-7]86-*-vxworks)
-    targ_defvec=bfd_elf32_i386_vec
+    targ_defvec=bfd_elf32_i386_vxworks_vec
     targ_underscore=yes
     ;;
   i[3-7]86-*-chaos)
Index: bfd/configure.in
===================================================================
RCS file: /var/cvsroot/src-cvs/src/bfd/configure.in,v
retrieving revision 1.174
diff -u -p -r1.174 configure.in
--- bfd/configure.in	5 Apr 2005 07:58:38 -0000	1.174
+++ bfd/configure.in	12 Apr 2005 15:00:30 -0000
@@ -621,6 +621,7 @@ do
     bfd_elf32_hppa_vec)		tb="$tb elf32-hppa.lo elf32.lo $elf" ;;
     bfd_elf32_i370_vec)		tb="$tb elf32-i370.lo elf32.lo $elf" ;;
     bfd_elf32_i386_freebsd_vec)	tb="$tb elf32-i386.lo elf32.lo $elf" ;;
+    bfd_elf32_i386_vxworks_vec)	tb="$tb elf32-i386.lo elf32.lo $elf" ;;
     bfd_elf32_i386_vec)		tb="$tb elf32-i386.lo elf32.lo $elf" ;;
     bfd_elf32_i860_little_vec)	tb="$tb elf32-i860.lo elf32.lo $elf" ;;
     bfd_elf32_i860_vec)		tb="$tb elf32-i860.lo elf32.lo $elf" ;;
Index: bfd/elf-bfd.h
===================================================================
RCS file: /var/cvsroot/src-cvs/src/bfd/elf-bfd.h,v
retrieving revision 1.179
diff -u -p -r1.179 elf-bfd.h
--- bfd/elf-bfd.h	4 Apr 2005 16:11:02 -0000	1.179
+++ bfd/elf-bfd.h	12 Apr 2005 15:19:33 -0000
@@ -1035,6 +1035,9 @@ struct elf_backend_data
        that the p_paddr field in the section header to be set to zero.
        This field indicates whether this behavior is required.  */
   unsigned want_p_paddr_set_to_zero : 1;
+
+  /* Set for VxWorks target to enable special shared library hamdling.  */
+  unsigned is_vxworks : 1;
 };
 
 /* Information stored for each BFD section in an ELF file.  This
@@ -1841,6 +1844,15 @@ extern bfd_boolean _sh_elf_set_mach_from
       else if (info->unresolved_syms_in_objects == RM_IGNORE		\
 	       && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)		\
 	;								\
+     else if (get_elf_backend_data (input_bfd)->is_vxworks		\
+	      && info->shared						\
+	      && (strcmp (h->root.root.string, "__GOTT_BASE__") == 0	\
+		  || strcmp (h->root.root.string, "__GOTT_INDEX__") == 0)) \
+	/* Ideally these "magic" symbols would be exported by libc.so.1	\
+	   which would be found via a DT_NEEDED tag, and then handled	\
+	   specially by the linker at runtime.  Except shared libraries	\
+	   don't even link to libc.so.1 by default... */		\
+	;								\
       else								\
 	{								\
 	  bfd_boolean err;						\
Index: bfd/elf.c
===================================================================
RCS file: /var/cvsroot/src-cvs/src/bfd/elf.c,v
retrieving revision 1.277
diff -u -p -r1.277 elf.c
--- bfd/elf.c	5 Apr 2005 04:01:09 -0000	1.277
+++ bfd/elf.c	12 Apr 2005 15:20:26 -0000
@@ -2736,6 +2736,7 @@ assign_section_numbers (bfd *abfd, struc
   Elf_Internal_Shdr **i_shdrp;
   bfd_size_type amt;
   struct bfd_elf_section_data *d;
+  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
 
   section_number = 1;
 
@@ -2931,8 +2932,6 @@ assign_section_numbers (bfd *abfd, struc
 		         where elfsec is 0.  */
 		      if (elfsec == 0)
 			{
-			  const struct elf_backend_data *bed
-			    = get_elf_backend_data (abfd);
 			  if (bed->link_order_error_handler)
 			    bed->link_order_error_handler
 			      (_("%B: warning: sh_link not set for section `%A'"),
@@ -2990,6 +2989,19 @@ assign_section_numbers (bfd *abfd, struc
 	  else
 	    name += 5;
 	  s = bfd_get_section_by_name (abfd, name);
+
+	  /* For VxWorks dynamic RTPs we have both dynamic and
+	     non-dynamic relocation sections which apply to the same place.
+	     The non-dynamic one has a different name and refers to the
+	     static symbol table.  The hack below makes this work.  */
+	  if (bed->is_vxworks && strcmp (name, ".plt.unloaded") == 0)
+	      {
+		d->this_hdr.sh_link = t->symtab_section;
+
+		if (s == NULL)
+		  s = bfd_get_section_by_name (abfd, ".plt");
+	      }
+
 	  if (s != NULL)
 	    d->this_hdr.sh_info = elf_section_data (s)->this_idx;
 	  break;
Index: bfd/elf32-i386.c
===================================================================
RCS file: /var/cvsroot/src-cvs/src/bfd/elf32-i386.c,v
retrieving revision 1.132
diff -u -p -r1.132 elf32-i386.c
--- bfd/elf32-i386.c	6 Feb 2005 18:11:29 -0000	1.132
+++ bfd/elf32-i386.c	12 Apr 2005 15:20:08 -0000
@@ -516,6 +516,12 @@ static const bfd_byte elf_i386_pic_plt_e
   0, 0, 0, 0	/* replaced with offset to start of .plt.  */
 };
 
+/* On VxWorks, the .rel.plt.unloaded section has absolute relocations
+   for the PLTResolve stub and then for each PLT entry.  */
+#define PLTRESOLVE_RELOCS_SHLIB 0
+#define PLTRESOLVE_RELOCS 2
+#define PLT_NON_JUMP_SLOT_RELOCS 2
+
 /* The i386 linker needs to keep track of the number of relocs that it
    decides to copy as dynamic relocs in check_relocs for each symbol.
    This is so that it can later discard them if they are found to be
@@ -595,7 +601,19 @@ struct elf_i386_link_hash_table
   asection *srelplt;
   asection *sdynbss;
   asection *srelbss;
-
+  
+  /* The (unloaded but important) .rel.plt.unloaded section on VxWorks.  */
+  asection *srelplt2;
+
+  /* Short-cuts to frequently used symbols for VxWorks targets.  */
+  struct elf_link_hash_entry *hgot, *hplt;
+
+  /* True if the target system is VxWorks.  */
+  int is_vxworks;
+
+  /* Value used to fill the last word of the first plt entry.  */
+  bfd_byte plt0_pad_byte;
+  
   union {
     bfd_signed_vma refcount;
     bfd_vma offset;
@@ -668,6 +686,11 @@ elf_i386_link_hash_table_create (bfd *ab
   ret->srelbss = NULL;
   ret->tls_ldm_got.refcount = 0;
   ret->sym_sec.abfd = NULL;
+  ret->is_vxworks = 0;
+  ret->srelplt2 = NULL;
+  ret->hgot = NULL;
+  ret->hplt = NULL;
+  ret->plt0_pad_byte = 0;
 
   return &ret->elf.root;
 }
@@ -708,6 +731,9 @@ static bfd_boolean
 elf_i386_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info)
 {
   struct elf_i386_link_hash_table *htab;
+  asection * s;
+  int flags;
+  const struct elf_backend_data *bed = get_elf_backend_data (dynobj);
 
   htab = elf_i386_hash_table (info);
   if (!htab->sgot && !create_got_section (dynobj, info))
@@ -726,6 +752,18 @@ elf_i386_create_dynamic_sections (bfd *d
       || (!info->shared && !htab->srelbss))
     abort ();
 
+  if (htab->is_vxworks && !info->shared)
+    {
+      s = bfd_make_section (dynobj, ".rel.plt.unloaded");
+      flags = (SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_READONLY
+	      | SEC_LINKER_CREATED);
+      if (s == NULL
+	 || ! bfd_set_section_flags (dynobj, s, flags)
+	 || ! bfd_set_section_alignment (dynobj, s, bed->s->log_file_align))
+       return FALSE;
+      htab->srelplt2 = s;
+    }
+
   return TRUE;
 }
 
@@ -1526,6 +1564,26 @@ allocate_dynrelocs (struct elf_link_hash
 
 	  /* We also need to make an entry in the .rel.plt section.  */
 	  htab->srelplt->size += sizeof (Elf32_External_Rel);
+
+	  if (htab->is_vxworks && !info->shared)
+	    {
+	      /* VxWorks has a second set of relocations for each PLT entry
+		 in executables.  They go in a separate relocation section,
+		 which is processed by the kernel loader.  */
+
+	      /* There are two relocations for the initial PLT entry: an
+		 R_386_32 relocation for _GLOBAL_OFFSET_TABLE_ + 4 and an
+		 R_386_32 relocation for _GLOBAL_OFFSET_TABLE_ + 8.  */
+
+	      if (h->plt.offset == PLT_ENTRY_SIZE)
+		htab->srelplt2->size += (sizeof (Elf32_External_Rel) * 2);
+
+	      /* There are two extra relocations for each subsequent PLT entry:
+		 an R_386_32 relocation for the GOT entry, and an R_386_32
+		 relocation for the PLT entry.  */
+
+	      htab->srelplt2->size += (sizeof (Elf32_External_Rel) * 2);
+	    }
 	}
       else
 	{
@@ -1816,6 +1874,24 @@ elf_i386_size_dynamic_sections (bfd *out
   else
     htab->tls_ldm_got.offset = -1;
 
+  if (htab->is_vxworks)
+    {
+      /* Save the GOT and PLT symbols in the hash table for easy access.
+	 Mark them as having relocations; they might not, but we won't
+	 know for sure until we build the GOT in finish_dynamic_symbol.  */
+
+      htab->hgot = elf_link_hash_lookup (elf_hash_table (info),
+					"_GLOBAL_OFFSET_TABLE_",
+					FALSE, FALSE, FALSE);
+      if (htab->hgot)
+	htab->hgot->indx = -2;
+      htab->hplt = elf_link_hash_lookup (elf_hash_table (info),
+					"_PROCEDURE_LINKAGE_TABLE_",
+					FALSE, FALSE, FALSE);
+      if (htab->hplt)
+	htab->hplt->indx = -2;
+    }
+
   /* Allocate global sym .plt and .got entries, and space for global
      sym dynamic relocs.  */
   elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, (PTR) info);
@@ -1825,6 +1901,8 @@ elf_i386_size_dynamic_sections (bfd *out
   relocs = FALSE;
   for (s = dynobj->sections; s != NULL; s = s->next)
     {
+      bfd_boolean strip_section = TRUE;
+
       if ((s->flags & SEC_LINKER_CREATED) == 0)
 	continue;
 
@@ -1834,10 +1912,16 @@ elf_i386_size_dynamic_sections (bfd *out
 	{
 	  /* Strip this section if we don't need it; see the
 	     comment below.  */
+	  /* We'd like to strip these sections if they aren't needed, but if
+	     we've exported dynamic symbols from them we must leave them.
+	     It's too late to tell BFD to get rid of the symbols.  */
+
+	  if (htab->hplt != NULL)
+	    strip_section = FALSE;
 	}
       else if (strncmp (bfd_get_section_name (dynobj, s), ".rel", 4) == 0)
 	{
-	  if (s->size != 0 && s != htab->srelplt)
+	  if (s->size != 0 && s != htab->srelplt && s != htab->srelplt2)
 	    relocs = TRUE;
 
 	  /* We use the reloc_count field as a counter if we need
@@ -1850,7 +1934,7 @@ elf_i386_size_dynamic_sections (bfd *out
 	  continue;
 	}
 
-      if (s->size == 0)
+      if (s->size == 0 && strip_section)
 	{
 	  /* If we don't need this section, strip it from the
 	     output file.  This is mostly to handle .rel.bss and
@@ -3029,6 +3113,43 @@ elf_i386_finish_dynamic_symbol (bfd *out
 		       + htab->sgotplt->output_offset
 		       + got_offset),
 		      htab->splt->contents + h->plt.offset + 2);
+
+	  if (htab->is_vxworks)
+	    {
+	      int s, k, reloc_index;
+
+	      /* Create the R_386_32 relocation referencing the GOT
+		 for this PLT entry.  */
+
+	      /* S: Current slot number (zero-based).  */
+	      s = (h->plt.offset - PLT_ENTRY_SIZE) / PLT_ENTRY_SIZE;
+	      /* K: Number of relocations for PLTResolve. */
+	      if (info->shared)
+		k = PLTRESOLVE_RELOCS_SHLIB;
+	      else
+		k = PLTRESOLVE_RELOCS;
+	      /* Skip the PLTresolve relocations, and the relocations for
+		 the other PLT slots. */
+	      reloc_index = k + s * PLT_NON_JUMP_SLOT_RELOCS;
+	      loc = (htab->srelplt2->contents + reloc_index
+		     * sizeof (Elf32_External_Rel));
+
+	      rel.r_offset = (htab->splt->output_section->vma
+			      + htab->splt->output_offset
+			      + h->plt.offset + 2),
+	      rel.r_info = ELF32_R_INFO (htab->hgot->indx, R_386_32);
+	      bfd_elf32_swap_reloc_out (output_bfd, &rel, loc);
+
+	      /* Create the R_386_32 relocation referencing the beginning of
+		 the PLT for this GOT entry.  */
+	      rel.r_offset = (htab->sgotplt->output_section->vma
+			      + htab->sgotplt->output_offset
+			      + got_offset);
+	      rel.r_info = ELF32_R_INFO (htab->hplt->indx, R_386_32);
+	      bfd_elf32_swap_reloc_out (output_bfd, &rel,
+	      loc + sizeof (Elf32_External_Rel));
+	    }
+
 	}
       else
 	{
@@ -3138,9 +3259,12 @@ elf_i386_finish_dynamic_symbol (bfd *out
       bfd_elf32_swap_reloc_out (output_bfd, &rel, loc);
     }
 
-  /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute.  */
+  /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute.
+     On VxWorks, the _GLOBAL_OFFSET_TABLE_ symbol is not absolute: it
+     is relative to the ".got" section.  */
   if (strcmp (h->root.root.string, "_DYNAMIC") == 0
-      || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0)
+      || (strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0
+	  && !htab->is_vxworks))
     sym->st_shndx = SHN_ABS;
 
   return TRUE;
@@ -3248,12 +3372,16 @@ elf_i386_finish_dynamic_sections (bfd *o
       if (htab->splt && htab->splt->size > 0)
 	{
 	  if (info->shared)
-	    memcpy (htab->splt->contents,
-		    elf_i386_pic_plt0_entry, PLT_ENTRY_SIZE);
+	    {
+	      memcpy (htab->splt->contents,
+		      elf_i386_pic_plt0_entry, PLT_ENTRY_SIZE);
+	      memset (htab->splt->contents + 12, htab->plt0_pad_byte, 4);
+	    }
 	  else
 	    {
 	      memcpy (htab->splt->contents,
 		      elf_i386_plt0_entry, PLT_ENTRY_SIZE);
+	      memset (htab->splt->contents + 12, htab->plt0_pad_byte, 4);
 	      bfd_put_32 (output_bfd,
 			  (htab->sgotplt->output_section->vma
 			   + htab->sgotplt->output_offset
@@ -3264,12 +3392,69 @@ elf_i386_finish_dynamic_sections (bfd *o
 			   + htab->sgotplt->output_offset
 			   + 8),
 			  htab->splt->contents + 8);
+
+	      if (htab->is_vxworks)
+		{
+		  Elf_Internal_Rela rel;
+		  struct elf_link_hash_entry *hgot;
+
+		  /* The VxWorks GOT is relocated by the dynamic linker.
+		     Therefore, we must emit relocations rather than
+		     simply computing the values now.  */
+		  hgot = elf_link_hash_lookup (elf_hash_table (info),
+					       "_GLOBAL_OFFSET_TABLE_",
+					       FALSE, FALSE, FALSE);
+		  /* Generate a relocation for _GLOBAL_OFFSET_TABLE_ + 4.
+		     On IA32 we use REL relocations so the addend goes in
+		     the PLT directly.  */
+		  rel.r_offset = (htab->splt->output_section->vma
+				  + htab->splt->output_offset
+				  + 2);
+		  rel.r_info = ELF32_R_INFO (hgot->indx, R_386_32);
+		  bfd_elf32_swap_reloc_out (output_bfd, &rel,
+					    htab->srelplt2->contents);
+		  /* Generate a relocation for _GLOBAL_OFFSET_TABLE_ + 8.  */
+		  rel.r_offset = (htab->splt->output_section->vma
+				  + htab->splt->output_offset
+				  + 8);
+		  rel.r_info = ELF32_R_INFO (hgot->indx, R_386_32);
+		  bfd_elf32_swap_reloc_out (output_bfd, &rel,
+					    htab->srelplt2->contents +
+					    sizeof (Elf32_External_Rel));
+		}
 	    }
 
 	  /* UnixWare sets the entsize of .plt to 4, although that doesn't
 	     really seem like the right value.  */
 	  elf_section_data (htab->splt->output_section)
 	    ->this_hdr.sh_entsize = 4;
+
+	  /* Correct the .rel.plt.unloaded relocations.  */
+	  if (htab->is_vxworks && !info->shared)
+	    {
+	      int num_plts = (htab->splt->size / PLT_ENTRY_SIZE) - 1;
+	      char *p;
+
+	      p = htab->srelplt2->contents;
+	      if (info->shared)
+		p += PLTRESOLVE_RELOCS_SHLIB * sizeof (Elf32_External_Rel);
+	      else
+		p += PLTRESOLVE_RELOCS * sizeof (Elf32_External_Rel);
+
+	      for (; num_plts; num_plts--)
+		{
+		  Elf_Internal_Rela rel;
+		  bfd_elf32_swap_reloc_in (output_bfd, p, &rel);
+		  rel.r_info = ELF32_R_INFO (htab->hgot->indx, R_386_32);
+		  bfd_elf32_swap_reloc_out (output_bfd, &rel, p);
+		  p += sizeof (Elf32_External_Rel);
+
+		  bfd_elf32_swap_reloc_in (output_bfd, p, &rel);
+		  rel.r_info = ELF32_R_INFO (htab->hplt->indx, R_386_32);
+		  bfd_elf32_swap_reloc_out (output_bfd, &rel, p);
+		  p += sizeof (Elf32_External_Rel);
+		}
+	    }
 	}
     }
 
@@ -3380,3 +3565,46 @@ elf_i386_post_process_headers (bfd *abfd
 #define	elf32_bed				elf32_i386_fbsd_bed
 
 #include "elf32-target.h"
+
+/* VxWorks support.  */
+
+#undef	TARGET_LITTLE_SYM
+#define	TARGET_LITTLE_SYM		bfd_elf32_i386_vxworks_vec
+#undef	TARGET_LITTLE_NAME
+#define	TARGET_LITTLE_NAME		"elf32-i386-vxworks"
+
+/* Like elf_i386_link_hash_table_create but with tweaks for VxWorks.  */
+
+static struct bfd_link_hash_table *
+elf_i386_vxworks_link_hash_table_create (bfd *abfd)
+{
+  struct bfd_link_hash_table *ret;
+  struct elf_i386_link_hash_table *htab;
+
+  ret = elf_i386_link_hash_table_create (abfd);
+  if (ret)
+    {
+      htab = (struct elf_i386_link_hash_table *) ret;
+      htab->is_vxworks = 1;
+      htab->plt0_pad_byte = 0x90;
+    }
+
+  return ret;
+}
+
+#undef	elf_backend_post_process_headers
+#define	elf_backend_post_process_headers	elf_i386_post_process_headers
+#undef bfd_elf32_bfd_link_hash_table_create
+#define bfd_elf32_bfd_link_hash_table_create \
+  elf_i386_vxworks_link_hash_table_create
+/* On VxWorks, we emit relocations against _PROCEDURE_LINKAGE_TABLE_, so
+   define it.  */
+#undef elf_backend_want_plt_sym
+#define elf_backend_want_plt_sym	1
+#undef elf_backend_is_vxworks
+#define elf_backend_is_vxworks 1
+
+#undef	elf32_bed
+#define	elf32_bed				elf32_i386_vxworks_bed
+
+#include "elf32-target.h"
Index: bfd/elflink.c
===================================================================
RCS file: /var/cvsroot/src-cvs/src/bfd/elflink.c,v
retrieving revision 1.144
diff -u -p -r1.144 elflink.c
--- bfd/elflink.c	1 Apr 2005 03:49:46 -0000	1.144
+++ bfd/elflink.c	13 Apr 2005 17:13:03 -0000
@@ -299,7 +299,10 @@ _bfd_elf_create_dynamic_sections (bfd *a
 	return FALSE;
       h = (struct elf_link_hash_entry *) bh;
       h->def_regular = 1;
-      h->type = STT_OBJECT;
+      if (bed->is_vxworks && (pltflags & SEC_CODE) != 0)
+	h->type = STT_FUNC;
+      else
+	h->type = STT_OBJECT;
 
       if (! info->executable
 	  && ! bfd_elf_link_record_dynamic_symbol (info, h))
@@ -5846,9 +5849,40 @@ elf_link_adjust_relocs (bfd *abfd,
       BFD_ASSERT ((*rel_hash)->indx >= 0);
 
       (*swap_in) (abfd, erela, irela);
-      for (j = 0; j < bed->s->int_rels_per_ext_rel; j++)
-	irela[j].r_info = ((bfd_vma) (*rel_hash)->indx << r_sym_shift
-			   | (irela[j].r_info & r_type_mask));
+      if (bed->is_vxworks
+	  && (abfd->flags & (DYNAMIC|EXEC_P))
+	  && (*rel_hash)->def_dynamic
+	  && !(*rel_hash)->def_regular
+	  && (*rel_hash)->root.type == bfd_link_hash_defined
+	  && (*rel_hash)->root.u.def.section->output_section != NULL)
+	{
+	  /* This is a relocation from an executable or shared library
+	     against a symbol in a different shared library.  We are
+	     createing a definition in the output file but it does not come
+	     from any of out normal (.o) files. ie. a PLT stub.
+	     Normally this would be a relocation against against SHN_UNDEF
+	     with the VMA of the PLT stub.  This upsets the VxWorks loader.
+	     Convert it to a section-relative relocation.
+	     This gets some other symbols (for instance .dynbss),
+	     but is conservatively correct.  */
+	  for (j = 0; j < bed->s->int_rels_per_ext_rel; j++)
+	    {
+	      asection *sec = (*rel_hash)->root.u.def.section;
+	      int this_idx =
+		elf_section_data (sec->output_section)->this_idx;
+
+	      irela[j].r_info = ((bfd_vma) this_idx << r_sym_shift
+				| (irela[j].r_info & r_type_mask));
+	      irela[j].r_addend += (*rel_hash)->root.u.def.value;
+	      irela[j].r_addend += sec->output_offset;
+	    }
+	}
+      else
+	{
+	  for (j = 0; j < bed->s->int_rels_per_ext_rel; j++)
+	    irela[j].r_info = ((bfd_vma) (*rel_hash)->indx << r_sym_shift
+			      | (irela[j].r_info & r_type_mask));
+	}
       (*swap_out) (abfd, irela, erela);
     }
 }
@@ -6332,7 +6366,14 @@ elf_link_output_extsym (struct elf_link_
       && h->ref_dynamic
       && !h->ref_regular
       && ! elf_link_check_versioned_symbol (finfo->info, bed, h)
-      && finfo->info->unresolved_syms_in_shared_libs != RM_IGNORE)
+      && finfo->info->unresolved_syms_in_shared_libs != RM_IGNORE
+      /* On VxWorks, these two symbols are undefined in shared
+	 libaries.  The Diab compiler does not create undefined
+	 references in the main executable so using "-u __GOTT_BASE__"
+	 when invoking GNU ld would not be fully compatible.  */
+      && (!bed->is_vxworks
+	  || (strcmp (h->root.root.string, "__GOTT_BASE__") != 0
+	      && strcmp (h->root.root.string, "__GOTT_INDEX__") != 0)))
     {
       if (! ((*finfo->info->callbacks->undefined_symbol)
 	     (finfo->info, h->root.root.string, h->root.u.undef.abfd,
Index: bfd/elfxx-target.h
===================================================================
RCS file: /var/cvsroot/src-cvs/src/bfd/elfxx-target.h,v
retrieving revision 1.79
diff -u -p -r1.79 elfxx-target.h
--- bfd/elfxx-target.h	2 Mar 2005 04:47:25 -0000	1.79
+++ bfd/elfxx-target.h	12 Apr 2005 15:20:43 -0000
@@ -99,6 +99,9 @@
 #ifndef elf_backend_want_p_paddr_set_to_zero
 #define elf_backend_want_p_paddr_set_to_zero 0
 #endif
+#ifndef elf_backend_is_vxworks
+#define elf_backend_is_vxworks 0
+#endif
 
 #define bfd_elfNN_bfd_debug_info_start	bfd_void
 #define bfd_elfNN_bfd_debug_info_end	bfd_void
@@ -610,7 +613,8 @@ static const struct elf_backend_data elf
   elf_backend_can_refcount,
   elf_backend_want_got_sym,
   elf_backend_want_dynbss,
-  elf_backend_want_p_paddr_set_to_zero
+  elf_backend_want_p_paddr_set_to_zero,
+  elf_backend_is_vxworks
 };
 #endif
 
Index: bfd/targets.c
===================================================================
RCS file: /var/cvsroot/src-cvs/src/bfd/targets.c,v
retrieving revision 1.124
diff -u -p -r1.124 targets.c
--- bfd/targets.c	24 Mar 2005 21:02:19 -0000	1.124
+++ bfd/targets.c	12 Apr 2005 15:00:30 -0000
@@ -561,6 +561,7 @@ extern const bfd_target bfd_elf32_hppa_n
 extern const bfd_target bfd_elf32_hppa_vec;
 extern const bfd_target bfd_elf32_i370_vec;
 extern const bfd_target bfd_elf32_i386_freebsd_vec;
+extern const bfd_target bfd_elf32_i386_vxworks_vec;
 extern const bfd_target bfd_elf32_i386_vec;
 extern const bfd_target bfd_elf32_i860_little_vec;
 extern const bfd_target bfd_elf32_i860_vec;
@@ -860,6 +861,7 @@ static const bfd_target * const _bfd_tar
 	&bfd_elf32_hppa_vec,
 	&bfd_elf32_i370_vec,
 	&bfd_elf32_i386_freebsd_vec,
+	&bfd_elf32_i386_vxworks_vec,
 	&bfd_elf32_i386_vec,
 	&bfd_elf32_i860_little_vec,
 	&bfd_elf32_i860_vec,
Index: gas/config/tc-i386.h
===================================================================
RCS file: /var/cvsroot/src-cvs/src/gas/config/tc-i386.h,v
retrieving revision 1.52
diff -u -p -r1.52 tc-i386.h
--- gas/config/tc-i386.h	23 Nov 2004 07:55:11 -0000	1.52
+++ gas/config/tc-i386.h	12 Apr 2005 15:00:30 -0000
@@ -61,7 +61,10 @@ extern unsigned long i386_mach (void);
 
 #ifdef TE_FreeBSD
 #define ELF_TARGET_FORMAT	"elf32-i386-freebsd"
+#elif defined (TE_VXWORKS)
+#define ELF_TARGET_FORMAT	"elf32-i386-vxworks"
 #endif
+
 #ifndef ELF_TARGET_FORMAT
 #define ELF_TARGET_FORMAT	"elf32-i386"
 #endif
Index: gas/testsuite/gas/i386/i386.exp
===================================================================
RCS file: /var/cvsroot/src-cvs/src/gas/testsuite/gas/i386/i386.exp,v
retrieving revision 1.33
diff -u -p -r1.33 i386.exp
--- gas/testsuite/gas/i386/i386.exp	1 Apr 2005 07:50:24 -0000	1.33
+++ gas/testsuite/gas/i386/i386.exp	13 Apr 2005 16:54:31 -0000
@@ -65,7 +65,8 @@ if [expr ([istarget "i*86-*-*"] ||  [ist
 	&& (![is_elf_format] || [istarget "*-*-linux*"]
 	    || [istarget "*-*-netbsd*"]
 	    || [istarget "*-*-freebsd*"]
-	    || [istarget "*-*-netware*"])} {
+	    || [istarget "*-*-netware*"]
+	    || [istarget "*-*-vxworks*"])} {
 	# Don't run this test on targets where '/' starts comments.
 	run_dump_test "divide"
     }
Index: ld/Makefile.am
===================================================================
RCS file: /var/cvsroot/src-cvs/src/ld/Makefile.am,v
retrieving revision 1.171
diff -u -p -r1.171 Makefile.am
--- ld/Makefile.am	12 Apr 2005 02:50:28 -0000	1.171
+++ ld/Makefile.am	12 Apr 2005 15:00:30 -0000
@@ -190,6 +190,7 @@ ALL_EMULATIONS = \
 	eelf_i386_chaos.o \
 	eelf_i386_fbsd.o \
 	eelf_i386_ldso.o \
+	eelf_i386_vxworks.o \
 	eelf_s390.o \
 	egld960.o \
 	egld960coff.o \
@@ -871,6 +872,10 @@ eelf_i386_fbsd.c: $(srcdir)/emulparams/e
 eelf_i386_ldso.c: $(srcdir)/emulparams/elf_i386_ldso.sh \
   $(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
 	${GENSCRIPTS} elf_i386_ldso "$(tdir_elf_i386_ldso)"
+eelf_i386_vxworks.c: $(srcdir)/emulparams/elf_i386_vxworks.sh \
+  $(srcdir)/emulparams/vxworks.sh \
+  $(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
+	${GENSCRIPTS} elf_i386_vxworks "$(tdir_elf_i386_vxworks)"
 eelf_s390.c: $(srcdir)/emulparams/elf_s390.sh \
   $(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
 	${GENSCRIPTS} elf_s390 "$(tdir_elf_s390)"
Index: ld/configure.tgt
===================================================================
RCS file: /var/cvsroot/src-cvs/src/ld/configure.tgt,v
retrieving revision 1.167
diff -u -p -r1.167 configure.tgt
--- ld/configure.tgt	23 Mar 2005 15:35:50 -0000	1.167
+++ ld/configure.tgt	12 Apr 2005 15:00:30 -0000
@@ -237,7 +237,7 @@ i[3-7]86-*-interix*)	targ_emul=i386pe_po
  			targ_extra_ofiles="deffilep.o pe-dll.o" ;;
 i[3-7]86-*-beospe*)	targ_emul=i386beos ;;
 i[3-7]86-*-beos*)	targ_emul=elf_i386_be ;;
-i[3-7]86-*-vxworks*)	targ_emul=elf_i386 ;;
+i[3-7]86-*-vxworks*)	targ_emul=elf_i386_vxworks ;;
 i[3-7]86-*-chaos)	targ_emul=elf_i386_chaos ;;
 m8*-*-*)		targ_emul=m88kbcs ;;
 a29k-*-udi)		targ_emul=sa29200 ;;
Index: ld/emulparams/elf_i386_vxworks.sh
===================================================================
RCS file: ld/emulparams/elf_i386_vxworks.sh
diff -N ld/emulparams/elf_i386_vxworks.sh
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/emulparams/elf_i386_vxworks.sh	12 Apr 2005 15:00:30 -0000
@@ -0,0 +1,14 @@
+SCRIPT_NAME=elf
+OUTPUT_FORMAT="elf32-i386-vxworks"
+TEXT_START_ADDR=0x08048000
+MAXPAGESIZE=0x1000
+COMMONPAGESIZE=0x1000
+NONPAGED_TEXT_START_ADDR=0x08048000
+ARCH=i386
+MACHINE=
+NOP=0x90909090
+TEMPLATE_NAME=elf32
+GENERATE_SHLIB_SCRIPT=yes
+GENERATE_PIE_SCRIPT=yes
+NO_SMALL_DATA=yes
+. ${srcdir}/emulparams/vxworks.sh
Index: ld/emulparams/vxworks.sh
===================================================================
RCS file: ld/emulparams/vxworks.sh
diff -N ld/emulparams/vxworks.sh
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/emulparams/vxworks.sh	12 Apr 2005 15:00:30 -0000
@@ -0,0 +1,25 @@
+# If you change this file, please also look at files which source this one:
+# elf_i386_vxworks.sh elf32ppcvxworks.sh elf32ebmipvxworks.sh
+
+# The Diab tools use a different init/fini convention.  Initialization code
+# is place in sections named ".init$NN".  These sections are then concatenated
+# into the .init section.  It is important that .init$00 be first and .init$99
+# be last. The other sections should be sorted, but the current linker script
+# parse does not seem to allow that with the SORT keyword in this context.
+INIT_START='_init = .;
+            KEEP (*(.init$00));
+            KEEP (*(.init$0[1-9]));
+            KEEP (*(.init$[1-8][0-9]));
+            KEEP (*(.init$9[0-8]));'
+INIT_END='KEEP (*(.init$99));'
+FINI_START='_fini = .;
+            KEEP (*(.fini$00));
+            KEEP (*(.fini$0[1-9]));
+            KEEP (*(.fini$[1-8][0-9]));
+            KEEP (*(.fini$9[0-8]));'
+FINI_END='KEEP (*(.fini$99));
+          PROVIDE (_etext = .);'
+
+ETEXT_NAME=etext_unrelocated
+OTHER_END_SYMBOLS="PROVIDE (_ehdr = ${TEXT_START_ADDR});"
+DATA_END_SYMBOLS=".edata : { PROVIDE (_edata = .); }"
Index: ld/scripttempl/elf.sc
===================================================================
RCS file: /var/cvsroot/src-cvs/src/ld/scripttempl/elf.sc,v
retrieving revision 1.53
diff -u -p -r1.53 elf.sc
--- ld/scripttempl/elf.sc	23 Mar 2005 04:14:46 -0000	1.53
+++ ld/scripttempl/elf.sc	12 Apr 2005 15:00:30 -0000
@@ -25,6 +25,8 @@
 #		.text section.
 #	DATA_START_SYMBOLS - symbols that appear at the start of the
 #		.data section.
+#	DATA_END_SYMBOLS - symbols that appear at the end of the
+#		writeable data sections.
 #	OTHER_GOT_SYMBOLS - symbols defined just before .got.
 #	OTHER_GOT_SECTIONS - sections just after .got.
 #	OTHER_SDATA_SECTIONS - sections just after .sdata.
@@ -45,6 +47,8 @@
 # 	combination of .fini sections.
 #	STACK_ADDR - start of a .stack section.
 #	OTHER_END_SYMBOLS - symbols to place right at the end of the script.
+#	ETEXT_NAME - name of a symbol for the end of the text section,
+#		normally etext.
 #	SEPARATE_GOTPLT - if set, .got.plt should be separate output section,
 #		so that .got can be in the RELRO area.  It should be set to
 #		the number of bytes in the beginning of .got.plt which can be
@@ -84,6 +88,7 @@ if [ -z "$MACHINE" ]; then OUTPUT_ARCH=$
 test -z "${ELFSIZE}" && ELFSIZE=32
 test -z "${ALIGNMENT}" && ALIGNMENT="${ELFSIZE} / 8"
 test "$LD_FLAG" = "N" && DATA_ADDR=.
+test -z "${ETEXT_NAME}" && ETEXT_NAME=etext
 test -n "$CREATE_SHLIB$CREATE_PIE" && test -n "$SHLIB_DATA_ADDR" && COMMONPAGESIZE=""
 test -z "$CREATE_SHLIB$CREATE_PIE" && test -n "$DATA_ADDR" && COMMONPAGESIZE=""
 test -n "$RELRO_NOW" && unset SEPARATE_GOTPLT
@@ -307,9 +312,9 @@ cat <<EOF
     KEEP (*(.fini))
     ${RELOCATING+${FINI_END}}
   } =${NOP-0}
-  ${RELOCATING+PROVIDE (__etext = .);}
-  ${RELOCATING+PROVIDE (_etext = .);}
-  ${RELOCATING+PROVIDE (etext = .);}
+  ${RELOCATING+PROVIDE (__${ETEXT_NAME} = .);}
+  ${RELOCATING+PROVIDE (_${ETEXT_NAME} = .);}
+  ${RELOCATING+PROVIDE (${ETEXT_NAME} = .);}
   ${WRITABLE_RODATA-${RODATA}}
   .rodata1      ${RELOCATING-0} : { *(.rodata1) }
   ${CREATE_SHLIB-${SDATA2}}
@@ -370,8 +375,7 @@ cat <<EOF
   ${OTHER_GOT_SECTIONS}
   ${SDATA}
   ${OTHER_SDATA_SECTIONS}
-  ${RELOCATING+_edata = .;}
-  ${RELOCATING+PROVIDE (edata = .);}
+  ${RELOCATING+${DATA_END_SYMBOLS-_edata = .; PROVIDE (edata = .);}}
   ${RELOCATING+__bss_start = .;}
   ${RELOCATING+${OTHER_BSS_SYMBOLS}}
   ${SBSS}

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [patch] VxWorks x86 shared library support.
  2005-04-14 13:58 [patch] VxWorks x86 shared library support Paul Brook
@ 2005-04-15  7:09 ` Alan Modra
  2005-04-15 12:19   ` Daniel Jacobowitz
  0 siblings, 1 reply; 4+ messages in thread
From: Alan Modra @ 2005-04-15  7:09 UTC (permalink / raw)
  To: Paul Brook; +Cc: binutils

I don't like any of your hacks to the generic ELF linker code.  With a
little thought, you should be able to eliminate most of them.

On Thu, Apr 14, 2005 at 02:58:25PM +0100, Paul Brook wrote:
> 	* elf-bfd.h (struct elf_backend_data): Add is_vxworks.
> 	(RELOC_FOR_GLOBAL_SYMBOL): Ignore VxWorks magic GOT symbols.

No way is this RELOC_FOR_GLOBAL_SYMBOL hack acceptable.  Instead, do
something about giving these magic symbols a value.  See, for example,
elf32_hppa_set_gp.

> 	* elf.c (assign_section_numbers): Add special handling for VxWorks
> 	.plt.unloaded section.

Well, maybe this is OK.

> 	* elflink.c (_bfd_elf_create_dynamic_sections): Mark VxWorks PLT
> 	symbols as functions.

Do this in backend code, by looking up the sym and changing its type.

> 	(elf_link_adjust_relocs): Convert SHN_UNDEF relocs for PLT stubs
> 	into section relative relocs.

Yikes!  You say

+         /* This is a relocation from an executable or shared library
+            against a symbol in a different shared library.  We are
+            createing a definition in the output file but it does not come
+            from any of out normal (.o) files. ie. a PLT stub.

So this is presumably a linker created reloc.  Why can't you create it
such that it doesn't need this horrible hack?

> 	(elf_link_output_extsym): Ignore undefined VxWorks GOTT symbols.

This shouldn't be needed if you give these syms a value.

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [patch] VxWorks x86 shared library support.
  2005-04-15  7:09 ` Alan Modra
@ 2005-04-15 12:19   ` Daniel Jacobowitz
  2005-04-15 22:20     ` Alan Modra
  0 siblings, 1 reply; 4+ messages in thread
From: Daniel Jacobowitz @ 2005-04-15 12:19 UTC (permalink / raw)
  To: Paul Brook, binutils

On Fri, Apr 15, 2005 at 04:39:21PM +0930, Alan Modra wrote:
> I don't like any of your hacks to the generic ELF linker code.  With a
> little thought, you should be able to eliminate most of them.

FWIW, I'll take blame for most of the gross common ELF bits.  They're
much prettier when Paul posted them than when I got through with them,
though.

> On Thu, Apr 14, 2005 at 02:58:25PM +0100, Paul Brook wrote:
> > 	* elf-bfd.h (struct elf_backend_data): Add is_vxworks.
> > 	(RELOC_FOR_GLOBAL_SYMBOL): Ignore VxWorks magic GOT symbols.
> 
> No way is this RELOC_FOR_GLOBAL_SYMBOL hack acceptable.  Instead, do
> something about giving these magic symbols a value.  See, for example,
> elf32_hppa_set_gp.

Won't this cause the symbols to be output as defined?  The loader
requires them to be undefined.

> > 	(elf_link_adjust_relocs): Convert SHN_UNDEF relocs for PLT stubs
> > 	into section relative relocs.
> 
> Yikes!  You say
> 
> +         /* This is a relocation from an executable or shared library
> +            against a symbol in a different shared library.  We are
> +            createing a definition in the output file but it does not come
> +            from any of out normal (.o) files. ie. a PLT stub.
> 
> So this is presumably a linker created reloc.  Why can't you create it
> such that it doesn't need this horrible hack?

No, it isn't linker created.  VxWorks executables are kind of odd; they
are linked using --emit-relocs, and both the dynamic and non-dynamic
relocations are required for proper loading.  What this bit is doing is
fixing up relocations from an input file that would otherwise be copied
straight to the output file.  They're reloaded from the input file
here, so this is the only place the linker has an opportunity to frob
them.

I suppose it could be a backend hook and defined by the various VxWorks
backends...

-- 
Daniel Jacobowitz
CodeSourcery, LLC

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [patch] VxWorks x86 shared library support.
  2005-04-15 12:19   ` Daniel Jacobowitz
@ 2005-04-15 22:20     ` Alan Modra
  0 siblings, 0 replies; 4+ messages in thread
From: Alan Modra @ 2005-04-15 22:20 UTC (permalink / raw)
  To: Paul Brook, binutils

On Fri, Apr 15, 2005 at 08:19:11AM -0400, Daniel Jacobowitz wrote:
> On Fri, Apr 15, 2005 at 04:39:21PM +0930, Alan Modra wrote:
> > No way is this RELOC_FOR_GLOBAL_SYMBOL hack acceptable.  Instead, do
> > something about giving these magic symbols a value.  See, for example,
> > elf32_hppa_set_gp.
> 
> Won't this cause the symbols to be output as defined?  The loader
> requires them to be undefined.

Yes, it would output them as defined if you did it the same place as
elf32_hppa_set_gp.  I didn't realize you wanted them undefined.  I
suppose you could put a hack in elf_backend_output_arch_syms to define
the sym for use by relocate_section.

> > > 	(elf_link_adjust_relocs): Convert SHN_UNDEF relocs for PLT stubs
> > > 	into section relative relocs.
> > 
> > Yikes!  You say
> > 
> > +         /* This is a relocation from an executable or shared library
> > +            against a symbol in a different shared library.  We are
> > +            createing a definition in the output file but it does not come
> > +            from any of out normal (.o) files. ie. a PLT stub.
> > 
> > So this is presumably a linker created reloc.  Why can't you create it
> > such that it doesn't need this horrible hack?
> 
> No, it isn't linker created.  VxWorks executables are kind of odd; they
> are linked using --emit-relocs, and both the dynamic and non-dynamic
> relocations are required for proper loading.  What this bit is doing is
> fixing up relocations from an input file that would otherwise be copied
> straight to the output file.  They're reloaded from the input file
> here, so this is the only place the linker has an opportunity to frob
> them.

No, they are loaded from memory, where they have been written by
_bfd_elf_link_output_relocs, or elf_backend_emit_relocs.  Please look at
putting any reloc twiddles into a backend_emit_relocs functions.

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2005-04-15 22:20 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-04-14 13:58 [patch] VxWorks x86 shared library support Paul Brook
2005-04-15  7:09 ` Alan Modra
2005-04-15 12:19   ` Daniel Jacobowitz
2005-04-15 22:20     ` Alan Modra

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).