Blame elf/dl-sym-post.h

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