Back to index

glibc  2.9
Defines | Functions | Variables
dl-machine.h File Reference
#include <assert.h>
#include <dl-tls.h>
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Defines

#define ELF_MACHINE_NAME   "powerpc"
#define DT_PPC(x)   (DT_PPC_##x - DT_LOPROC + DT_NUM)
#define ELF_MACHINE_BEFORE_RTLD_RELOC(dynamic_info)   /* nothing */
#define elf_machine_relplt   elf_machine_rela
#define ELF_MACHINE_USER_ADDRESS_MASK   0xf0000000UL
#define RTLD_START   asm (".globl _dl_start");
#define ELF_PREFERRED_ADDRESS(loader, maplength, mapstartpref)   __elf_preferred_address (loader, maplength, mapstartpref)
#define elf_machine_type_class(type)
#define ELF_MACHINE_JMP_SLOT   R_PPC_JMP_SLOT
#define ELF_MACHINE_NO_REL   1
#define ARCH_LA_PLTENTER   ppc32_gnu_pltenter
#define ARCH_LA_PLTEXIT   ppc32_gnu_pltexit

Functions

static int elf_machine_matches_host (const Elf32_Ehdr *ehdr)
static Elf32_Addr__attribute__ ((const)) ppc_got(void)
 ElfW (Addr) __elf_preferred_address(struct link_map *loader
int __elf_machine_runtime_setup (struct link_map *map, int lazy, int profile)
static int elf_machine_runtime_setup (struct link_map *map, int lazy, int profile)
Elf32_Addr __elf_machine_fixup_plt (struct link_map *map, const Elf32_Rela *reloc, Elf32_Addr *reloc_addr, Elf32_Addr finaladdr)
static Elf32_Addr elf_machine_fixup_plt (struct link_map *map, lookup_t t, const Elf32_Rela *reloc, Elf32_Addr *reloc_addr, Elf64_Addr finaladdr)
static Elf32_Addr elf_machine_plt_value (struct link_map *map, const Elf32_Rela *reloc, Elf32_Addr value)

Variables

size_t maplength

Define Documentation

#define ARCH_LA_PLTENTER   ppc32_gnu_pltenter

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

#define ARCH_LA_PLTEXIT   ppc32_gnu_pltexit

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

#define DT_PPC (   x)    (DT_PPC_##x - DT_LOPROC + DT_NUM)

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

#define ELF_MACHINE_BEFORE_RTLD_RELOC (   dynamic_info)    /* nothing */

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

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

#define ELF_MACHINE_NAME   "powerpc"

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

#define ELF_MACHINE_NO_REL   1

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

#define elf_machine_relplt   elf_machine_rela

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

Value:
((((type) == R_PPC_JMP_SLOT                      \
    || (type) == R_PPC_REL24                            \
    || ((type) >= R_PPC_DTPMOD32 /* contiguous TLS */   \
       && (type) <= R_PPC_DTPREL32)                     \
    || (type) == R_PPC_ADDR24) * ELF_RTYPE_CLASS_PLT)   \
   | (((type) == R_PPC_COPY) * ELF_RTYPE_CLASS_COPY))

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

#define ELF_MACHINE_USER_ADDRESS_MASK   0xf0000000UL

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

#define ELF_PREFERRED_ADDRESS (   loader,
  maplength,
  mapstartpref 
)    __elf_preferred_address (loader, maplength, mapstartpref)

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

#define RTLD_START   asm (".globl _dl_start");

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


Function Documentation

static Elf32_Addr* __attribute__ ( (const ) [inline, static]

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

{
  Elf32_Addr *got;
#ifdef HAVE_ASM_PPC_REL16
  asm ("bcl 20,31,1f\n"
       "1:    mflr %0\n"
       "      addis %0,%0,_GLOBAL_OFFSET_TABLE_-1b@ha\n"
       "      addi %0,%0,_GLOBAL_OFFSET_TABLE_-1b@l\n"
       : "=b" (got) : : "lr");
#else
  asm (" bl _GLOBAL_OFFSET_TABLE_-4@local"
       : "=l" (got));
#endif
  return got;
}
Elf32_Addr __elf_machine_fixup_plt ( struct link_map map,
const Elf32_Rela reloc,
Elf32_Addr reloc_addr,
Elf32_Addr  finaladdr 
)

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

{
  Elf32_Sword delta = finaladdr - (Elf32_Word) reloc_addr;
  if (delta << 6 >> 6 == delta)
    *reloc_addr = OPCODE_B (delta);
  else if (finaladdr <= 0x01fffffc || finaladdr >= 0xfe000000)
    *reloc_addr = OPCODE_BA (finaladdr);
  else
    {
      Elf32_Word *plt, *data_words;
      Elf32_Word index, offset, num_plt_entries;

      num_plt_entries = (map->l_info[DT_PLTRELSZ]->d_un.d_val
                      / sizeof(Elf32_Rela));
      plt = (Elf32_Word *) D_PTR (map, l_info[DT_PLTGOT]);
      offset = reloc_addr - plt;
      index = (offset - PLT_INITIAL_ENTRY_WORDS)/2;
      data_words = plt + PLT_DATA_START_WORDS (num_plt_entries);

      reloc_addr += 1;

      if (index < PLT_DOUBLE_SIZE)
       {
         data_words[index] = finaladdr;
         PPC_SYNC;
         *reloc_addr = OPCODE_B ((PLT_LONGBRANCH_ENTRY_WORDS - (offset+1))
                              * 4);
       }
      else
       {
         index -= (index - PLT_DOUBLE_SIZE)/2;

         data_words[index] = finaladdr;
         PPC_SYNC;

         reloc_addr[1] = OPCODE_MTCTR (12);
         MODIFIED_CODE_NOQUEUE (reloc_addr + 1);
         PPC_SYNC;

         reloc_addr[0] = OPCODE_LWZ (12,
                                  (Elf32_Word) (data_words + index), 11);
       }
    }
  MODIFIED_CODE (reloc_addr);
  return finaladdr;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int __elf_machine_runtime_setup ( struct link_map map,
int  lazy,
int  profile 
)

Definition at line 212 of file dl-machine.c.

{
  if (map->l_info[DT_JMPREL])
    {
      Elf32_Word i;
      Elf32_Word *plt = (Elf32_Word *) D_PTR (map, l_info[DT_PLTGOT]);
      Elf32_Word num_plt_entries = (map->l_info[DT_PLTRELSZ]->d_un.d_val
                                / sizeof (Elf32_Rela));
      Elf32_Word rel_offset_words = PLT_DATA_START_WORDS (num_plt_entries);
      Elf32_Word data_words = (Elf32_Word) (plt + rel_offset_words);
      Elf32_Word size_modified;

      extern void _dl_runtime_resolve (void);
      extern void _dl_prof_resolve (void);

      /* Convert the index in r11 into an actual address, and get the
        word at that address.  */
      plt[PLT_LONGBRANCH_ENTRY_WORDS] = OPCODE_ADDIS_HI (11, 11, data_words);
      plt[PLT_LONGBRANCH_ENTRY_WORDS + 1] = OPCODE_LWZ (11, data_words, 11);

      /* Call the procedure at that address.  */
      plt[PLT_LONGBRANCH_ENTRY_WORDS + 2] = OPCODE_MTCTR (11);
      plt[PLT_LONGBRANCH_ENTRY_WORDS + 3] = OPCODE_BCTR ();

      if (lazy)
       {
         Elf32_Word *tramp = plt + PLT_TRAMPOLINE_ENTRY_WORDS;
         Elf32_Word dlrr = (Elf32_Word)(profile
                                    ? _dl_prof_resolve
                                    : _dl_runtime_resolve);
         Elf32_Word offset;

         if (profile && GLRO(dl_profile) != NULL
             && _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;

         /* For the long entries, subtract off data_words.  */
         tramp[0] = OPCODE_ADDIS_HI (11, 11, -data_words);
         tramp[1] = OPCODE_ADDI (11, 11, -data_words);

         /* Multiply index of entry by 3 (in r11).  */
         tramp[2] = OPCODE_SLWI (12, 11, 1);
         tramp[3] = OPCODE_ADD (11, 12, 11);
         if (dlrr <= 0x01fffffc || dlrr >= 0xfe000000)
           {
             /* Load address of link map in r12.  */
             tramp[4] = OPCODE_LI (12, (Elf32_Word) map);
             tramp[5] = OPCODE_ADDIS_HI (12, 12, (Elf32_Word) map);

             /* Call _dl_runtime_resolve.  */
             tramp[6] = OPCODE_BA (dlrr);
           }
         else
           {
             /* Get address of _dl_runtime_resolve in CTR.  */
             tramp[4] = OPCODE_LI (12, dlrr);
             tramp[5] = OPCODE_ADDIS_HI (12, 12, dlrr);
             tramp[6] = OPCODE_MTCTR (12);

             /* Load address of link map in r12.  */
             tramp[7] = OPCODE_LI (12, (Elf32_Word) map);
             tramp[8] = OPCODE_ADDIS_HI (12, 12, (Elf32_Word) map);

             /* Call _dl_runtime_resolve.  */
             tramp[9] = OPCODE_BCTR ();
           }

         /* Set up the lazy PLT entries.  */
         offset = PLT_INITIAL_ENTRY_WORDS;
         i = 0;
         while (i < num_plt_entries && i < PLT_DOUBLE_SIZE)
           {
             plt[offset  ] = OPCODE_LI (11, i * 4);
             plt[offset+1] = OPCODE_B ((PLT_TRAMPOLINE_ENTRY_WORDS + 2
                                    - (offset+1))
                                   * 4);
             i++;
             offset += 2;
           }
         while (i < num_plt_entries)
           {
             plt[offset  ] = OPCODE_LIS_HI (11, i * 4 + data_words);
             plt[offset+1] = OPCODE_LWZU (12, i * 4 + data_words, 11);
             plt[offset+2] = OPCODE_B ((PLT_TRAMPOLINE_ENTRY_WORDS
                                    - (offset+2))
                                   * 4);
             plt[offset+3] = OPCODE_BCTR ();
             i++;
             offset += 4;
           }
       }

      /* Now, we've modified code.  We need to write the changes from
        the data cache to a second-level unified cache, then make
        sure that stale data in the instruction cache is removed.
        (In a multiprocessor system, the effect is more complex.)
        Most of the PLT shouldn't be in the instruction cache, but
        there may be a little overlap at the start and the end.

        Assumes that dcbst and icbi apply to lines of 16 bytes or
        more.  Current known line sizes are 16, 32, and 128 bytes.
        The following gets the __cache_line_size, when available.  */

      /* Default minimum 4 words per cache line.  */
      int line_size_words = 4;

      if (lazy && __cache_line_size != 0)
       /* Convert bytes to words.  */
       line_size_words = __cache_line_size / 4;

      size_modified = lazy ? rel_offset_words : 6;
      for (i = 0; i < size_modified; i += line_size_words)
        PPC_DCBST (plt + i);
      PPC_DCBST (plt + size_modified - 1);
      PPC_SYNC;

      for (i = 0; i < size_modified; i += line_size_words)
        PPC_ICBI (plt + i);
      PPC_ICBI (plt + size_modified - 1);
      PPC_ISYNC;
    }

  return lazy;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static Elf32_Addr elf_machine_fixup_plt ( struct link_map map,
lookup_t  t,
const Elf32_Rela reloc,
Elf32_Addr reloc_addr,
Elf64_Addr  finaladdr 
) [inline, static]

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

{
  if (map->l_info[DT_PPC(GOT)] == 0)
    /* Handle old style PLT.  */
    return __elf_machine_fixup_plt (map, reloc, reloc_addr, finaladdr);

  *reloc_addr = finaladdr;
  return finaladdr;
}

Here is the call graph for this function:

static int elf_machine_matches_host ( const Elf32_Ehdr ehdr) [inline, static]

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

{
  return ehdr->e_machine == EM_PPC;
}
static Elf32_Addr elf_machine_plt_value ( struct link_map map,
const Elf32_Rela reloc,
Elf32_Addr  value 
) [inline, static]

Definition at line 248 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 171 of file dl-machine.h.

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

  if (map->l_info[DT_PPC(GOT)] == 0)
    /* Handle old style PLT.  */
    return __elf_machine_runtime_setup (map, lazy, profile);

  /* New style non-exec PLT consisting of an array of addresses.  */
  map->l_info[DT_PPC(GOT)]->d_un.d_ptr += map->l_addr;
  if (lazy)
    {
      Elf32_Addr *plt, *got, glink;
      Elf32_Word num_plt_entries;
      void (*dlrr) (void);
      extern void _dl_runtime_resolve (void);
      extern void _dl_prof_resolve (void);

      if (__builtin_expect (!profile, 1))
       dlrr = _dl_runtime_resolve;
      else
       {
         if (GLRO(dl_profile) != NULL
             &&_dl_name_match_p (GLRO(dl_profile), map))
           GL(dl_profile_map) = map;
         dlrr = _dl_prof_resolve;
       }
      got = (Elf32_Addr *) map->l_info[DT_PPC(GOT)]->d_un.d_ptr;
      glink = got[1];
      got[1] = (Elf32_Addr) dlrr;
      got[2] = (Elf32_Addr) map;

      /* Relocate everything in .plt by the load address offset.  */
      plt = (Elf32_Addr *) D_PTR (map, l_info[DT_PLTGOT]);
      num_plt_entries = (map->l_info[DT_PLTRELSZ]->d_un.d_val
                      / sizeof (Elf32_Rela));

      /* If a library is prelinked but we have to relocate anyway,
        we have to be able to undo the prelinking of .plt section.
        The prelinker saved us at got[1] address of .glink
        section's start.  */
      if (glink)
       {
         glink += map->l_addr;
         while (num_plt_entries-- != 0)
           *plt++ = glink, glink += 4;
       }
      else
       while (num_plt_entries-- != 0)
         *plt++ += map->l_addr;
    }
  return lazy;
}

Here is the call graph for this function:

ElfW ( Addr  )

Variable Documentation

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