Blame elf/dl-sym-post.h

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