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]

Re: Support for SPARC STT_REGISTER


(Updated patch attached below).

> What is the section of such a symbol?

ABI says:

st_name: Index into the string table of the name of the symbol, if 0, it is
a register used for scratch. st_name 0 implies STB_GLOBAL.
st_value: Register number (2, 3, 6, 7).
st_size = st_other = 0
st_info = ELF64_ST_INFO(bind, STT_REGISTER) where bind is usually
STB_GLOBAL, but can be STB_WEAK or STB_LOCAL.
st_shndx: SHN_ABS if this object initializes this register symbol (currently
unsupported in Solaris as as far as I can examine) or SHN_UNDEF otherwise.

Here is elfdump output how it looks like under Solaris:
ccc:~# elfdump t.so.1 # Shared library

ELF Header
  ei_magic:   { 0x7f, E, L, F }
  ei_class:   ELFCLASS64          ei_data:      ELFDATA2MSB
  e_machine:  EM_SPARCV9          e_version:    EV_CURRENT
  e_type:     ET_DYN
  e_flags:    [ EF_SPARCV9_TSO  EF_SPARC_SUN_US1 ]
  e_entry:                 0x3c4  e_ehsize:     64  e_shstrndx:   10
  e_shoff:                 0x780  e_shentsize:  64  e_shnum:      11
  e_phoff:                  0x40  e_phentsize:  56  e_phnum:       3
...
Symbol Table:  .dynsym
     index        value           size     type bind oth shndx       name
       [0]  0x000000000000 0x000000000000  NOTY LOCL 0   UNDEF
...
      [10]  0x000000000000 0x000000000000  SECT LOCL 0   .shstrtab
      [11]  REG_G3         0x000000000000  REGI GLOB 0   UNDEF
      [12]  0x000000100470 0x000000000000  OBJT GLOB 0   .bss        _end
      [13]  0x0000001003d0 0x000000000000  OBJT GLOB 0   .dynamic    _DYNAMIC
      [14]  REG_G2         0x000000000000  REGI GLOB 0   UNDEF       addrb
      [15]  0x000000100470 0x000000000000  OBJT GLOB 0   .dynamic    _edata
...
Symbol Table:  .symtab
     index        value           size     type bind oth shndx       name
       [0]  0x000000000000 0x000000000000  NOTY LOCL 0   UNDEF
       [1]  0x000000000000 0x000000000000  FILE LOCL 0   ABS         t.so.1
...
      [14]  0x0000000003c0 0x000000000000  NOTY LOCL 0   .text       addr
      [15]  REG_G3         0x000000000000  REGI GLOB 0   UNDEF
      [16]  0x000000100470 0x000000000000  OBJT GLOB 0   .bss        _end
      [17]  0x0000001003d0 0x000000000000  OBJT GLOB 0   .dynamic    _DYNAMIC
      [18]  REG_G2         0x000000000000  REGI GLOB 0   UNDEF       addrb
      [19]  0x000000100470 0x000000000000  OBJT GLOB 0   .dynamic    _edata
...
Dynamic Section:  .dynamic
     index  tag           value
       [1]  HASH          0xe8
       [2]  STRTAB        0x338
       [3]  STRSZ         0x85
       [4]  SYMTAB        0x170
       [5]  SYMENT        0x18
       [6]  FEATURE_1     0x1               [ PARINIT ]
       [7]  REGISTER      0xe
       [8]  REGISTER      0xb

ccc:~# elfdump t.o # Object file

ELF Header
  ei_magic:   { 0x7f, E, L, F }
  ei_class:   ELFCLASS64          ei_data:      ELFDATA2MSB
  e_machine:  EM_SPARCV9          e_version:    EV_CURRENT
  e_type:     ET_REL
  e_flags:    [ EF_SPARCV9_TSO  EF_SPARC_SUN_US1 ]
  e_entry:                     0  e_ehsize:     64  e_shstrndx:    1
  e_shoff:                  0xc0  e_shentsize:  64  e_shnum:       5
  e_phoff:                     0  e_phentsize:   0  e_phnum:       0
...
Symbol Table:  .symtab
     index        value           size     type bind oth shndx       name
       [0]  0x000000000000 0x000000000000  NOTY LOCL 0   UNDEF
       [1]  0x000000000000 0x000000000000  SECT LOCL 0   .text
       [2]  REG_G2         0x000000000000  REGI GLOB 0   UNDEF       address

> 
> You have added code to handle them specially in the linker hash table.
> I don't think this is necessary.  This is a case of linking symbols
> with special semantics.  You don't need to remove those symbols
> entirely from the linking process; you just need to implement special
> semantics for them.  We already have a hook for that:
> elf_add_symbol_hook.  It can implement the special semantics for
> STT_REGISTER symbols, and then adjust its arguments to invoke some
> appropriately harmless set of standard semantics.

That's what I spoke about in the comment above the patch. I'd like to keep
it in the linker hash table, but hash table does not allow me to insert more
symbols with the same name, which I need in this case, because one can e.g.
declare
	.register %g2, #scratch
	.register %g3, #scratch
which means you'll have two symbols with empty name (which differ only by
st_value in the final output). I already use elf_add_symbol_hook in my
patch. I have to keep those symbols in my local structure anyway (because I
need to look up a STT_REGISTER symbol with a particular st_value, not name,
for the linking), so it was fairly easy to flush all those symbols out from
that table eventhough they don't live in the hash table. But if you allow
e.g. some function to insert a symbol into the hash table eventhough the
name is in there already, then they can live in the hash.
But it would probably need some hooks in output_extsym (especially because
of the SHN_UNDEF and STB_GLOBAL at the same time), so keeping it out of the
like it is done in many backends for some .dynsym entries seems cleaner to
me.

>    --- ./bfd/bfd-in2.h.jj	Tue Jun 29 10:46:31 1999
>    +++ ./bfd/bfd-in2.h	Wed Jun 30 12:37:16 1999
>    @@ -2312,6 +2312,9 @@ typedef struct symbol_cache_entry
>    +	/* Processor specific symbol type.  */
>    +#define BSF_PROC	  0x20000
>    +
> 
> I don't care for this.  Changes to the generic ABI should ideally have
> a generic meaning.  This does not.  I also don't see why it is
> necessary to change the generic ABI in this manner, given the
> existence of elf_symbol_type.

Ok, I got rid of this. The new patch attached below.
It already creates the correct .dynsym entries and DT_SPARC_REGISTER
.dynamic entries pointing to it as ABI requires.

> 
> These patches seem to have a bunch of code that don't seem to have
> anything to do with STT_REGISTER.  Could you please submit that part
> of them separately, so that we can get them in without getting tangled
> up with extraneous issues?  Thanks.

I have submitted that hunk two days ago in the OLO10 patch.

Anyway, here is the new patch, which I hope works as the ABI requires, at
least to the extent I have tested so far.
BTW: The change of DT_SPARC_REGISTER from 0x70000001 to 0x7000001 is not a
typo on my part, I suppose Sparc International made a typo in SYSV sparc64
ABI supplement but it got implemented like that into Solaris 7 linker :(, so
I guess we have to keep it compatible. It is outside of any processor
specific range, unfortunately.

1999-07-07  Jakub Jelinek  <jj@ultra.linux.cz>

	* bfd/elf-bfd.h (struct elf_backend_data): Add
	print_symbol_all and output_arch_syms backend methods.
	* bfd/elfxx-target.h: Likewise.
	* bfd/elf64-sparc.c (sparc64_elf_bfd_link_hash_table_create,
	sparc64_elf_add_symbol_hook, sparc64_elf_output_arch_syms,
	sparc64_elf_get_symbol_type, sparc64_elf_symbol_processing): New
	functions.
	(sparc64_elf_size_dynamic_sections): Leave space for STT_REGISTER
	symbols in .dynsym, add their names into .dynstr. Use generic
	_bfd_elf_link_adjust_dynindx instead of sparc64_elf_adjust_dynindx).
	(sparc64_elf_adjust_dynindx): Remove.
	(sparc64_elf_finish_dynamic_sections): Output STT_REGISTER symbols
	into .dynsym, fix up DT_SPARC_REGISTER pointers to them.
	(sparc64_elf_print_symbol_all): New function.
	* bfd/elf.c (bfd_elf_print_symbol): Allow special backend symbol
	printing using the print_symbol_all hook.
	* bfd/elflink.h (elf_bfd_final_link): Allow backend to emit some
	global symbols which don't live in the symbol hash table.
	* binutils/readelf.c (get_dynamic_type): Handle sparc
	DT_SPARC_REGISTER printing.
	* gas/config/tc-sparc.c (md_longopts): Add --no-undeclared-regs
	option.
	(sparc_ip): Warn if %g2 or %g3 register is used and not covered
	by .register pseudo-op if -64 and --no-undeclared-regs.
	(s_register, sparc_adjust_symtab): New functions.
	* gas/config/tc-sparc.h (tc_adjust_symtab, sparc_adjust_symtab):
	Declare sparc_adjust_symtab as tc_adjust_symtab.
	* gas/doc/c-sparc.texi: Document .register and .nword pseudo-ops.
	* include/elf/sparc.h: "Fix" DT_SPARC_REGISTER to match ABI and
	Solaris linker.

--- ./bfd/elf-bfd.h.jj4	Tue Jun 29 10:46:50 1999
+++ ./bfd/elf-bfd.h	Wed Jul  7 10:21:41 1999
@@ -517,6 +517,21 @@ struct elf_backend_data
   void (*elf_backend_post_process_headers)
     PARAMS ((bfd *, struct bfd_link_info *));
 
+  /* This function, if defined, prints a symbol to file and returns the
+     name of the symbol to be printed.  It should return NULL to fall
+     back to default symbol printing.  */
+  const char *(*elf_backend_print_symbol_all)
+    PARAMS ((bfd *, PTR, asymbol *));
+
+  /* This function, if defined, is called after all local symbols and
+     global symbols converted to locals are emited into the symtab
+     section.  It allows the backend to emit special global symbols
+     not handled in the hash table.  */
+  boolean (*elf_backend_output_arch_syms)
+    PARAMS ((struct bfd_link_info *, PTR,
+	    boolean (*) PARAMS ((PTR, const char *,
+             Elf_Internal_Sym *, asection *))));
+
   /* The swapping table to use when dealing with ECOFF information.
      Used for the MIPS ELF .mdebug section.  */
   const struct ecoff_debug_swap *elf_backend_ecoff_debug_swap;
--- ./bfd/elf64-sparc.c.jj4	Tue Jul  6 16:59:00 1999
+++ ./bfd/elf64-sparc.c	Wed Jul  7 13:59:33 1999
@@ -32,6 +32,8 @@ Foundation, Inc., 59 Temple Place - Suit
 /* In case we're on a 32-bit machine, construct a 64-bit "-1" value.  */
 #define MINUS_ONE (~ (bfd_vma) 0)
 
+static struct bfd_link_hash_table * sparc64_elf_bfd_link_hash_table_create
+  PARAMS((bfd *));
 static reloc_howto_type *sparc64_elf_reloc_type_lookup
   PARAMS ((bfd *, bfd_reloc_code_real_type));
 static void sparc64_elf_info_to_howto
@@ -51,8 +53,13 @@ static boolean sparc64_elf_adjust_dynami
   PARAMS((struct bfd_link_info *, struct elf_link_hash_entry *));
 static boolean sparc64_elf_size_dynamic_sections
   PARAMS((bfd *, struct bfd_link_info *));
-static boolean sparc64_elf_adjust_dynindx
-  PARAMS((struct elf_link_hash_entry *, PTR));
+static int sparc64_elf_get_symbol_type
+  PARAMS (( Elf_Internal_Sym *, int));
+static boolean sparc64_elf_add_symbol_hook
+  PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Sym *,
+	  const char **, flagword *, asection **, bfd_vma *));
+static void sparc64_elf_symbol_processing
+  PARAMS ((bfd *, asymbol *));
 
 static boolean sparc64_elf_merge_private_bfd_data
   PARAMS ((bfd *, bfd *));
@@ -598,6 +605,54 @@ sparc64_elf_write_relocs (abfd, sec, dat
     }
 }
 
+/* Sparc64 ELF linker hash table.  */
+
+struct sparc64_elf_app_reg
+{
+  unsigned char bind;
+  unsigned short shndx;
+  bfd_size_type dynstr_index;
+  bfd *abfd;
+  char *name;
+};
+
+struct sparc64_elf_link_hash_table
+{
+  struct elf_link_hash_table root;
+
+  struct sparc64_elf_app_reg app_regs [4];
+  int dynindx_reg_base;
+};
+
+/* Get the Sparc64 ELF linker hash table from a link_info structure.  */
+
+#define sparc64_elf_hash_table(p) \
+  ((struct sparc64_elf_link_hash_table *) ((p)->hash))
+  
+/* Create a Sparc64 ELF linker hash table.  */
+
+static struct bfd_link_hash_table *
+sparc64_elf_bfd_link_hash_table_create (abfd)
+     bfd *abfd;
+{
+  struct sparc64_elf_link_hash_table *ret;
+
+  ret = ((struct sparc64_elf_link_hash_table *)
+	 bfd_zalloc (abfd, sizeof (struct sparc64_elf_link_hash_table)));
+  if (ret == (struct sparc64_elf_link_hash_table *) NULL)
+    return NULL;
+
+  if (! _bfd_elf_link_hash_table_init (&ret->root, abfd,
+				       _bfd_elf_link_hash_newfunc))
+    {
+      bfd_release (abfd, ret);
+      return NULL;
+    }
+
+  return &ret->root.root;
+}
+
+
 /* Utility for performing the standard initial work of an instruction
    relocation.
    *PRELOCATION will contain the relocated item.
@@ -1198,6 +1253,202 @@ sparc64_elf_check_relocs (abfd, info, se
   return true;
 }
 
+/* Hook called by the linker routine which adds symbols from an object
+   file.  We use it for STT_REGISTER symbols.  */
+
+static boolean
+sparc64_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
+     bfd *abfd;
+     struct bfd_link_info *info;
+     const Elf_Internal_Sym *sym;
+     const char **namep;
+     flagword *flagsp;
+     asection **secp;
+     bfd_vma *valp;
+{
+  static char *stt_types[] = { "NOTYPE", "OBJECT", "FUNCTION" };
+
+  if (ELF_ST_TYPE (sym->st_info) == STT_REGISTER)
+    {
+      int reg;
+      struct sparc64_elf_app_reg *p;
+      
+      reg = (int)sym->st_value;
+      switch (reg & ~1)
+	{
+	case 2: reg -= 2; break;
+	case 6: reg -= 4; break;
+	default:
+          (*_bfd_error_handler)
+            (_("%s: Only registers %%g[2367] can be declared using STT_REGISTER"),
+             bfd_get_filename (abfd));
+	  return false;
+	}
+
+      if (info->hash->creator != abfd->xvec
+	  || (abfd->flags & DYNAMIC) != 0)
+        {
+	  /* STT_REGISTER only works when linking an elf64_sparc object.
+	     If STT_REGISTER comes from a dynamic object, don't put it into
+	     the output bfd.  The dynamic linker will recheck it.  */
+	  *namep = NULL;
+	  return true;
+        }
+
+      p = sparc64_elf_hash_table(info)->app_regs + reg;
+
+      if (p->name != NULL && strcmp (p->name, *namep))
+	{
+          (*_bfd_error_handler)
+            (_("Register %%g%d used incompatibly: "
+               "previously declared in %s to %s, in %s redefined to %s"),
+             (int)sym->st_value,
+             bfd_get_filename (p->abfd), *p->name ? p->name : "#scratch",
+             bfd_get_filename (abfd), **namep ? *namep : "#scratch");
+	  return false;
+	}
+
+      if (p->name == NULL)
+	{
+	  if (**namep)
+	    {
+	      struct elf_link_hash_entry *h;
+	      
+	      h = (struct elf_link_hash_entry *)
+		bfd_link_hash_lookup (info->hash, *namep, false, false, false);
+
+	      if (h != NULL)
+		{
+		  unsigned char type = h->type;
+
+		  if (type > STT_FUNC) type = 0;
+		  (*_bfd_error_handler)
+		    (_("Symbol `%s' has differing types: "
+		       "previously %s, REGISTER in %s"),
+		     *namep, stt_types [type], bfd_get_filename (abfd));
+		  return false;
+		}
+
+	      p->name = bfd_hash_allocate (&info->hash->table,
+					   strlen (*namep) + 1);
+	      if (!p->name)
+		return false;
+
+	      strcpy (p->name, *namep);
+	    }
+	  else
+	    p->name = "";
+	  p->bind = ELF_ST_BIND (sym->st_info);
+	  p->abfd = abfd;
+	  p->shndx = sym->st_shndx;
+	}
+      else
+	{
+	  if (p->bind == STB_WEAK
+	      && ELF_ST_BIND (sym->st_info) == STB_GLOBAL)
+	    {
+	      p->bind = STB_GLOBAL;
+	      p->abfd = abfd;
+	    }
+	}
+      *namep = NULL;
+      return true;
+    }
+  else if (! *namep || ! **namep)
+    return true;
+  else
+    {
+      int i;
+      struct sparc64_elf_app_reg *p;
+
+      p = sparc64_elf_hash_table(info)->app_regs;
+      for (i = 0; i < 4; i++, p++)
+	if (p->name != NULL && ! strcmp (p->name, *namep))
+	  {
+	    unsigned char type = ELF_ST_TYPE (sym->st_info);
+
+	    if (type > STT_FUNC) type = 0;
+	    (*_bfd_error_handler)
+	      (_("Symbol `%s' has differing types: "
+		 "REGISTER in %s, %s in %s"),
+	       *namep, bfd_get_filename (p->abfd), stt_types [type],
+	       bfd_get_filename (abfd));
+	    return false;
+	  }
+    }
+  return true;
+}
+
+/* This function takes care of emmiting STT_REGISTER symbols
+   which we cannot easily keep in the symbol hash table.  */
+
+static boolean
+sparc64_elf_output_arch_syms (info, finfo, func)
+     struct bfd_link_info *info;
+     PTR finfo;
+     boolean (*func) PARAMS ((PTR, const char *,
+			      Elf_Internal_Sym *, asection *));
+{
+  int reg;
+  struct sparc64_elf_app_reg *app_regs =
+    sparc64_elf_hash_table(info)->app_regs;
+  Elf_Internal_Sym sym;
+
+  if (info->strip == strip_all)
+    return true;
+
+  for (reg = 0; reg < 4; reg++)
+    if (app_regs [reg].name != NULL)
+      {
+	if (info->strip == strip_some
+	    && bfd_hash_lookup (info->keep_hash,
+				app_regs [reg].name,
+				false, false) == NULL)
+	  continue;
+
+	sym.st_value = reg < 2 ? reg + 2 : reg + 4;
+	sym.st_size = 0;
+	sym.st_other = 0;
+	sym.st_info = ELF_ST_INFO (app_regs [reg].bind, STT_REGISTER);
+	sym.st_shndx = app_regs [reg].shndx;
+	if (! (*func) (finfo, app_regs [reg].name, &sym,
+		       sym.st_shndx == SHN_ABS
+			 ? bfd_abs_section_ptr : bfd_und_section_ptr))
+	  return false;
+      }
+
+  return true;
+}
+
+static int
+sparc64_elf_get_symbol_type (elf_sym, type)
+     Elf_Internal_Sym * elf_sym;
+     int type;
+{
+  if (ELF_ST_TYPE (elf_sym->st_info) == STT_REGISTER)
+    return STT_REGISTER;
+  else
+    return type;
+}
+
+/* A STB_GLOBAL,STT_REGISTER symbol should be BSF_GLOBAL
+   even in SHN_UNDEF section.  */
+
+static void
+sparc64_elf_symbol_processing (abfd, asym)
+     bfd *abfd;
+     asymbol *asym;
+{
+  elf_symbol_type *elfsym;
+
+  elfsym = (elf_symbol_type *) asym;
+  if (elfsym->internal_elf_sym.st_info
+      == ELF_ST_INFO (STB_GLOBAL, STT_REGISTER))
+    {
+      asym->flags |= BSF_GLOBAL;
+    }
+}
+
 /* Adjust a symbol defined by a dynamic object and referenced by a
    regular object.  The current definition is in some section of the
    dynamic object, but we're not including those sections.  We have to
@@ -1497,6 +1748,9 @@ sparc64_elf_size_dynamic_sections (outpu
 	 must add the entries now so that we get the correct size for
 	 the .dynamic section.  The DT_DEBUG entry is filled in by the
 	 dynamic linker and used by the debugger.  */
+      int i, c;
+      struct sparc64_elf_app_reg * app_regs;
+
       if (! info->shared)
 	{
 	  if (! bfd_elf64_add_dynamic_entry (info, DT_DEBUG, 0))
@@ -1525,6 +1779,44 @@ sparc64_elf_size_dynamic_sections (outpu
 	  if (! bfd_elf64_add_dynamic_entry (info, DT_TEXTREL, 0))
 	    return false;
 	}
+
+      /* Add dynamic STT_REGISTER symbols and corresponding DT_SPARC_REGISTER
+	 entries if needed.  */
+      app_regs = sparc64_elf_hash_table (info)->app_regs;
+      c = 0;
+      for (i = 0; i < 4; i++)
+	if (app_regs [i].name != NULL)
+	  {
+	    if (! bfd_elf64_add_dynamic_entry (info, DT_SPARC_REGISTER, 0))
+	      return false;
+	    c++;
+	  }
+
+      if (c)
+	{
+	  struct bfd_strtab_hash *dynstr;
+
+	  dynstr = elf_hash_table (info)->dynstr;
+	  BFD_ASSERT (dynstr != NULL);
+
+	  elf_link_hash_traverse (elf_hash_table (info),
+				  _bfd_elf_link_adjust_dynindx,
+				  (PTR) &c);
+	  elf_hash_table (info)->dynsymcount += c;
+
+	  for (i = 0; i < 4; i++)
+	    if (app_regs [i].name != NULL
+		&& *app_regs [i].name != '\0')
+	      {
+		app_regs [i].dynstr_index =
+		  _bfd_stringtab_add (dynstr, app_regs [i].name, true, false);
+		if (app_regs [i].dynstr_index == (bfd_size_type) -1)
+		  return false;
+	      }
+
+	  /* The first symbol in .dynsym is a dummy.  */
+	  sparc64_elf_hash_table (info)->dynindx_reg_base = 1;
+	}
     }
 
   /* If we are generating a shared library, we generate a section
@@ -1552,29 +1844,15 @@ sparc64_elf_size_dynamic_sections (outpu
 	}
 
       elf_link_hash_traverse (elf_hash_table (info),
-			      sparc64_elf_adjust_dynindx,
+			      _bfd_elf_link_adjust_dynindx,
 			      (PTR) &c);
       elf_hash_table (info)->dynsymcount += c;
+      sparc64_elf_hash_table (info)->dynindx_reg_base += c;
     }
 
   return true;
 }
 
-/* Increment the index of a dynamic symbol by a given amount.  Called
-   via elf_link_hash_traverse.  */
-
-static boolean
-sparc64_elf_adjust_dynindx (h, cparg)
-     struct elf_link_hash_entry *h;
-     PTR cparg;
-{
-  int *cp = (int *) cparg;
-
-  if (h->dynindx != -1)
-    h->dynindx += *cp;
-  return true;
-}
-
 
 /* Relocate a SPARC64 ELF section.  */
 
@@ -2398,6 +2676,7 @@ sparc64_elf_finish_dynamic_sections (out
   bfd *dynobj;
   asection *sdyn;
   asection *sgot;
+  Elf64_External_Dyn *dt_register_dyn = NULL;
 
   dynobj = elf_hash_table (info)->dynobj;
 
@@ -2426,6 +2705,10 @@ sparc64_elf_finish_dynamic_sections (out
 	    case DT_PLTGOT:   name = ".plt"; size = false; break;
 	    case DT_PLTRELSZ: name = ".rela.plt"; size = true; break;
 	    case DT_JMPREL:   name = ".rela.plt"; size = false; break;
+	    case DT_SPARC_REGISTER:
+			      if (dt_register_dyn == NULL)
+				dt_register_dyn = dyncon;
+			      /* fallthrough */
 	    default:	      name = NULL; size = false; break;
 	    }
 
@@ -2523,6 +2806,53 @@ sparc64_elf_finish_dynamic_sections (out
       elf_section_data (sdynsym->output_section)->this_hdr.sh_info = c + 1;
     }
 
+  if (elf_hash_table (info)->dynamic_sections_created)
+    {
+      int reg;
+      struct sparc64_elf_app_reg *app_regs =
+	sparc64_elf_hash_table(info)->app_regs;
+      asection *sdynsym;
+      Elf_Internal_Sym sym;
+      Elf_Internal_Dyn dyn;
+      int c = sparc64_elf_hash_table (info)->dynindx_reg_base;
+
+      /* Set up the STT_REGISTER dynamic symbols.  */
+
+      sdynsym = bfd_get_section_by_name (dynobj, ".dynsym");
+      BFD_ASSERT (sdynsym != NULL);
+
+      sym.st_size = 0;
+      sym.st_other = 0;
+
+      for (reg = 0; reg < 4; reg++)
+	if (app_regs [reg].name != NULL)
+	  {
+	    sym.st_value = reg < 2 ? reg + 2 : reg + 4;
+	    sym.st_size = 0;
+	    sym.st_name = app_regs [reg].dynstr_index;
+	    sym.st_other = 0;
+	    sym.st_info = ELF_ST_INFO (app_regs [reg].bind, STT_REGISTER);
+	    sym.st_shndx = app_regs [reg].shndx;
+	    bfd_elf64_swap_symbol_out (output_bfd, &sym,
+				       (PTR) (((Elf64_External_Sym *)
+					       sdynsym->contents)
+					      + c));
+	    if (dt_register_dyn == NULL)
+	      return false;
+
+	    bfd_elf64_swap_dyn_in (dynobj, dt_register_dyn, &dyn);
+
+	    if (dyn.d_tag != DT_SPARC_REGISTER)
+	      return false;
+	    
+	    dyn.d_un.d_val = c;
+	    bfd_elf64_swap_dyn_out (output_bfd, &dyn, dt_register_dyn);
+
+	    ++dt_register_dyn;
+	    ++c;
+	  }
+    }
+
   return true;
 }
 
@@ -2599,7 +2929,34 @@ sparc64_elf_merge_private_bfd_data (ibfd
     }
   return true;
 }
+
+/* Print a STT_REGISTER symbol to file FILE.  */
 
+static const char *
+sparc64_elf_print_symbol_all (abfd, filep, symbol)
+     bfd *abfd;
+     PTR filep;
+     asymbol *symbol;
+{
+  FILE *file = (FILE *) filep;
+  int reg, type;
+  
+  if (ELF_ST_TYPE (((elf_symbol_type *) symbol)->internal_elf_sym.st_info)
+      != STT_REGISTER)
+    return NULL;
+
+  reg = ((elf_symbol_type *) symbol)->internal_elf_sym.st_value;
+  type = symbol->flags;
+  fprintf (file, "REG_%c%c%11s%c%c    R", "GOLI" [reg / 8], '0' + (reg & 7), "",
+		 ((type & BSF_LOCAL)
+		  ? (type & BSF_GLOBAL) ? '!' : 'l'
+  	          : (type & BSF_GLOBAL) ? 'g' : ' '),
+  	         (type & BSF_WEAK) ? 'w' : ' ');
+  if (symbol->name == NULL || symbol->name [0] == '\0')
+    return "#scratch";
+  else
+    return symbol->name;
+}
 
 /* Set the right machine number for a SPARC64 ELF file.  */
 
@@ -2653,6 +3010,9 @@ const struct elf_size_info sparc64_elf_s
 /* This is the value that we used before the ABI was released.  */
 #define ELF_MACHINE_ALT1 EM_OLD_SPARCV9
 
+#define bfd_elf64_bfd_link_hash_table_create \
+  sparc64_elf_bfd_link_hash_table_create
+  
 #define elf_info_to_howto \
   sparc64_elf_info_to_howto
 #define bfd_elf64_get_reloc_upper_bound \
@@ -2666,6 +3026,12 @@ const struct elf_size_info sparc64_elf_s
 
 #define elf_backend_create_dynamic_sections \
   _bfd_elf_create_dynamic_sections
+#define elf_backend_add_symbol_hook \
+  sparc64_elf_add_symbol_hook
+#define elf_backend_get_symbol_type \
+  sparc64_elf_get_symbol_type
+#define elf_backend_symbol_processing \
+  sparc64_elf_symbol_processing
 #define elf_backend_check_relocs \
   sparc64_elf_check_relocs
 #define elf_backend_adjust_dynamic_symbol \
@@ -2678,6 +3044,10 @@ const struct elf_size_info sparc64_elf_s
   sparc64_elf_finish_dynamic_symbol
 #define elf_backend_finish_dynamic_sections \
   sparc64_elf_finish_dynamic_sections
+#define elf_backend_print_symbol_all \
+  sparc64_elf_print_symbol_all
+#define elf_backend_output_arch_syms \
+  sparc64_elf_output_arch_syms
 
 #define bfd_elf64_bfd_merge_private_bfd_data \
   sparc64_elf_merge_private_bfd_data
--- ./bfd/elf.c.jj4	Tue Jun 29 10:47:02 1999
+++ ./bfd/elf.c	Wed Jul  7 09:47:57 1999
@@ -756,8 +756,21 @@ bfd_elf_print_symbol (abfd, filep, symbo
     case bfd_print_symbol_all:
       {
 	CONST char *section_name;
+	CONST char *name = NULL;
+	struct elf_backend_data *bed;
+	
 	section_name = symbol->section ? symbol->section->name : "(*none*)";
-	bfd_print_symbol_vandf ((PTR) file, symbol);
+
+	bed = get_elf_backend_data (abfd);
+	if (bed->elf_backend_print_symbol_all)
+	    name = (*bed->elf_backend_print_symbol_all) (abfd, filep, symbol);
+
+	if (name == NULL)
+	  {
+	    name = symbol->name;  
+	    bfd_print_symbol_vandf ((PTR) file, symbol);
+	  }
+
 	fprintf (file, " %s\t", section_name);
 	/* Print the "other" value for a symbol.  For common symbols,
 	   we've already printed the size; now print the alignment.
@@ -825,7 +838,7 @@ bfd_elf_print_symbol (abfd, filep, symbo
 		   ((unsigned int)
 		    ((elf_symbol_type *) symbol)->internal_elf_sym.st_other));
 
-	fprintf (file, " %s", symbol->name);
+	fprintf (file, " %s", name);
       }
       break;
     }
--- ./bfd/elflink.h.jj4	Tue Jun 29 10:47:22 1999
+++ ./bfd/elflink.h	Sat Jul  3 21:43:13 1999
@@ -4064,6 +4064,18 @@ elf_bfd_final_link (abfd, info)
   if (eoinfo.failed)
     return false;
 
+  /* If backend needs to output some symbols not present in the hash
+     table, do it now.  */
+  if (bed->elf_backend_output_arch_syms)
+    {
+      if (! (*bed->elf_backend_output_arch_syms)
+	      (info, (PTR) &finfo,
+	       (boolean (*) PARAMS ((PTR, const char *,
+	                    Elf_Internal_Sym *, asection *)))
+	       elf_link_output_sym))
+	return false;
+    }      
+
   /* Flush all symbols to the file.  */
   if (! elf_link_flush_output_syms (&finfo))
     return false;
--- ./bfd/elfxx-target.h.jj4	Wed Jun  9 09:51:35 1999
+++ ./bfd/elfxx-target.h	Sat Jul  3 21:07:17 1999
@@ -294,6 +294,12 @@ Foundation, Inc., 59 Temple Place - Suit
 #ifndef elf_backend_post_process_headers
 #define elf_backend_post_process_headers	NULL
 #endif
+#ifndef elf_backend_print_symbol_all
+#define elf_backend_print_symbol_all		NULL
+#endif
+#ifndef elf_backend_output_arch_syms
+#define elf_backend_output_arch_syms		NULL
+#endif
 
 /* Previously, backends could only use SHT_REL or SHT_RELA relocation
    sections, but not both.  They defined USE_REL to indicate SHT_REL
@@ -366,6 +372,8 @@ static CONST struct elf_backend_data elf
   elf_backend_gc_mark_hook,
   elf_backend_gc_sweep_hook,
   elf_backend_post_process_headers,
+  elf_backend_print_symbol_all,
+  elf_backend_output_arch_syms,
   elf_backend_ecoff_debug_swap,
   ELF_MACHINE_ALT1,
   ELF_MACHINE_ALT2,
--- ./binutils/readelf.c.jj4	Mon Jul  5 14:55:30 1999
+++ ./binutils/readelf.c	Wed Jul  7 12:16:31 1999
@@ -899,6 +899,10 @@ get_dynamic_type (type)
 	}
       else if ((type >= DT_LOOS) && (type <= DT_HIOS))
 	sprintf (buff, _("Operating System specific: %lx"), type);
+      else if (type == DT_SPARC_REGISTER
+	       && elf_header.e_machine == EM_SPARCV9)
+	/* Why this allocation could not go into the LOPROC-HIPROC area? */
+	return "SPARC_REGISTER";
       else
 	sprintf (buff, _("<unknown>: %lx"), type);
       
--- ./gas/config/tc-sparc.c.jj4	Wed Jul  7 09:41:46 1999
+++ ./gas/config/tc-sparc.c	Wed Jul  7 13:36:13 1999
@@ -87,6 +87,10 @@ static int warn_on_bump;
    architecture, issue a warning.  */
 static enum sparc_opcode_arch_val warn_after_architecture;
 
+/* Non-zero if as should generate error if an undeclared g[23] register
+   has been used in -64.  */
+static int no_undeclared_regs;
+
 /* Non-zero if we are generating PIC code.  */
 int sparc_pic_code;
 
@@ -97,6 +101,9 @@ extern int target_big_endian;
 
 static int target_little_endian_data;
 
+/* Symbols for global registers on v9.  */
+static symbolS *globals[8];
+
 /* V9 and 86x have big and little endian data, but instructions are always big
    endian.  The sparclet has bi-endian support but both data and insns have
    the same endianness.  Global `target_big_endian' is used for data.
@@ -119,6 +126,7 @@ static void s_common PARAMS ((int));
 static void s_empty PARAMS ((int));
 static void s_uacons PARAMS ((int));
 static void s_ncons PARAMS ((int));
+static void s_register PARAMS ((int));
 
 const pseudo_typeS md_pseudo_table[] =
 {
@@ -143,6 +151,7 @@ const pseudo_typeS md_pseudo_table[] =
   {"2byte", s_uacons, 2},
   {"4byte", s_uacons, 4},
   {"8byte", s_uacons, 8},
+  {"register", s_register, 0},
 #endif
   {NULL, 0, 0},
 };
@@ -400,6 +409,10 @@ struct option md_longopts[] = {
   {"enforce-aligned-data", no_argument, NULL, OPTION_ENFORCE_ALIGNED_DATA},
 #define OPTION_LITTLE_ENDIAN_DATA (OPTION_MD_BASE + 11)
   {"little-endian-data", no_argument, NULL, OPTION_LITTLE_ENDIAN_DATA},
+#ifdef OBJ_ELF
+#define OPTION_NO_UNDECLARED_REGS (OPTION_MD_BASE + 12)
+  {"no-undeclared-regs", no_argument, NULL, OPTION_NO_UNDECLARED_REGS},
+#endif
   {NULL, no_argument, NULL, 0}
 };
 size_t md_longopts_size = sizeof(md_longopts);
@@ -549,6 +562,10 @@ md_parse_option (c, arg)
       else
 	sparc_pic_code = 1;
       break;
+
+    case OPTION_NO_UNDECLARED_REGS:
+      no_undeclared_regs = 1;
+      break;
 #endif
 
     default:
@@ -1865,6 +1882,11 @@ sparc_ip (str, pinsn)
 		      goto error;
 		    }
 
+		  if ((mask & ~1) == 2 && sparc_arch_size == 64
+		      && no_undeclared_regs && ! globals [mask])
+		    as_bad (_("detected global register use not "
+			      "covered by .register pseudo-op"));
+
 		  /* Got the register, now figure out where
 		     it goes in the opcode.  */
 		  switch (*args)
@@ -3706,6 +3728,112 @@ s_ncons (bytes)
 {
   cons (sparc_arch_size == 32 ? 4 : 8);
 }
+
+#ifdef OBJ_ELF
+/* Handle the SPARC ELF .register pseudo-op.  This sets the binding of a
+   global register.
+   The syntax is:
+   
+   .register %g[2367],{#scratch|symbolname}
+   */
+
+static void
+s_register (ignore)
+     int ignore;
+{
+  char c;
+  int reg;
+  int flags;
+  const char *regname;
+
+  if (input_line_pointer[0] != '%'
+      || input_line_pointer[1] != 'g'
+      || ((input_line_pointer[2] & ~1) != '2'
+	  && (input_line_pointer[2] & ~1) != '6')
+      || input_line_pointer[3] != ',')
+    as_bad (_("register syntax is .register %%g[2367],{#scratch|symbolname}"));
+  reg = input_line_pointer[2] - '0';
+  input_line_pointer += 4;
+
+  if (*input_line_pointer == '#')
+    {
+      ++input_line_pointer;
+      regname = input_line_pointer;
+      c = get_symbol_end ();
+      if (strcmp (regname, "scratch"))
+	as_bad (_("register syntax is .register %%g[2367],{#scratch|symbolname}"));
+      regname = "";
+    }
+  else
+    {
+      regname = input_line_pointer;
+      c = get_symbol_end ();
+    }
+  if (sparc_arch_size == 64)
+    {
+      if (globals [reg])
+	{
+	  if (strcmp (S_GET_NAME (globals [reg]), regname))
+	    as_bad (_("redefinition of global register"));
+	}
+      else
+	{
+	  if (*regname)
+	    {
+	      if (symbol_find (regname))
+		as_bad (_("Register symbol %s already defined."), regname);
+	    }
+	  globals [reg] = symbol_make (regname);
+	  flags = symbol_get_bfdsym (globals [reg])->flags;
+	  if (! *regname)
+	    flags = flags & ~(BSF_GLOBAL|BSF_LOCAL|BSF_WEAK);
+	  if (! (flags & (BSF_GLOBAL|BSF_LOCAL|BSF_WEAK)))
+	    flags |= BSF_GLOBAL;
+	  symbol_get_bfdsym (globals [reg])->flags = flags;
+	  S_SET_VALUE (globals [reg], (valueT)reg);
+	  S_SET_ALIGN (globals [reg], reg);
+	  S_SET_SIZE (globals [reg], 0);
+	  /* Although we actually want undefined_section here,
+	     we have to use absolute_section, because otherwise
+	     generic as code will make it a COM section.
+	     We fix this up in sparc_adjust_symtab.  */
+	  S_SET_SEGMENT (globals [reg], absolute_section);
+	  S_SET_OTHER (globals [reg], 0);
+	  elf_symbol (symbol_get_bfdsym (globals [reg]))
+	    ->internal_elf_sym.st_info =
+	      ELF_ST_INFO(STB_GLOBAL, STT_REGISTER);
+	  elf_symbol (symbol_get_bfdsym (globals [reg]))
+	    ->internal_elf_sym.st_shndx = SHN_UNDEF;
+	}
+    }
+
+  *input_line_pointer = c;
+
+  demand_empty_rest_of_line ();
+}
+
+/* Adjust the symbol table.  We set undefined sections for STT_REGISTER
+   symbols which need it.  */
+   
+void
+sparc_adjust_symtab ()
+{
+  symbolS *sym;
+     
+  for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
+    {
+      if (ELF_ST_TYPE (elf_symbol (symbol_get_bfdsym (sym))
+		       ->internal_elf_sym.st_info) != STT_REGISTER)
+	continue;
+
+      if (ELF_ST_TYPE (elf_symbol (symbol_get_bfdsym (sym))
+		       ->internal_elf_sym.st_shndx != SHN_UNDEF))
+	continue;
+
+      S_SET_SEGMENT (sym, undefined_section);
+    }
+}
+#endif
 
 /* If the --enforce-aligned-data option is used, we require .word,
    et. al., to be aligned correctly.  We do it by setting up an
--- ./gas/config/tc-sparc.h.jj4	Mon Jul  5 14:15:17 1999
+++ ./gas/config/tc-sparc.h	Wed Jul  7 13:35:50 1999
@@ -134,6 +134,10 @@ extern int elf32_sparc_force_relocation 
 	       == S_GET_SEGMENT ((FIX)->fx_addsy)))			\
        || strchr (S_GET_NAME ((FIX)->fx_addsy), '\001') != NULL		\
        || strchr (S_GET_NAME ((FIX)->fx_addsy), '\002') != NULL))
+
+/* Finish up the entire symtab.  */
+#define tc_adjust_symtab() sparc_adjust_symtab ()
+extern void sparc_adjust_symtab PARAMS ((void));
 #endif
 
 #ifdef OBJ_AOUT
--- ./gas/doc/c-sparc.texi.jj4	Mon May  3 09:28:45 1999
+++ ./gas/doc/c-sparc.texi	Sat Jul  3 18:38:25 1999
@@ -145,11 +145,24 @@ syntax is different.
 @item .half
 This is functionally identical to @code{.short}.
 
+@cindex @code{nword} directive, SPARC
+@item .nword
+On the Sparc, the @code{.nword} directive produces native word sized value,
+ie. if assembling with -32 it is equivalent to @code{.word}, if assembling
+with -64 it is equivalent to @code{.xword}.
+
 @cindex @code{proc} directive, SPARC
 @item .proc
 This directive is ignored.  Any text following it on the same
 line is also ignored.
 
+@cindex @code{register} directive, SPARC
+@item .register
+This directive declares use of a global application or system register.
+It must be followed by a register name %g2, %g3, %g6 or %g7, comma and
+the symbol name for that register or @code{#scratch} if it is a scratch
+register.
+
 @cindex @code{reserve} directive, SPARC
 @item .reserve
 This must be followed by a symbol name, a positive number, and
@@ -176,4 +189,3 @@ instead of the 16 bit values it produces
 On the Sparc V9 processor, the @code{.xword} directive produces
 64 bit values.
 @end table
-
--- ./include/elf/sparc.h.jj4	Mon Jul  5 14:44:35 1999
+++ ./include/elf/sparc.h	Wed Jul  7 12:08:04 1999
@@ -143,7 +143,7 @@ END_RELOC_NUMBERS
 #define ELF64_R_TYPE_INFO(data, type)	(((((bfd_vma) (data)) & 0xffffff) << 8) \
 					 + (bfd_vma) (type))
 
-#define DT_SPARC_REGISTER	0x70000001
+#define DT_SPARC_REGISTER	0x07000001
 
 /*
  * FIXME: NOT ABI -- GET RID OF THIS


Cheers,
    Jakub
___________________________________________________________________
Jakub Jelinek | jj@sunsite.mff.cuni.cz | http://sunsite.mff.cuni.cz
Administrator of SunSITE Czech Republic, MFF, Charles University
___________________________________________________________________
UltraLinux  |  http://ultra.linux.cz/  |  http://ultra.penguin.cz/
Linux version 2.3.9 on a sparc64 machine (1343.49 BogoMips)
___________________________________________________________________

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