(root)/
glibc-2.38/
sysdeps/
microblaze/
dl-machine.h
       1  /* Copyright (C) 1995-2023 Free Software Foundation, Inc.
       2  
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public License as
       7     published by the Free Software Foundation; either version 2.1 of the
       8     License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #ifndef dl_machine_h
      20  #define dl_machine_h
      21  
      22  #define ELF_MACHINE_NAME "microblaze"
      23  
      24  #include <sys/param.h>
      25  #include <tls.h>
      26  #include <dl-static-tls.h>
      27  #include <dl-machine-rel.h>
      28  
      29  /* Return nonzero iff ELF header is compatible with the running host.  */
      30  static inline int
      31  elf_machine_matches_host (const Elf32_Ehdr *ehdr)
      32  {
      33    return (ehdr->e_machine == EM_MICROBLAZE);
      34  }
      35  
      36  /* Return the link-time address of _DYNAMIC.  Conveniently, this is the
      37     first element of the GOT.  This must be inlined in a function which
      38     uses global data.  */
      39  static inline Elf32_Addr
      40  elf_machine_dynamic (void)
      41  {
      42    /* This produces a GOTOFF reloc that resolves to zero at link time, so in
      43       fact just loads from the GOT register directly.  By doing it without
      44       an asm we can let the compiler choose any register.  */
      45  
      46    Elf32_Addr got_entry_0;
      47    __asm__ __volatile__(
      48      "lwi %0,r20,0"
      49      :"=r"(got_entry_0)
      50      );
      51    return got_entry_0;
      52  }
      53  
      54  /* Return the run-time load address of the shared object.  */
      55  static inline Elf32_Addr
      56  elf_machine_load_address (void)
      57  {
      58    /* Compute the difference between the runtime address of _DYNAMIC as seen
      59       by a GOTOFF reference, and the link-time address found in the special
      60       unrelocated first GOT entry.  */
      61  
      62    Elf32_Addr dyn;
      63    __asm__ __volatile__ (
      64      "addik %0,r20,_DYNAMIC@GOTOFF"
      65      : "=r"(dyn)
      66      );
      67    return dyn - elf_machine_dynamic ();
      68  }
      69  
      70  /* Set up the loaded object described by L so its unrelocated PLT
      71     entries will jump to the on-demand fixup code in dl-runtime.c.  */
      72  
      73  static inline int __attribute__ ((always_inline))
      74  elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[],
      75  			   int lazy, int profile)
      76  {
      77    extern void _dl_runtime_resolve (Elf32_Word);
      78    extern void _dl_runtime_profile (Elf32_Word);
      79  
      80    return lazy;
      81  }
      82  
      83  /* The PLT uses Elf32_Rela relocs.  */
      84  #define elf_machine_relplt elf_machine_rela
      85  
      86  /* Mask identifying addresses reserved for the user program,
      87     where the dynamic linker should not map anything.  */
      88  #define ELF_MACHINE_USER_ADDRESS_MASK	0x80000000UL
      89  
      90  /* Initial entry point code for the dynamic linker.
      91     The C function `_dl_start' is the real entry point;
      92     its return value is the user program's entry point.  */
      93  
      94  #define RTLD_START asm ("\
      95  	.text\n\
      96  	.globl _start\n\
      97  	.type _start,@function\n\
      98  _start:\n\
      99  	addk  r5,r0,r1\n\
     100  	addk  r3,r0,r0\n\
     101  1:\n\
     102  	addik r5,r5,4\n\
     103  	lw    r4,r5,r0\n\
     104  	bneid r4,1b\n\
     105  	addik r3,r3,1\n\
     106  	addik r3,r3,-1\n\
     107  	addk  r5,r0,r1\n\
     108  	sw    r3,r5,r0\n\
     109  	addik r1,r1,-24\n\
     110  	sw    r15,r1,r0\n\
     111  	brlid r15,_dl_start\n\
     112  	nop\n\
     113  	/* FALLTHRU.  */\n\
     114  \n\
     115  	.globl _dl_start_user\n\
     116  	.type _dl_start_user,@function\n\
     117  _dl_start_user:\n\
     118  	mfs   r20,rpc\n\
     119  	addik r20,r20,_GLOBAL_OFFSET_TABLE_+8\n\
     120  	lwi   r5,r1,24\n\
     121  	swi   r5,r1,24\n\
     122  	swi   r3,r1,20\n\
     123  	addk  r6,r5,r0\n\
     124  	addk  r5,r5,r5\n\
     125  	addk  r5,r5,r5\n\
     126  	addik r7,r1,28\n\
     127  	addk  r8,r7,r5\n\
     128  	addik r8,r8,4\n\
     129  	lwi   r5,r20,_rtld_local@GOTOFF\n\
     130  	brlid r15,_dl_init\n\
     131  	nop\n\
     132  	lwi   r5,r1,24\n\
     133  	lwi   r3,r1,20\n\
     134  	addk  r4,r5,r5\n\
     135  	addk  r4,r4,r4\n\
     136  	addik r6,r1,28\n\
     137  	addk  r7,r6,r4\n\
     138  	addik r7,r7,4\n\
     139  	addik r15,r20,_dl_fini@GOTOFF\n\
     140  	addik r15,r15,-8\n\
     141  	brad  r3\n\
     142  	addik r1,r1,24\n\
     143  	nop\n\
     144  	.size _dl_start_user, . - _dl_start_user\n\
     145  	.previous");
     146  
     147  /* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry or
     148     TLS variable, so undefined references should not be allowed to
     149     define the value.
     150     ELF_RTYPE_CLASS_COPY iff TYPE should not be allowed to resolve to one
     151     of the main executable's symbols, as for a COPY reloc.  */
     152  #ifndef RTLD_BOOTSTRAP
     153  # define elf_machine_type_class(type) \
     154    (((type) == R_MICROBLAZE_JUMP_SLOT \
     155      || (type) == R_MICROBLAZE_TLSDTPREL32 \
     156      || (type) == R_MICROBLAZE_TLSDTPMOD32 \
     157      || (type) == R_MICROBLAZE_TLSTPREL32) \
     158      * ELF_RTYPE_CLASS_PLT \
     159     | ((type) == R_MICROBLAZE_COPY) * ELF_RTYPE_CLASS_COPY)
     160  #else
     161  # define elf_machine_type_class(type) \
     162    (((type) == R_MICROBLAZE_JUMP_SLOT) * ELF_RTYPE_CLASS_PLT \
     163     | ((type) == R_MICROBLAZE_COPY) * ELF_RTYPE_CLASS_COPY)
     164  #endif
     165  
     166  /* A reloc type used for ld.so cmdline arg lookups to reject PLT entries.  */
     167  #define ELF_MACHINE_JMP_SLOT	R_MICROBLAZE_JUMP_SLOT
     168  
     169  static inline Elf32_Addr
     170  elf_machine_fixup_plt (struct link_map *map, lookup_t t,
     171  		       const ElfW(Sym) *refsym, const ElfW(Sym) *sym,
     172  		       const Elf32_Rela *reloc,
     173  		       Elf32_Addr *reloc_addr, Elf32_Addr value)
     174  {
     175    return *reloc_addr = value;
     176  }
     177  
     178  /* Return the final value of a plt relocation. Ignore the addend.  */
     179  static inline Elf32_Addr
     180  elf_machine_plt_value (struct link_map *map, const Elf32_Rela *reloc,
     181  		       Elf32_Addr value)
     182  {
     183    return value;
     184  }
     185  
     186  #endif /* !dl_machine_h.  */
     187  
     188  /* Names of the architecture-specific auditing callback functions.  */
     189  #define ARCH_LA_PLTENTER microblaze_gnu_pltenter
     190  #define ARCH_LA_PLTEXIT microblaze_gnu_pltexit
     191  
     192  #ifdef RESOLVE_MAP
     193  
     194  /* Perform the relocation specified by RELOC and SYM (which is fully resolved).
     195     MAP is the object containing the reloc.  */
     196  
     197  /* Macro to put 32-bit relocation value into 2 words.  */
     198  #define PUT_REL_64(rel_addr,val) \
     199    do { \
     200      ((unsigned short *)(rel_addr))[1] = (val) >> 16; \
     201      ((unsigned short *)(rel_addr))[3] = (val) & 0xffff; \
     202    } while (0)
     203  
     204  static inline void __attribute__ ((always_inline))
     205  elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
     206  		  const Elf32_Rela *reloc, const Elf32_Sym *sym,
     207  		  const struct r_found_version *version,
     208  		  void *const reloc_addr_arg, int skip_ifunc)
     209  {
     210    Elf32_Addr *const reloc_addr = reloc_addr_arg;
     211    const int r_type = ELF32_R_TYPE (reloc->r_info);
     212  
     213    if (__builtin_expect (r_type == R_MICROBLAZE_64_PCREL, 0))
     214      PUT_REL_64 (reloc_addr, map->l_addr + reloc->r_addend);
     215    else if (r_type == R_MICROBLAZE_REL)
     216      *reloc_addr = map->l_addr + reloc->r_addend;
     217    else
     218      {
     219        const Elf32_Sym *const refsym = sym;
     220        struct link_map *sym_map = RESOLVE_MAP (map, scope, &sym, version,
     221  					      r_type);
     222        Elf32_Addr value = SYMBOL_ADDRESS (sym_map, sym, true);
     223  
     224        value += reloc->r_addend;
     225        if (r_type == R_MICROBLAZE_GLOB_DAT
     226            || r_type == R_MICROBLAZE_JUMP_SLOT
     227            || r_type == R_MICROBLAZE_32)
     228  	{
     229  	  *reloc_addr = value;
     230  	}
     231        else if (r_type == R_MICROBLAZE_COPY)
     232  	{
     233  	  if (sym != NULL && (sym->st_size > refsym->st_size
     234  	      || (sym->st_size < refsym->st_size && GLRO (dl_verbose))) )
     235  	    {
     236  	      const char *strtab;
     237  
     238  	      strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
     239  	      _dl_error_printf ("\
     240  %s: Symbol `%s' has different size in shared object, consider re-linking\n",
     241  				RTLD_PROGNAME, strtab + refsym->st_name);
     242  	    }
     243  	  memcpy (reloc_addr_arg, (void *) value,
     244  		  MIN (sym->st_size, refsym->st_size));
     245  	}
     246        else if (r_type == R_MICROBLAZE_NONE)
     247  	{
     248  	}
     249  #if !defined RTLD_BOOTSTRAP
     250        else if (r_type == R_MICROBLAZE_TLSDTPMOD32)
     251  	{
     252  	  if (sym_map != NULL)
     253  	    *reloc_addr = sym_map->l_tls_modid;
     254  	}
     255        else if (r_type == R_MICROBLAZE_TLSDTPREL32)
     256  	{
     257  	  if (sym != NULL)
     258  	    *reloc_addr = sym->st_value + reloc->r_addend;
     259  	}
     260        else if (r_type == R_MICROBLAZE_TLSTPREL32)
     261  	{
     262  	  if (sym != NULL)
     263  	    {
     264  	      CHECK_STATIC_TLS (map, sym_map);
     265  	      *reloc_addr = sym->st_value + sym_map->l_tls_offset + reloc->r_addend;
     266  	    }
     267  	}
     268  #endif
     269        else
     270  	{
     271  	  _dl_reloc_bad_type (map, r_type, 0);
     272  	}
     273      }
     274  }
     275  
     276  static inline void
     277  elf_machine_rela_relative (Elf32_Addr l_addr, const Elf32_Rela *reloc,
     278  			   void *const reloc_addr_arg)
     279  {
     280    Elf32_Addr *const reloc_addr = reloc_addr_arg;
     281    PUT_REL_64 (reloc_addr, l_addr + reloc->r_addend);
     282  }
     283  
     284  static inline void
     285  elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
     286  		      Elf32_Addr l_addr, const Elf32_Rela *reloc,
     287  		      int skip_ifunc)
     288  {
     289    Elf32_Addr *const reloc_addr = (void *) (l_addr + reloc->r_offset);
     290    if (ELF32_R_TYPE (reloc->r_info) == R_MICROBLAZE_JUMP_SLOT)
     291      *reloc_addr += l_addr;
     292    else
     293      _dl_reloc_bad_type (map, ELF32_R_TYPE (reloc->r_info), 1);
     294  }
     295  
     296  #endif /* RESOLVE_MAP.  */