Blame elf/dl-sym-post.h

Packit Service efe454
/* Post-processing of a symbol produced by dlsym, dlvsym.
Packit Service efe454
   Copyright (C) 1999-2020 Free Software Foundation, Inc.
Packit Service efe454
   This file is part of the GNU C Library.
Packit Service efe454
Packit Service efe454
   The GNU C Library is free software; you can redistribute it and/or
Packit Service efe454
   modify it under the terms of the GNU Lesser General Public
Packit Service efe454
   License as published by the Free Software Foundation; either
Packit Service efe454
   version 2.1 of the License, or (at your option) any later version.
Packit Service efe454
Packit Service efe454
   The GNU C Library is distributed in the hope that it will be useful,
Packit Service efe454
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service efe454
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service efe454
   Lesser General Public License for more details.
Packit Service efe454
Packit Service efe454
   You should have received a copy of the GNU Lesser General Public
Packit Service efe454
   License along with the GNU C Library; if not, see
Packit Service efe454
   <https://www.gnu.org/licenses/>.  */
Packit Service efe454
Packit Service efe454
Packit Service efe454
/* Return the link map containing the caller address.  */
Packit Service efe454
static struct link_map *
Packit Service efe454
_dl_sym_find_caller_link_map (ElfW(Addr) caller)
Packit Service efe454
{
Packit Service efe454
  struct link_map *l = _dl_find_dso_for_object (caller);
Packit Service efe454
  if (l != NULL)
Packit Service efe454
    return l;
Packit Service efe454
  else
Packit Service efe454
    /* If the address is not recognized the call comes from the main
Packit Service efe454
       program (we hope).  */
Packit Service efe454
    return GL(dl_ns)[LM_ID_BASE]._ns_loaded;
Packit Service efe454
}
Packit Service efe454
Packit Service efe454
/* Translates RESULT, *REF, VALUE into a symbol address from the point
Packit Service efe454
   of view of MATCH.  Performs IFUNC resolution and auditing if
Packit Service efe454
   necessary.  If MATCH is NULL, CALLER is used to determine it.  */
Packit Service efe454
static void *
Packit Service efe454
_dl_sym_post (lookup_t result, const ElfW(Sym) *ref, void *value,
Packit Service efe454
              ElfW(Addr) caller, struct link_map *match)
Packit Service efe454
{
Packit Service efe454
  /* Resolve indirect function address.  */
Packit Service efe454
  if (__glibc_unlikely (ELFW(ST_TYPE) (ref->st_info) == STT_GNU_IFUNC))
Packit Service efe454
    {
Packit Service efe454
      DL_FIXUP_VALUE_TYPE fixup
Packit Service efe454
        = DL_FIXUP_MAKE_VALUE (result, (ElfW(Addr)) value);
Packit Service efe454
      fixup = elf_ifunc_invoke (DL_FIXUP_VALUE_ADDR (fixup));
Packit Service efe454
      value = (void *) DL_FIXUP_VALUE_CODE_ADDR (fixup);
Packit Service efe454
    }
Packit Service efe454
Packit Service efe454
#ifdef SHARED
Packit Service efe454
  /* Auditing checkpoint: we have a new binding.  Provide the
Packit Service efe454
     auditing libraries the possibility to change the value and
Packit Service efe454
     tell us whether further auditing is wanted.  */
Packit Service efe454
  if (__glibc_unlikely (GLRO(dl_naudit) > 0))
Packit Service efe454
    {
Packit Service efe454
      const char *strtab = (const char *) D_PTR (result,
Packit Service efe454
                                                 l_info[DT_STRTAB]);
Packit Service efe454
      /* Compute index of the symbol entry in the symbol table of
Packit Service efe454
         the DSO with the definition.  */
Packit Service efe454
      unsigned int ndx = (ref - (ElfW(Sym) *) D_PTR (result,
Packit Service efe454
                                                     l_info[DT_SYMTAB]));
Packit Service efe454
Packit Service efe454
      if (match == NULL)
Packit Service efe454
        match = _dl_sym_find_caller_link_map (caller);
Packit Service efe454
Packit Service efe454
      if ((match->l_audit_any_plt | result->l_audit_any_plt) != 0)
Packit Service efe454
        {
Packit Service efe454
          unsigned int altvalue = 0;
Packit Service efe454
          struct audit_ifaces *afct = GLRO(dl_audit);
Packit Service efe454
          /* Synthesize a symbol record where the st_value field is
Packit Service efe454
             the result.  */
Packit Service efe454
          ElfW(Sym) sym = *ref;
Packit Service efe454
          sym.st_value = (ElfW(Addr)) value;
Packit Service efe454
Packit Service efe454
          for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
Packit Service efe454
            {
Packit Service efe454
              struct auditstate *match_audit
Packit Service efe454
                = link_map_audit_state (match, cnt);
Packit Service efe454
              struct auditstate *result_audit
Packit Service efe454
                = link_map_audit_state (result, cnt);
Packit Service efe454
              if (afct->symbind != NULL
Packit Service efe454
                  && ((match_audit->bindflags & LA_FLG_BINDFROM) != 0
Packit Service efe454
                      || ((result_audit->bindflags & LA_FLG_BINDTO)
Packit Service efe454
                          != 0)))
Packit Service efe454
                {
Packit Service efe454
                  unsigned int flags = altvalue | LA_SYMB_DLSYM;
Packit Service efe454
                  uintptr_t new_value
Packit Service efe454
                    = afct->symbind (&sym, ndx,
Packit Service efe454
                                     &match_audit->cookie,
Packit Service efe454
                                     &result_audit->cookie,
Packit Service efe454
                                     &flags, strtab + ref->st_name);
Packit Service efe454
                  if (new_value != (uintptr_t) sym.st_value)
Packit Service efe454
                    {
Packit Service efe454
                      altvalue = LA_SYMB_ALTVALUE;
Packit Service efe454
                      sym.st_value = new_value;
Packit Service efe454
                    }
Packit Service efe454
                }
Packit Service efe454
Packit Service efe454
              afct = afct->next;
Packit Service efe454
            }
Packit Service efe454
Packit Service efe454
          value = (void *) sym.st_value;
Packit Service efe454
        }
Packit Service efe454
    }
Packit Service efe454
#endif
Packit Service efe454
  return value;
Packit Service efe454
}