Back to index

glibc  2.9
Defines | Functions
dl-machine.h File Reference
#include <string.h>

Go to the source code of this file.

Defines

#define ELF_MACHINE_NAME   "alpha"
#define ELF_MACHINE_USER_ADDRESS_MASK   0x120000000UL
#define DT_ALPHA(x)   (DT_ALPHA_##x - DT_LOPROC + DT_NUM)
#define RTLD_START   asm ("\ .section .text \n\ .set at \n\ .globl _start \n\ .ent _start \n\_start: \n\ .frame $31,0,$31,0 \n\ br $gp, 0f \n\0: ldgp $gp, 0($gp) \n\ .prologue 0 \n\ /* Pass pointer to argument block to _dl_start. */ \n\ mov $sp, $16 \n\ bsr $26, _dl_start !samegp \n\ .end _start \n\ /* FALLTHRU */ \n\ .globl _dl_start_user \n\ .ent _dl_start_user \n\_dl_start_user: \n\ .frame $31,0,$31,0 \n\ .prologue 0 \n\ /* Save the user entry point address in s0. */ \n\ mov $0, $9 \n\ /* See if we were run as a command with the executable \n\ file name as an extra leading argument. */ \n\ ldah $1, _dl_skip_args($gp) !gprelhigh \n\ ldl $1, _dl_skip_args($1) !gprellow \n\ bne $1, $fixup_stack \n\$fixup_stack_ret: \n\ /* The special initializer gets called with the stack \n\ just as the application's entry point will see it; \n\ it can switch stacks if it moves these contents \n\ over. */ \n\" RTLD_START_SPECIAL_INIT " \n\ /* Call _dl_init(_dl_loaded, argc, argv, envp) to run \n\ initializers. */ \n\ ldah $16, _rtld_local($gp) !gprelhigh \n\ ldq $16, _rtld_local($16) !gprellow \n\ ldq $17, 0($sp) \n\ lda $18, 8($sp) \n\ s8addq $17, 8, $19 \n\ addq $19, $18, $19 \n\ bsr $26, _dl_init_internal !samegp \n\ /* Pass our finalizer function to the user in $0. */ \n\ ldah $0, _dl_fini($gp) !gprelhigh \n\ lda $0, _dl_fini($0) !gprellow \n\ /* Jump to the user's entry point. */ \n\ mov $9, $27 \n\ jmp ($9) \n\$fixup_stack: \n\ /* Adjust the stack pointer to skip _dl_skip_args words.\n\ This involves copying everything down, since the \n\ stack pointer must always be 16-byte aligned. */ \n\ ldah $7, _dl_argv_internal($gp) !gprelhigh \n\ ldq $2, 0($sp) \n\ ldq $5, _dl_argv_internal($7) !gprellow \n\ subq $31, $1, $6 \n\ subq $2, $1, $2 \n\ s8addq $6, $5, $5 \n\ mov $sp, $4 \n\ s8addq $1, $sp, $3 \n\ stq $2, 0($sp) \n\ stq $5, _dl_argv_internal($7) !gprellow \n\ /* Copy down argv. */ \n\0: ldq $5, 8($3) \n\ addq $4, 8, $4 \n\ addq $3, 8, $3 \n\ stq $5, 0($4) \n\ bne $5, 0b \n\ /* Copy down envp. */ \n\1: ldq $5, 8($3) \n\ addq $4, 8, $4 \n\ addq $3, 8, $3 \n\ stq $5, 0($4) \n\ bne $5, 1b \n\ /* Copy down auxiliary table. */ \n\2: ldq $5, 8($3) \n\ ldq $6, 16($3) \n\ addq $4, 16, $4 \n\ addq $3, 16, $3 \n\ stq $5, -8($4) \n\ stq $6, 0($4) \n\ bne $5, 2b \n\ br $fixup_stack_ret \n\ .end _dl_start_user \n\ .set noat \n\.previous");
#define RTLD_START_SPECIAL_INIT   /* nothing */
#define elf_machine_type_class(type)
#define ELF_MACHINE_JMP_SLOT   R_ALPHA_JMP_SLOT
#define ELF_MACHINE_NO_REL   1
#define ARCH_LA_PLTENTER   alpha_gnu_pltenter
#define ARCH_LA_PLTEXIT   alpha_gnu_pltexit

Functions

static int elf_machine_matches_host (const Elf64_Ehdr *ehdr)
static Elf64_Addr elf_machine_dynamic (void)
static Elf64_Addr elf_machine_load_address (void)
static int elf_machine_runtime_setup (struct link_map *map, int lazy, int profile)
static Elf64_Addr elf_machine_fixup_plt (struct link_map *map, lookup_t t, const Elf64_Rela *reloc, Elf64_Addr *got_addr, Elf64_Addr value)
static Elf64_Addr elf_machine_plt_value (struct link_map *map, const Elf64_Rela *reloc, Elf64_Addr value)

Define Documentation

#define ARCH_LA_PLTENTER   alpha_gnu_pltenter

Definition at line 347 of file dl-machine.h.

#define ARCH_LA_PLTEXIT   alpha_gnu_pltexit

Definition at line 348 of file dl-machine.h.

#define DT_ALPHA (   x)    (DT_ALPHA_##x - DT_LOPROC + DT_NUM)

Definition at line 37 of file dl-machine.h.

Definition at line 247 of file dl-machine.h.

#define ELF_MACHINE_NAME   "alpha"

Definition at line 27 of file dl-machine.h.

#define ELF_MACHINE_NO_REL   1

Definition at line 250 of file dl-machine.h.

Value:

Definition at line 236 of file dl-machine.h.

#define ELF_MACHINE_USER_ADDRESS_MASK   0x120000000UL

Definition at line 34 of file dl-machine.h.

#define RTLD_START   asm ("\ .section .text \n\ .set at \n\ .globl _start \n\ .ent _start \n\_start: \n\ .frame $31,0,$31,0 \n\ br $gp, 0f \n\0: ldgp $gp, 0($gp) \n\ .prologue 0 \n\ /* Pass pointer to argument block to _dl_start. */ \n\ mov $sp, $16 \n\ bsr $26, _dl_start !samegp \n\ .end _start \n\ /* FALLTHRU */ \n\ .globl _dl_start_user \n\ .ent _dl_start_user \n\_dl_start_user: \n\ .frame $31,0,$31,0 \n\ .prologue 0 \n\ /* Save the user entry point address in s0. */ \n\ mov $0, $9 \n\ /* See if we were run as a command with the executable \n\ file name as an extra leading argument. */ \n\ ldah $1, _dl_skip_args($gp) !gprelhigh \n\ ldl $1, _dl_skip_args($1) !gprellow \n\ bne $1, $fixup_stack \n\$fixup_stack_ret: \n\ /* The special initializer gets called with the stack \n\ just as the application's entry point will see it; \n\ it can switch stacks if it moves these contents \n\ over. */ \n\" RTLD_START_SPECIAL_INIT " \n\ /* Call _dl_init(_dl_loaded, argc, argv, envp) to run \n\ initializers. */ \n\ ldah $16, _rtld_local($gp) !gprelhigh \n\ ldq $16, _rtld_local($16) !gprellow \n\ ldq $17, 0($sp) \n\ lda $18, 8($sp) \n\ s8addq $17, 8, $19 \n\ addq $19, $18, $19 \n\ bsr $26, _dl_init_internal !samegp \n\ /* Pass our finalizer function to the user in $0. */ \n\ ldah $0, _dl_fini($gp) !gprelhigh \n\ lda $0, _dl_fini($0) !gprellow \n\ /* Jump to the user's entry point. */ \n\ mov $9, $27 \n\ jmp ($9) \n\$fixup_stack: \n\ /* Adjust the stack pointer to skip _dl_skip_args words.\n\ This involves copying everything down, since the \n\ stack pointer must always be 16-byte aligned. */ \n\ ldah $7, _dl_argv_internal($gp) !gprelhigh \n\ ldq $2, 0($sp) \n\ ldq $5, _dl_argv_internal($7) !gprellow \n\ subq $31, $1, $6 \n\ subq $2, $1, $2 \n\ s8addq $6, $5, $5 \n\ mov $sp, $4 \n\ s8addq $1, $sp, $3 \n\ stq $2, 0($sp) \n\ stq $5, _dl_argv_internal($7) !gprellow \n\ /* Copy down argv. */ \n\0: ldq $5, 8($3) \n\ addq $4, 8, $4 \n\ addq $3, 8, $3 \n\ stq $5, 0($4) \n\ bne $5, 0b \n\ /* Copy down envp. */ \n\1: ldq $5, 8($3) \n\ addq $4, 8, $4 \n\ addq $3, 8, $3 \n\ stq $5, 0($4) \n\ bne $5, 1b \n\ /* Copy down auxiliary table. */ \n\2: ldq $5, 8($3) \n\ ldq $6, 16($3) \n\ addq $4, 16, $4 \n\ addq $3, 16, $3 \n\ stq $5, -8($4) \n\ stq $6, 0($4) \n\ bne $5, 2b \n\ br $fixup_stack_ret \n\ .end _dl_start_user \n\ .set noat \n\.previous");

Definition at line 136 of file dl-machine.h.

#define RTLD_START_SPECIAL_INIT   /* nothing */

Definition at line 224 of file dl-machine.h.


Function Documentation

static Elf64_Addr elf_machine_dynamic ( void  ) [inline, static]

Definition at line 50 of file dl-machine.h.

{
#ifndef NO_AXP_MULTI_GOT_LD
  return (Elf64_Addr) &_DYNAMIC;
#else
  register Elf64_Addr *gp __asm__ ("$29");
  return gp[-4096];
#endif
}

Here is the call graph for this function:

static Elf64_Addr elf_machine_fixup_plt ( struct link_map map,
lookup_t  t,
const Elf64_Rela reloc,
Elf64_Addr got_addr,
Elf64_Addr  value 
) [inline, static]

Definition at line 255 of file dl-machine.h.

{
  const Elf64_Rela *rela_plt;
  Elf64_Word *plte;
  long int edisp;

  /* Store the value we are going to load.  */
  *got_addr = value;

  /* If this binary uses the read-only secure plt format, we're done.  */
  if (map->l_info[DT_ALPHA(PLTRO)])
    return value;

  /* Otherwise we have to modify the plt entry in place to do the branch.  */

  /* Recover the PLT entry address by calculating reloc's index into the
     .rela.plt, and finding that entry in the .plt.  */
  rela_plt = (const Elf64_Rela *) D_PTR (map, l_info[DT_JMPREL]);
  plte = (Elf64_Word *) (D_PTR (map, l_info[DT_PLTGOT]) + 32);
  plte += 3 * (reloc - rela_plt);

  /* Find the displacement from the plt entry to the function.  */
  edisp = (long int) (value - (Elf64_Addr)&plte[3]) / 4;

  if (edisp >= -0x100000 && edisp < 0x100000)
    {
      /* If we are in range, use br to perfect branch prediction and
        elide the dependency on the address load.  This case happens,
        e.g., when a shared library call is resolved to the same library.  */

      int hi, lo;
      hi = value - (Elf64_Addr)&plte[0];
      lo = (short int) hi;
      hi = (hi - lo) >> 16;

      /* Emit "lda $27,lo($27)" */
      plte[1] = 0x237b0000 | (lo & 0xffff);

      /* Emit "br $31,function" */
      plte[2] = 0xc3e00000 | (edisp & 0x1fffff);

      /* Think about thread-safety -- the previous instructions must be
        committed to memory before the first is overwritten.  */
      __asm__ __volatile__("wmb" : : : "memory");

      /* Emit "ldah $27,hi($27)" */
      plte[0] = 0x277b0000 | (hi & 0xffff);
    }
  else
    {
      /* Don't bother with the hint since we already know the hint is
        wrong.  Eliding it prevents the wrong page from getting pulled
        into the cache.  */

      int hi, lo;
      hi = (Elf64_Addr)got_addr - (Elf64_Addr)&plte[0];
      lo = (short)hi;
      hi = (hi - lo) >> 16;

      /* Emit "ldq $27,lo($27)" */
      plte[1] = 0xa77b0000 | (lo & 0xffff);

      /* Emit "jmp $31,($27)" */
      plte[2] = 0x6bfb0000;

      /* Think about thread-safety -- the previous instructions must be
        committed to memory before the first is overwritten.  */
      __asm__ __volatile__("wmb" : : : "memory");

      /* Emit "ldah $27,hi($27)" */
      plte[0] = 0x277b0000 | (hi & 0xffff);
    }

  /* At this point, if we've been doing runtime resolution, Icache is dirty.
     This will be taken care of in _dl_runtime_resolve.  If instead we are
     doing this as part of non-lazy startup relocation, that bit of code
     hasn't made it into Icache yet, so there's nothing to clean up.  */

  return value;
}

Here is the call graph for this function:

static Elf64_Addr elf_machine_load_address ( void  ) [inline, static]

Definition at line 63 of file dl-machine.h.

{
  /* This relies on the compiler using gp-relative addresses for static symbols.  */
  static void *dot = &dot;
  return (void *)&dot - dot;
}
static int elf_machine_matches_host ( const Elf64_Ehdr ehdr) [inline, static]

Definition at line 41 of file dl-machine.h.

{
  return ehdr->e_machine == EM_ALPHA;
}
static Elf64_Addr elf_machine_plt_value ( struct link_map map,
const Elf64_Rela reloc,
Elf64_Addr  value 
) [inline, static]

Definition at line 340 of file dl-machine.h.

{
  return value + reloc->r_addend;
}
static int elf_machine_runtime_setup ( struct link_map map,
int  lazy,
int  profile 
) [inline, static]

Definition at line 74 of file dl-machine.h.

{
  extern char _dl_runtime_resolve_new[] attribute_hidden;
  extern char _dl_runtime_profile_new[] attribute_hidden;
  extern char _dl_runtime_resolve_old[] attribute_hidden;
  extern char _dl_runtime_profile_old[] attribute_hidden;

  struct pltgot {
    char *resolve;
    struct link_map *link;
  };

  struct pltgot *pg;
  long secureplt;
  char *resolve;

  if (map->l_info[DT_JMPREL] == 0 || !lazy)
    return lazy;

  /* Check to see if we're using the read-only plt form.  */
  secureplt = map->l_info[DT_ALPHA(PLTRO)] != 0;

  /* If the binary uses the read-only secure plt format, PG points to
     the .got.plt section, which is the right place for ld.so to place
     its hooks.  Otherwise, PG is currently pointing at the start of
     the plt; the hooks go at offset 16.  */
  pg = (struct pltgot *) D_PTR (map, l_info[DT_PLTGOT]);
  pg += !secureplt;

  /* This function will be called to perform the relocation.  They're
     not declared as functions to convince the compiler to use gp
     relative relocations for them.  */
  if (secureplt)
    resolve = _dl_runtime_resolve_new;
  else
    resolve = _dl_runtime_resolve_old;

  if (__builtin_expect (profile, 0))
    {
      if (secureplt)
       resolve = _dl_runtime_profile_new;
      else
       resolve = _dl_runtime_profile_old;

      if (GLRO(dl_profile) && _dl_name_match_p (GLRO(dl_profile), map))
       {
         /* This is the object we are looking for.  Say that we really
            want profiling and the timers are started.  */
         GL(dl_profile_map) = map;
       }
    }

  pg->resolve = resolve;
  pg->link = map;

  return lazy;
}

Here is the call graph for this function: